• java泛型编程


         一般的类和方法都是针对特定数据类型的,当写一个对多种数据类型都适用的类和方法时就需要使用泛型编程,java的泛型编程类似于C++中的模板,即一种参数化类型的编程方法,具体地说就是将和数据类型相关的信息抽象出来,主要提供通用的实现和逻辑,和数据类型相关的信息由使用时参数决定

    一.泛型类:

    • 栈的实现

    示例代码:

    package com.genericity;
    
    import org.junit.Test;
    
    /**
    * @Title: LinkedListStack.java 
    * @Package com.genericity 
    * @Description: 编写一个泛型栈(链表式)
    * @author lky 
    * @date 2015年10月17日 下午8:34:07 
    * @version V1.0
     */
    public class LinkedListStack<T> {
        
        /**
        * @Title: LinkedListStack.java 
        * @Package com.genericity 
        * @Description:定义栈中的节点类型
        * @author lky 
        * @date 2015年10月17日 下午8:38:51 
        * @version V1.0
         */
        private static class Node<U>{
            U item;
            Node<U> next;
            
            Node(){
                this.item=null;
                this.next=null;
            }
            Node(U item,Node<U>next){
                this.item=item;
                this.next=next;
            }
            
            boolean isEmpty(){
                return item==null && next==null;
            }
            
        }
        
        private Node<T> top=new Node<T>();//栈顶指针
        
        public void push(T item){  //入栈
            top=new Node<T>(item,top);
        }
        
        public T pop(){    //出栈
            T result=top.item;
            if(!top.isEmpty()){
                top=top.next;
            }
            return result;
        }
        
        
    }

    测试:

    package com.genericity;
    
    import org.junit.Test;
    
    public class testLinkedListStack {
        @Test
        public void testPush(){
            LinkedListStack<String> aLinkedListStack=new LinkedListStack<String>();
            aLinkedListStack.push("lky");
            aLinkedListStack.push("aaaa");
            String res=aLinkedListStack.pop();
            while(res!=null){
                System.out.println(res);
                res=aLinkedListStack.pop();
            }
        }
    }

    二.泛型方法:

    package com.genericity;
    
    import java.util.ArrayList;
    import java.util.Date;
    
    import org.junit.Test;
    
    public class GenericMethods  {
        
        /**
        * @Title: getType 
        * @Description: 返回任意数组的数据类型
        * @param item
         */
        public <T> String getType(T item){
            return item.getClass().getName();
        }
        
        @Test
        public void test(){
            System.out.println(new GenericMethods().getType(new Date()));
            System.out.println(new GenericMethods().getType(1));
            System.out.println(new GenericMethods().getType("lky"));
            System.out.println(new GenericMethods().getType(new ArrayList<String>()));
        }
    }

    三.泛型集合:

    1. java容器默认存放Object类型对象,如果一个容器中即存放有A类型对象,又存放有B类型对象,如果用户将A对象和B对象类型弄混淆,则容易产生转换错误,会发生类型转换异常。
    2. 如果用户不知道集合容器中元素的数据类型,同样也可能会产生类型转换异常。

         鉴于上述的问题,java5中引入了泛型机制,在定义集合容器对象时显式指定其元素的数据类型,在使用集合容器时,编译器会检查数据类型是否和容器指定的数据类型相符合,如果不符合在无法编译通过,从编译器层面强制保证数据类型安全。

    示例代码:

    package com.genericity;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    import java.util.Queue;
    import java.util.Set;
    
    import org.junit.Test;
    
    public class New {
    
        public <k, v> Map<k, v> map() {
            return new HashMap<k, v>();
        }
    
        public <T> List<T> list() {
            return new ArrayList<T>();
        }
    
        public <T> LinkedList<T> linkList() {
            return new LinkedList<T>();
        }
    
        public <T> Set<T> set() {
            return new HashSet<T>();
        }
    
        public <T> Queue<T> queue() {
            return new LinkedList<T>();
        }
        
        @Test
        public void test(){
            New new1=new New();
            Map<String, LinkedList<String>> lisMap=new1.map();
        }
    }
    • 数学中集合的实现

    代码实现:

    package com.genericity;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.junit.Test;
    
    
    public class Sets {
        
        /**
        * @Title: union 
        * @Description: 集合的并集
        * @throws
         */
        public static <T> Set<T> union(Set<T> a,Set<T> b){
            Set<T> set=new HashSet<T>(a);
            set.addAll(b);
            return set;
        }
        
        /**
        * @Title: intersetion 
        * @Description: 集合交集
         */
        public static <T> Set<T> intersetion(Set<T>a,Set<T> b){
            Set<T> set=new HashSet<T>(a);
            set.retainAll(b);
            return set;
            
        }
        /**
        * @Title: difference 
        * @Description: 集合差集
         */
        public static <T> Set<T> difference(Set<T>a, Set<T> b){
            Set<T> set=new HashSet<T>(a);
            set.removeAll(b);
            return set;
        }
        
        public static <T> Set<T> complement(Set<T>a,Set<T> b){
           return  difference(union(a, b), intersetion(a, b));
        }
        
        
        @Test
        public void test(){
            HashSet<Integer> a=new HashSet<Integer>();
            HashSet<Integer> b=new HashSet<Integer>();
            for(int i=0;i<8;++i){
                if(i<5)a.add(i);
                if(i>2) b.add(i); 
            }
            
            System.out.println(union(a, b).toString());
            System.out.println(difference(a, b).toString());
            System.out.println(intersetion(a, b).toString());
            System.out.println(complement(a, b).toString());
        }
        
    }

    四.泛型边界

    上边界:

    • Java泛型编程中使用extends关键字指定泛型参数类型的上边界,即泛型只能适用于extends关键字后面类或接口的子类。
    • Java泛型编程的边界可以是多个,使用如<T extends A & B & C>语法来声明,其中只能有一个是类,并且只能是extends后面的第一个为类,其他的均只能为接口(和类/接口中的extends意义不同)。
    • 使用了泛型边界之后,泛型对象就可以使用边界对象中公共的成员变量和方法。

    下边界:

    • 通过T Super A限制了T元素只能是A的父类。

    五.泛型通配符

    • 泛型通配符”?”

    一个比较经典泛型通配符的例子如下:

    public class SampleClass < T extends S> {…}

    假如A,B,C,…Z这26个class都实现了S接口。我们使用时需要使用到这26个class类型的泛型参数。那实例化的时候怎么办呢?依次写下

    SampleClass<A> a = new SampleClass();

    SampleClass<B> a = new SampleClass();

    SampleClass<Z> a = new SampleClass();

    这显然很冗余,还不如使用Object而不使用泛型,使用通配符非常方便:

    SampleClass<? Extends S> sc = newSampleClass();

    六.无边界的通配符

    • 泛型的通配符也可以不指定边界,没有边界的通配符意思是不确定参数的类型,编译时泛型檫除类型信息,认为是Object类型
    • List和List<?>的区别是:List是一个原始类型的List,它可以存放任何Object类型的对象,不需要编译时类型检查。List<?>等价于List<Object>,它不是一个原始类型的List,它存放一些特定类型,只是暂时还不确定是什么类型,需要编译时类型检查。因此List的效率要比List<?>高。
    • 具体讲解见http://blog.csdn.net/chjttony/article/details/6801406
  • 相关阅读:
    Best Time to Buy and Sell Stock
    Remove Nth Node From End of List
    Unique Paths
    Swap Nodes in Pairs
    Convert Sorted Array to Binary Search Tree
    Populating Next Right Pointers in Each Node
    Maximum Subarray
    Climbing Stairs
    Unique Binary Search Trees
    Remove Duplicates from Sorted Array
  • 原文地址:https://www.cnblogs.com/dmir/p/4888542.html
Copyright © 2020-2023  润新知