专栏名称: java那些事
分享java开发中常用的技术,分享软件开发中各种新技术的应用方法。每天推送java技术相关或者互联网相关文章。关注“java那些事”,让自己做一个潮流的java技术人!《java程序员由笨鸟到菜鸟》系列文章火热更新中。
目录
相关文章推荐
51好读  ›  专栏  ›  java那些事

Java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一

java那些事  · 公众号  · Java  · 2019-03-13 11:50

正文

请到「今天看啥」查看全文


);

  • Generic generic3 = new Generic ( false );


  • Log .d( "泛型测试" , "key is " + generic.getKey());

  • Log .d( "泛型测试" , "key is " + generic1.getKey());

  • Log .d( "泛型测试" , "key is " + generic2.getKey());

  • Log .d( "泛型测试" , "key is " + generic3.getKey());

    1. D/泛型测试: key is 111111

    2. D/泛型测试: key is 4444

    3. D/泛型测试: key is 55.55

    4. D/泛型测试: key is false


    注意:

    • 泛型的类型参数只能是类类型,不能是简单类型。

    • 不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。


    1. if (ex_num instanceof Generic < Number >){

    2. }


    泛型接口

    泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中,可以看一个例子:


    1. //定义一个泛型接口

    2. public interface Generator {

    3. public T next();

    4. }


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


    1. /**

    2. * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中

    3. * 即:class FruitGenerator implements Generator {

    4. * 如果不声明泛型,如:class FruitGenerator implements Generator ,编译器会报错:"Unknown class"

    5. */

    6. class FruitGenerator implements Generator {

    7. @Override

    8. public T next() {

    9. return null ;

    10. }

    11. }


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


    1. /**

    2. * 传入泛型实参时:

    3. * 定义一个生产器实现这个接口,虽然我们只创建了一个泛型接口Generator

    4. * 但是我们可以为T传入无数个实参,形成无数种类型的Generator接口。

    5. * 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型

    6. * 即:Generator ,public T next();中的的T都要替换成传入的String类型。

    7. */

    8. public class FruitGenerator implements Generator < String > {


    9. private String [] fruits = new String []{ "Apple" , "Banana" , "Pear" };


    10. @Override

    11. public String next() {

    12. Random rand = new Random ();

    13. return fruits[rand.nextInt( 3 )];

    14. }

    15. }


    泛型通配符

    我们知道Ingeter是Number的一个子类,同时在特性章节中我们也验证过Generic 与Generic 实际上是相同的一种基本类型。那么问题来了,在使用Generic 作为形参的方法中,能否使用Generic 的实例传入呢?在逻辑上类似于Generic 和Generic 是否可以看成具有父子关系的泛型类型呢?

    为了弄清楚这个问题,我们使用Generic 这个泛型类继续看下面的例子:


    1. public void showKeyValue1( Generic < Number > obj){

    2. Log .d( "泛型测试" , "key value is " + obj.getKey());

    3. }

    1. Generic < Integer > gInteger = new Generic < Integer >( 123 );

    2. Generic < Number > gNumber = new Generic < Number >( 456 );


    3. showKeyValue(gNumber);


    4. // showKeyValue这个方法编译器会为我们报错:Generic

    5. // cannot be applied to Generic

    6. // showKeyValue(gInteger);


    通过提示信息我们可以看到Generic 不能被看作为`Generic 的子类。由此可以看出:同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。

    回到上面的例子,如何解决上面的问题?总不能为了定义一个新的方法来处理Generic 类型的类,这显然与java中的多台理念相违背。因此我们需要一个在逻辑上可以表示同时是Generic 和Generic 父类的引用类型。由此类型通配符应运而生。

    我们可以将上面的方法改一下:


    1. public void showKeyValue1( Generic obj){

    2. Log .d( "泛型测试" , "key value is " + obj.getKey());

    3. }


    类型通配符一般是使用?代替具体的类型实参,注意了,此处’?’是类型实参,而不是类型形参 。重要说三遍!此处’?’是类型实参,而不是类型形参 ! 此处’?’是类型实参,而不是类型形参 !再直白点的意思就是,此处的?和Number、String、Integer一样都是一种实际的类型,可以把?看成所有类型的父类。是一种真实的类型。

    可以解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。

    泛型方法

    在java中,泛型类的定义非常简单,但是泛型方法就比较复杂了。

    尤其是我们见到的大多数泛型类中的成员方法也都使用了泛型,有的甚至泛型类中也包含着泛型方法,这样在初学者中非常容易将泛型方法理解错了。

    泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。


    1. /**







    请到「今天看啥」查看全文