泛型(Generics)

泛型(Generics)
    
  1)泛型的定义
        
    泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type),也就是说
所操作的数据类型被
    指定为一个参数,在用到的时候在指定具体的类型。
        
    这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。
        
    泛型的类型将来传入是只能是引用类型的,不能是基本类型的。
        
    例如:
            //编译通过
            
    List<String>
            
    List<Action>
            
    List<Integer>
            
    List<Integer[]>
            
    List<int[]>

            
    //编译报错
            
    List<int>

    
  2)java中的泛型只是在编辑期间起作用的,在运行时会把泛型信息擦除的。
        
    只是在编译期间启动类型安全检查的作用,运行时不起作用。
        
    例如:List<String> list = new ArrayList<String>();
        
    虽然指定了泛型为String,但是在运行时候依然是可以向该list中存放其他类型数据的。(比如使用反射的方法)
        
        
    //类中写了如下俩个方法编译会报错,因为编译后这俩个是相同的俩个方法
        
    public void test(List<String> list){
        }
        
        
    public void test(List<Long> list){
        }

    
  3)泛型类
        
    一个泛型类就是具有一个或多个类型变量(把类型参数化)的类。
        
    定义一个泛型类十分简单,只需要在类名后面加上<>,再在里面加上类型参数.
        
        
    注:类型变量使用大写形式,且比较短,这是很常见的。在JDK中,使用变量E表示集合的元素类型
        
    ,K和V分别表示关键字与值的类型。(需要时还可以用其他的字母,也可以是一个或多个字母)

        
    例如:
        //这里的T是根据将来用户使用Point类的时候所传的类型来定
        
    //Point<Double> p = new Point<Double>();
        
    public class Point<T> {
            
      private T x;
            
      private T y;
            
      public T getX() {
                
        return x;
            
      }
            
      public void setX(T x) {
                
        this.x = x;
            
      }
            
      public T getY() {
                
        return y;
            
      }
            
      public void setY(T y) {
                
        this.y = y;
            
      }
        
    }

        
    例如:
        
    //这里的T和S是根据将来用户使用Point类的时候所传的类型来定
        
    //Point<String,Integer> p = new Point<String,Integer>();
        
    public class Point<T,S> {
            
      private T x;
            
      private S y;
            
      public T getX() {
                
        return x;
            
      }
            
      public void setX(T x) {
                
        this.x = x;
            
      }
            
      public S getY() {
                
        return y;
            
      }
            
      public void setY(S y) {
                
        this.y = y;
            
      }
        
    }
    
    
    
  4)泛型接口
        
    一个泛型接口就是具有一个或多个类型变量的接口。
        
    例如:
        
    public interface Action<T,U>{  
            
      void doSomeThing(T t,U u);  
        
    }  

        
    public class ActionTest implements Action<String,Date>{  
            
      public void doSomeThing(String str,Date date) {  
                
        System.out.println(str);  
                
        System.out.println(date);  
            
      }  
        
    }  


    
  5)泛型方法
        
    在方法上直接声明泛型,该方法就是泛型方法
        
    例如:
        
    public class Test{
            
      public <T> void run1(T t){
            
            
      }

            
      public <T> T run2(T t){
                
        return t;
            
      }

            
      public <T,S> void run3(T t,S s){
        
            
      }
        
    }


    
  6)通配符
        
    泛型增加了java中类型的复杂性,例如List<String>、List<Integer>、List<Object>等这些都是不同的类型。
        
        
    //编译报错
        
    //虽然 List list = new ArrayList(); 是正确的
        
    //虽然 Object是String的父类型
        
    //但是下面代码编译时报错的,因为使用了泛型
        
    List<Object> list = new ArrayList<String>();

        
    泛型中?是通配符,它可以表示所有泛型的父类型:
        
    List<?> list = new ArrayList<任意>();

        
    例如:
        
    //这时list可以指向任何泛型的List类型集合对象
        
    public void test(List<?> list){
            
    //编译报错,因为我们并不知道?到底代表什么类型
            
    list.add(1);
            
            
    //编译通过
            
    for(Object o:list){
                
      System.out.println(o);
            
      }
        
    }

        
    注:通配符?只能用在泛型变量声明的时候。

    
    
  7)泛型中的entends和super关键字
        
    在泛型中可以使用entends和super关键字来表示将来用户所传的泛型参数的上限和下限。
        
        
    entends关键字的使用:
        
    例如: 在声明泛型类和泛型接口时使用extends
        
    public class Point<T extends Number> {
            
      private T x;
            
      private T y;
        
    }

        
    public class Point<T extends Number,S> {
            
      private T x;
            
      private S y;
        
    }

        
    public interface Action<T extends Person> {
            
      public void doSomeThing(T t);
        
    }
        
        
    例如:在声明泛型方法时使用extends
        
    public <T extends Action> void run(T t){
        
        
    }

        
        
    例如:在声明泛型类型变量时使用extends
        
    List<? extends Number> list = new ArrayList<Integer>();
        
    List<? extends Number> list = new ArrayList<Long>();
        
    List<? extends Number> list = new ArrayList<Double>();
        
    //编译报错
        
    List<? extends Number> list = new ArrayList<String>();
        
    
    例如:
        
    public void test(List<? extends Number> list){
        
        
    }
        

        
    super关键字的使用:
        
    例如:
        
    //编译报错
        
    //声明泛型类或泛型接口时不能使用super
        
    public class Point<T super Number> {
    
        
    }
        
    public interface Action<T super Number> {
    
        
    }

        
    //编译报错
        
    //声明泛型方法时不能使用super
        
    public <T super Action> void run2(T t){
        
        
    }


        
    例如:在声明泛型类型变量时使用super
        
    //编译通过
        
    List<? super Number> list1 = new ArrayList<Object>();
        
    List<? super Student> list2 = new ArrayList<Object>();
        
    List<? super Student> list3 = new ArrayList<Person>();

        
    //编译通过
        
    public void test(List<? super Number> list){
        
        
    }
        
        
    //编译通过
        
    public void test(List<? super Student> list){
        
        
    }
        

    
  8)泛型中的&
        
    使用&可以给泛型加多个限定

        
    例如:
        
    public class A{
    
        
    }
        
    public inerface B{
            
        
    }
        
        
    //不管该限定是类还是接口,统一都使用关键字extends
        
    //可以使用&符号给出多个限定
        
    //如果限定既有接口也有类,那么类必须只有一个,并且放在首位置
        
    public class Point<T extends A&B> {
    
        
    }

        
    class Sub extends A implements B{}

        
    main:
            
    //编译报错
            
    Point<A> p = new Point<A>();
            
    Point<B> p = new Point<B>();
            
            
    //编译通过
            
    Point<Sub> p = new Point<Sub>();

猜你喜欢

转载自blog.csdn.net/bifuguo/article/details/81748277