JAVA 深入理解 泛型擦除类型信息

泛型类型信息被擦除

public class Erased<T> {
    private  final  int SIZE  = 100;
    public static void f(Object arg){
//        if(arg instanceof  T)		 	//error 
//            T[] array = new T[SIZE];	//error
    }
}

1.类型信息被擦除 不可进行实例类型的判断
2.类型信息被擦除 不可实例该种类型的数组

可以通过间接的方式获得当前实例类型

class Building{}
class  House extends  Building{}

public class ClassTypeCapture<T> {
    Class<T> kind;
    public ClassTypeCapture(Class<T> kind) {
        this.kind = kind;
    }
    public  boolean Instanceof(Object obj){
        return  kind.isInstance(obj); //判断是否为当前类的实例
    }
    public  static void main(String []argv){
        ClassTypeCapture<Building> ctc = new ClassTypeCapture<Building>(Building.class);
        System.out.println(ctc.Instanceof(new House()));
    }
}

同在该方式来判断当前的实例类型 通过 Class.IsInstance判断类型

泛型创建对象

class ClassAsFactory<T>{
    private  T x;
    public ClassAsFactory(Class<T> kind) {
        try {
            x = kind.newInstance();
        } catch (Exception e) {
            throw  new RuntimeException(e);
        }
    }
}
class Employee{}

public class InstantiateCenericType {
    public  static void main(String []args){
        ClassAsFactory<Employee> ecf = new ClassAsFactory<>(Employee.class); //OK
        System.out.println("ClassFactory create success!");
        try{
            ClassAsFactory<Integer> ecf1 = new ClassAsFactory<Integer>(Integer.class); //error
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

** 使用这种方式虽然可以创建对象但是不符合规范,逻辑不够优雅 (SUN公司不推荐)**

优雅方式一

interface  FactoryI<T>{
    T create();
}

class Foo2<T>{
    private  T x;
    public <F extends FactoryI<T>> Foo2(F factory){
        x = factory.create();
    }
}

class IntegerFactory implements FactoryI<Integer>{

    @Override
    public Integer create() {
        return new Integer(0);
    }
}

class  Widget{
    public  static  class Factory implements FactoryI<Widget>{

        @Override
        public Widget create() {
            return new Widget();
        }
    }
}

public class FactoryConsraint {
    public static void main(String [] argv){
        new Foo2<Integer>(new IntegerFactory());
        new Foo2<Widget>(new Widget.Factory());
    }
}

优雅方式二

abstract class GenericWithCreate<T>{
    final T element;
    public GenericWithCreate(){ element = create(); } //第二步
    abstract T create();
}

class X{}

class Creator extends  GenericWithCreate<X>{
    @Override
    X create() { 	//第三步
        return new X();
    }

    public  void f(){	//第四步
        System.out.println(element.getClass().getSimpleName());
    }
}
public class CreateGeneric {
    public static void main(String []argc){
        Creator c = new Creator();	//第一步
        c.f();	//第五步
    }
}

创建泛型数组

创建数组最菜的方式

import java.util.ArrayList;
import java.util.List;

public class ListOfGenerics<T> {
    private List<T> array = new ArrayList<>();
    public void add(T item){array.add(item);}
    public T get(int index){return array.get(index);}
}

创建指针数组

public class ArrayOfGeneric {
    static final int SIZE = 100;
    static Generic<Integer>[] gia;
    public static void main(String [] argv){
//        产生运行错误
//        gia = (Generic<Integer>[]) new Object[SIZE];
            gia = new Generic[SIZE];
            System.out.println(gia.getClass().getSimpleName());
            gia[0] = new Generic<Integer>();

    }
}

** 实例擦除类型信息的类型指针数组 再将实时的变量的引用添加进数组之中**

菜菜方法二

public class GenericArray<T> {
    private T[] array;

    public GenericArray(int sz) {
        array = (T[]) new Object[sz];
    }
    public void put(int index, T item){
        array[index] = item;
    }
    public T get(int index){
        return array[index];
    }
    public T[] rep(){
        return  array;
    }
    public static void main(String [] argv){
        GenericArray<Integer> gai = new GenericArray<Integer>(10);
        Object [] a = gai.rep();
        //Integer[] b = gai.rep(); //error 不是继承类 无法实现转换

    }
}

菜菜方式三

public class GenericArray2<T> {
    private Object[] array;

    public GenericArray2(int sz) {
        array = new Object[sz];
    }
    public void put(int index, T item){
        array[index] = item;
    }
    public T get(int index){
        return (T)array[index];
    }
    public T[] rep(){
        return (T[]) array;
    }
    public static void main(String [] argv){
        GenericArray2<Integer> gai = new GenericArray2<Integer>(10);
        Object [] a = gai.rep();

        for (int i = 0; i< 10; i++){ gai.put(i, i); }
        for (int i = 0; i< 10; i++){
            Integer j;
            j = gai.get(i);
            System.out.printf(" " + j);
        }

//        Integer[] b = gai.rep(); // error  但是此处依旧不可 无可推翻底层的数组类型

    }
}

**无法直接推翻底层的数组类型 转换思路: 通过反射从底层直接构建 **

这个稍稍好一点

import java.lang.reflect.Array;

public class GenericArrayWithTypeToken<T> {
    private T[] array;

    public GenericArrayWithTypeToken(Class<T> type, int size) {
        array= (T[]) Array.newInstance(type, size);
    }
    public void put(int index, T item){
        array[index] = item;
    }
    public T get(int index){
        return array[index];
    }
    public T[] rep(){
        return array;
    }
    public static void main(String [] argv){
        GenericArrayWithTypeToken<Integer> gai = new GenericArrayWithTypeToken<Integer>(Integer.class,10);
        Object [] a = gai.rep();

        for (int i = 0; i< 10; i++){ gai.put(i, i); }
        for (int i = 0; i< 10; i++){
            Integer j;
            j = gai.get(i);
            System.out.printf(" " + j);
        }

        Integer[] b = gai.rep(); 
        for(int i : b){
            System.out.printf(" " + i);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值