JavaCore-泛型详解

版权声明:你天加练的全战攻城狮梦 https://blog.csdn.net/u010122604/article/details/87792951

分类:
泛型类
泛型接口
泛型方法

泛型类:

public class ArrayList<E> extends AbstractList<E> 
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    
    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return ArrayList.this.elementData(offset + index);
    }
    
    //...省略掉其他具体的定义过程

}

泛型接口:

public interface List<E> extends Collection<E> {

    int size();

    boolean isEmpty();

    boolean contains(Object o);

    Iterator<E> iterator();

    Object[] toArray();

    <T> T[] toArray(T[] a);

    boolean add(E e);

    boolean remove(Object o);

    boolean containsAll(Collection<?> c);

    boolean addAll(Collection<? extends E> c);

    boolean addAll(int index, Collection<? extends E> c);

    boolean removeAll(Collection<?> c);

    boolean retainAll(Collection<?> c);

    void clear();

    boolean equals(Object o);

    int hashCode();

    E get(int index);

    E set(int index, E element);

    void add(int index, E element);

    E remove(int index);

    int indexOf(Object o);

    int lastIndexOf(Object o);

    ListIterator<E> listIterator();

    ListIterator<E> listIterator(int index);

    List<E> subList(int fromIndex, int toIndex);
}

泛型方法:
在调用方法的时候,已经指明泛型方法的具体类型

    public <T> T showKeyName(Generic<T> container){
        System.out.println("container key :" + container.getKey());
        //当然这个例子举的不太合适,只是为了说明泛型方法的特性。
        T test = container.getKey();
        return test;
    }

这才是一个泛型方法,首先在public与返回值之间必不可少,表明这是一个泛型方法,并且声明了泛型T,这个T可以出现在泛型方法的任意位置

泛型的引用 可以 把使用Object的错误提前到编译后,而不是运行后,提升安全性

类型擦除:
Java虚拟机中不存在泛型,泛型只是为了完善Java体系,增加程序员编程的便捷性以及安全性而创建的一种机制,在Java虚拟机中对应的泛型都是确定的类型。
Java虚拟机会把这些泛型参数类型都擦除,用相应的确定类型来代替,这个动作叫做类型擦除,用于代替的类型成为原始类型,在类型擦除过程中,一般使用第一个限定的类型来替换,若无限定则使用Object。

class Test<T>
{
    private T t;
    public void show(T t)
    {

    }
}

虚拟机进行翻译后的原始类型

class Test
{
    private Object t;
    public void show(Object t)
    {
        
    }
}

泛型类(带限定类型)代码:

class Test<? extends Comparable>
{
    private T t;
    public void show(T t)
    {

    }
}

虚拟机进行翻译后的原始类型:

class Test
{
    private Comparable t;
    public void show(Comparable t)
    {
        
    }
}

泛型类的翻译

class Test<T>
{
    private T t;
    public void show(T t)
    {

    }
}

class TestDemo extends Test<String>
{
    private String t;
    public void show(String t)
    {
        
    }
}

如果泛型类型的类型变量没有限定,那么就用Object作为原始类型
如果有限定()就用XClass作为原始类型
如果有多个限定(<T extends XClass1&XClass2>)就用第一个边界的限定类型XCLass1类作为原始类型。

由于TestDemo继承了Test,但是Test在类型参数后还有一个public void show(Object t),这和那个show(String t)出现重载,但是本意确实没有show(Object t)的
因此在虚拟机翻译泛型方法中,引入了桥方法,及在类型擦除后的show(Object t)中调用另一个方法,从而达到子类覆盖父类的方法,这种操作只有JVM才可以实现

public void show(Object t)
{
    show((String) t);
}

类型限定
? extends SomeClass 这种限定,说明的是只能接收SomeClass及其子类类型,所谓的“上限”
? super SomeClass 这种限定,说明只能接收SomeClass及其父类类型,所谓的“下限”

public <T extends Comparable> shwo(T a, T b)
{
    int num = a.compareTo(b);
}

也可以有多重类型限定

<T extends Comparable & Serializable>

多种类型限定类型擦除机制

class Test<T extends Comparable & Serializable>
{
    private T lower;
    private T upper;

    public Test(T first, T second) //此处是利用Comparable的方法,因此把Comparable写在前边,类型擦除后为Comparable,若为Serializable,还得用强制类型转换,否则不能使用compareTo方法。
    {
        int a = first.compareTo(second);
        ...
    }
}

泛型误区:
泛型的类型必须是类的引用,不能是基本数据类型
不能创建参数化类型数组
不能实例化类型变量,以及不能出下泛型调用信息

T t = new T();
//或
T.Class

不能再静态域 or 方法中出现参数类型,但是可以使用静态泛型方法

class Test<T>
{
    private static T example;  //error 执行泛型静态变量
    public static void showExample() //error 在静态域中操作不能类型擦除的泛型
    {
        action about T...
    }
    public static T showExample() //error 静态泛型返回值
    {
        action about T....    
     }
}

//非泛型方法,和在静态方法中使用费静态参数是一样的,静态方法是先于对象而存在于内存中的,因此在编译的时候,T的类型无法确定,会抛出:
“Cannot make a static reference to a non_static reference”

//静态泛型方法是对的
    class Test<T>{
    public static <T> T show() {
            action
        }
    }

不能抛出or捕获泛型类的实例

try
{
    ....
}
catch(T e) //error
{
    ...
}

在异常规范中使用使用类型变量是允许的,一下方法是合法的:

public static<T extends throwable> void doWork(T t) throw T //ok
{
	try{
		do work;
	}catch(Throwable realCause){
		log;
	}
}

泛型类型中的方法冲突
由于类型擦除

public class Pair<T>{  
      public boolean equals(T value){  
            return (first.equals(value));  
      }  
}  

在类型擦书后与Object中额equals方法方法签名一样
出现Error

 【Error】    Name clash: The method equals(T) of type Pair<T> has the same erasure as equals(Object) of type Object but does not override it

猜你喜欢

转载自blog.csdn.net/u010122604/article/details/87792951