Java中泛型的详细解析,深入分析泛型的使用方式 (2)

当实现泛型接口的类,未传入泛型实参时:

/** * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中: * 即 class FruitGenerator<T> implements Generator<T> {} * 如果不声明泛型,比如: class FruitGenerator implements Generator<T>. 此时编译器会报错 - Unknown class */ class FruitGenerator<T> implements Generator<T> { @Override public T next() { return null; } }

当实现泛型接口的类,传入泛型实参时:

/** * 传入泛型实参时: * 定义一个生产器实现这个接口 * 尽管只创建了一个泛型接口Generator<T>,但是可以为T传入无数个实参,形成无数种类型的Generator接口 * 在实现类实现泛型接口时,如果已经将泛型类型传入实参类型,则所有使用泛型的地方动摇替换成传入的实参类型 * 即: Generator<T>, public T next(); 这里的T都要替换成传入的String类型 */ public class FruitGenerator implements Generator<String> { private String[] fruits = new String[]{"Apple", "Banana", "Pear"}; @Override public String next() { Random rand = new Random(); return fruits[rand.nextInt(3)]; } } 泛型通配符

Integernumber的一个子类 ,Generic< Integer >Generic< number > 实际上是相同的一种类型

由此,产生如下问题:

在使用Generic< number > 作为形参的方法中,能否使用Generic< Integer > 的实例传入?

在逻辑上类似于Generic< number >和Generic< Integer >是否可以看成是具有父子关系的泛型类型呢?

Generic< T >泛型类示例:

public void showKeyValue1(Generic<Number> obj) { Log.d("泛型测试", "key value is" + obj.getKey()); } Generic<Integer> gInteger = new Generic<Integer>(123); Generic<Number> gNumber = new Generic<Number>(456); showKeyValue(gNumber); showKeyValue这个方法编译器会报错: Generic<java.lang.Integer> cannot be applied to Generic<java.lang.Number> showKeyValue(gInteger);

由此可以看到Generic< Integer >不能看作是Generic< Number >的子类.

由此可见:

同一种泛型可以对应多个版本,因为参数类型是不确定的

不同版本的泛型类型实例是不兼容的

为了解决这样的问题,又不能为了定义一个新的方法来处理Generic< Integer >,这与Java中多态的理念违背.因此,需要一个在逻辑上可以表示同时是Generic< Integer >和Generic< Number >父类的引用类型.这样的类型就是类型通配符:

使用通配符表示泛型:

public void showKeyValueWildcard(Generic<?> obj) { Log.d("泛型测试", "key value is" + obj.getKey()); }

类型通配符一般使用 ? 代替具体的类型实参:

此处的 ?类型实参, 而不是类型形参.

和Number,String,Integer一样,都是一种实际的类型

可以把 ? 看作是所有类型的父类,是一种真实的类型

类型通配符的使用场景:

当具体类型不确定的时候,这个通配符就是 ?

当操作类型时,不需要使用类型的具体功能,只使用Object类中的功能,那么可以使用 ? 通配符来表示未知的类型

泛型方法

泛型类: 在实例化类的时候指明泛型的具体类型

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

/** * 泛型方法: * 1. public 和 返回值中间的 <T> 非常重要,可以理解为声明此方法为泛型方法 * 2. 只有声明了 <T> 的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法 * 3. <T> 表示该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T * 4. 与泛型类的定义一样,此处的T可以为任意标识,常见的比如: T, E, K, V等形式的参数常用于表示泛型 * * @param tClass 传入的泛型实参 * @return T 返回值为T类型 */ public <T> T genericMethod(Class<T> tClass) throws InstanttiationException, IllegalAccessException { T instance = tClass.newInstance(); return instance; } Object obj = genericMethod(Class.forName("com.oxford.test")); 泛型方法的基本用法

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzddxj.html