初入理解Java泛型

90 阅读2分钟

1、什么是泛型

泛型就是标签。容器要用标签标记一下,就是容器存储什么类型的数据。

ArrayList();

定义:把元素的类型设计出一个参数,这个类型参数叫泛型。Collection,List

这个就是类型参数,即泛型。

2、为什么要用泛型?

容器的默认类型是Object,那么标签的出现,是限制容器的类型。

有了泛型,这样集合就可以向数组学习。使元素更规范化。

3、泛型类、泛型接口、泛型方法

3.1、泛型类:

           类中的某个或某几个属性不确定类型的时候,可以采用泛型去约定该类型,这样通用型高。

public class Order<T> {T t;}
public class Emp<K,V> {}

3.2、泛型接口:

            接口中的某个或某几个属性不确定类型的时候,可以采用泛型去约定该类型,

这样通用型高。

public interface IUser<T> {T t;}
public interface IDept<K,V> {}

3.3、泛型方法:

           就是给当前方法定义泛型,和当前类没有关系。

public class User {
    public <E> List<E> copyArrToList(E[] arr){
        if (null == arr || arr.length == 0){           
            return Collections.EMPTY_LIST;        
        }        
        List<E> list = new ArrayList<>(arr.length);        
        for (E e : arr) {            
            list.add(e);        
        }        
        return list;    
    }
}

4、通配符的使用

类A是类B的父类, G 和 G 是没有关系的,两者的共同父类是 G<?>。

4.1、上届通配符

G<? extend Number> 

只允许泛型为Number及Number的子类的引用调用。

public class Person<T> { T t;}
public class SubPerson<T> extends Person<T>{}
public class Test{
    public static void main (String[] args){
        List<? extends Person> list = null;
        List<Person> list1 = null;
        List<SubPerson> list2 = null;
        List<Object> list3 = null;

        list = list1;
        list = list2;
        //list = list3; #这个编译报错
    }
}

G<? extend Comparable>

只允许泛型为实现Comparable接口的实现类的引用调用。

public interface IOrder<T> {T t ;}
public class IOrderImpl<T> implements IOrder<T> {}
public class Test{
    public static void main (String[] args){
        List<? extends IOrder> list = null;        
        List<IOrder> list1 = null;        
        List<IOrderImpl> list2 = null;        
        List<Object> list3 = null;

        list = list1;
        list = list2;
        //list = list3; #这个编译报错
    }
}

4.2、下届通配符

G<? super Number>

只允许泛型为Number及Number的父类的引用调用。

public class Person<T> { T t;}
public class SubPerson<T> extends Person<T>{}
public class Test{
    public static void main (String[] args){
        List<? super SubPerson> list = null;        
        List<Person> list1 = null;
        List<SubPerson> list2 = null;
        List<Object> list3 = null;

        list = list1;
        list = list2;
        //list = list3; #这个编译报错
    }
}

4.3、无界通配符

意味着可以使用任何对象,但它不能使用object类型。

5、泛型擦除

泛型信息只存在于编译前,编译后的字节码中是不包含泛型中的类型信息的。因此,编译器在编译时去掉类型参数,叫做类型擦除

例如 List<Integer>List<String>  等类型在编译之后都会变成 List。JVM看到的只是 List,而泛型信息对JVM来说是不可见的。

Class c1 = new ArrayList<String>().getClass(); 
Class c2 = new ArrayList<Integer>().getClass(); 
System.out.println(c1 == c2); // true