栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java:高级之泛型概念引入,泛型可以设置多个类型参数,泛型继承和泛型接口实现,限制泛型可用类型,泛型通配的方式,泛型方法,泛型方法限制泛型可用类型

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java:高级之泛型概念引入,泛型可以设置多个类型参数,泛型继承和泛型接口实现,限制泛型可用类型,泛型通配的方式,泛型方法,泛型方法限制泛型可用类型

目录页

        泛型简介

        泛型类

        限制泛型可用类型

        类型通配声明

        泛型方法

问题引入

        如果我们需要产生多个对象,每个对象的逻辑完全一样,只是对象内的成员变量的类型不同。那我们如何去做?

我们新建一个工程

做一个构造方法        public Cls1(int a){
                                        this.a =a;
                                            }

然后我们实例化这个方法的时候,给他传一个10        Cls1 cls1 = new Cls1(10);

然后我们输出cls1 里面的getData()                System.out.println(cls1.getData());

 运行结果

 同样的我们在做一个类,唯一的区别,所有的东西都一样,但是它a变成了        String a;

 运行结果

你会发现有两个类,这两个类的逻辑完全一样,所谓的逻辑就是里面的一些方法,包括构造方法,只是成员变量的类型不同

 那比如我们现在要做了double 类型的,是不是还得专门为double 创建一个类呀?

          

问题解决

        创建多个类文件,给每个类中的成员变量设置指定的数据类型

                缺点:这种方法会导致类的膨胀,重用性太差。

        创建一个类文件,给这个类中的成员变量设置Object数据类型。

                缺点:编译的时候正常,但运行的时候可能会异常

 创建多个类文件,给每个类中的成员变量设置指定的数据类型:

这样整个业务场景下来,整形一个,小数一个,字符一个,甚至里面会集成一些其他的类。

创建一个类文件,给这个类中的成员变量设置Object数据类型。:

我们会发现整形int ,打开它的类型继承

 你会发现Object是所有类型的父类

这种情况下我们完全可以把这两个删掉一个,

然后我们把Cls2改成Cls1        第21行

发现没写错,可是还报错        错误提示:     The constructor Cls1(int) is undefined

 发现是版本的问题

我们右击,然后选择properties

 然后看到JDK那行了嘛?

 

把对勾去掉

然后选择1.5版本往后的点击ok

 这个时候就没有报错了

 运行一下

 但是他有一个不太好的地方

这个Object导致整个类对这个变量的属性很模糊

可能会产生某些错误,

假如我现在输出“冰糖李子”,编码过程中误操作了,把“冰糖李子”这个字符串强制转换成整型数,你会发现编译的时候是ok 的

但是运行的时候会出现异常,类型转化异常

难免我们在操作过程中,随着代码量的增大,对里面的object的类型模糊不清晰,导致你程序员在编写代码的时候,做了一个误判,做了一个错误的转换,导致程序崩溃

面向于 这种情况发生,我们有一个非常好的解决办法,就是泛型

一、泛型简介        JDK1.5之后引入 

        泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的

        泛型的原理就是“类型的参数化”,即把类型看做参数。也就是说把所要操作的数据类型看做参数,就像方法的形式参数是运行时传递的值的占位符一样。

        简单的说,类型变量扮演的角色就如同一个参数,它提供给编译器用来类型检查的信息。

        泛型可以提高代码的扩展性和重用性

那么泛型怎么做?

示例----泛型类

        public  class GenClass{

                private   T  obj;

        

                public  GenClass(T   obj){

                        this.obj = obj;

                }         

                public  T  getobj(){

                        return obj;

                }

                public  void   setobj(T  obj){

                        this .obj  = obj;

                }

}

泛型的意思就是就是在class后面添加一个,用T去替代里面未名的数据类型

比如说我们的代码可以在Cls1后面加上,用一个T来表示

然后new 的时候要把这个东西用上,你在实例化的时候呈现,他是一个整形

Cls1 cls1= new Cls1(10);

同样使用cls2的时候,落地的时候,我让他都是字符串

Cls1 cls2 = new Cls1("冰糖李子");

 运行结果

我们用替代了刚才写的Object,在使用的时候,在程序员编码的过程当中,实例化类的时候,在<>里面,去告诉操作系统,包括程序员看代码的时候更具象的把他表达出来

这就叫做泛型

泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的

当你转换出现问题的时候,你硬要把string转化成Integer,他就会报错,

刚才我们用object的时候它没有任何的报错,

只是在程序运行的时候出现类型转换异常

(这就是泛型引入的除了程序员可读之外,还有个好处就是防止你的误操作,误转换)

Cannot cast from String to Integer

         泛型的原理就是“类型的参数化”,即把类型看做参数。也就是说把所要操作的数据类型看做参数,就像方法的形式参数是运行时传递的值的占位符一样。:

我们习惯了函数调用,习惯了传参public Cls1(T a),

那实际上类型也可以以参数的形式传过来,为了区别我们用来了<>

我们在这个类初始化,实例化的时候    Cls1 cls1= new Cls1(10);

我们直接把泛型类里面的,涉及到泛型的位置,用Integer替代进去

也就是说Cls1类里面的  a变量的的类型,        T a;

是根据我们真正实例化的时候,用<>的方式传参过去的,来确定里面a的类型

,同样的一个类,你在使用实例化的时候,给泛型传的类型不一样,这个类最后体现的结果也是不一样的

                                Cls1 cls1= new Cls1(10);
                                    System.out.println(cls1.getData());
                                    Cls1 cls2 = new Cls1("冰糖李子");
                                            System.out.println(cls2.getData());

 二、泛型类及特点

        1、泛型的类型参数可以是泛型类

        2、泛型类可以同时设置多个类型参数

        3、泛型类可以继承泛型类

        4、泛型类可以实现泛型接口

 泛型的类型参数可以是泛型类:

也就是说你这个除了普通变量Integer   和String 外,他也能接受是个泛型

泛型类可以继承泛型类:

跟我们普通类的继承是一样的,当然你泛型可以在继承过程中实现多个类型参数

你的父类型是个泛型,他里面只有一个,你完全可以除了,多一个 呀,等等。

一般我们泛型用的,不是写死的 ,就像形参的名字,你愿意起什么都可以的,

按照程序员编码习惯,一般是呀,,呀,经常用的几种写法

泛型类可以实现泛型接口:

这个继承和实现,和我们普通类的继承和实现没有很大的区别,唯一的区别就是体现在参数上面,和泛型上面

泛型类可以同时设置多个类型参数:

现在再做一个类Cls2,多个参数用,隔开        class  Cls2

构造方法                        public Cls2(T a,T2 b){
                                                this.a =a;

                                                this.b =b;
                                            }

有两个变量,                T a;
                                    T2 b;

这两个变量的具体类型为止

同样的b的类型是T2,        public T getData(){
                                                return a;
                                            }
    
                                            public T2 getData2(){
                                                        return b;
                                                    }

我们在真正做他的时候,<>里面的顺序一样,构造方法要传参

   

 运行结果

           

 这面要注意一个问题,比如说我现在有一个Cls4,两个泛型我们都是整型数

这面显示一个错误 

he constructor Cls2(int, String) is undefined

你这面都写integer,但是他会认定你传进来的构造方法是一个字符串,所以他会失败

 我改成10就OK啦

 

 那么我们可以把上面两个整型数拿来相加嘛?

运行结果 

 暂时看到编译是ok 的,加也是可以正常加的

 那如果一个是Integer 一个是String呢

数据类型不同的时候相加,看结果

 

运行结果        

也能加        

用System.out.println可加的                

但是会给人家错误的认为,感觉不同的数据类型都可以拿来加,                                        

但是你要知道System.out.println这面的加号是起到一个连接的作用        

 如果我们单独给他拎出来,他会出现一个什么样的情况呢?

        int sum = 0;
            sum = cls4.getData()+cls4.getData2();
            System.out.println(sum);
            

 

 运行结果

这样子写也行 

泛型的类型参数可以是泛型类:

Cls1 cls1= new Cls1(10);里面也可以放入泛型

比如说里面就是Cls1,Cls1他就是个泛型,这边我用Integer给他确认下来

                        Cls1> cls1

另一面也一样

这面出现问题是因为不能写10,

 因为他应该是Cls1的实例化                               

泛型类里面的类型还是个泛型,你new的时候和前面一样,这面的构造方法呢?

 构造方法传过来的时候 ,T不就变成Cls1

我们在输出的时候,System.out.println(cls1.getData());

这个Data,get出来是一个泛型

因为Cls1他是最外面的那一层,你获得出来的应该是Cls1

Cls1> cls1= new Cls1>(new Cls1(10));
     

这个Cls1又是一个类,你如果访问到a,你还得getData一次

        System.out.println(cls1.getData().getData());

这个时候我们才能把10抓出来

 运行结果

泛型类可以继承泛型类:

我现在的Cls2和Cls1是重复的呀,这样写也是一种浪费 

可以         class Cls2 extends Cls1,继承过来儿子比父亲多点特性,是ok的,

就是构造方法这面我们需要做一些修改

错误提示:        Implicit super constructor Cls1() is undefined. Must explicitly invoke another constructor

因为他要调用父亲的            super(a);        你在子的构造方法中,调用父亲的构造方法来构造自己

剩下的一项,   this.b=b;     作为数据的初始化

 可以把父类有的去掉

 然后我们使用一下

Cls2 cls = new Cls2(100,"冰糖李子");

用法还是一样的,就是我们在构造Cls2的时候,不要写那么多代码,一些东西是从Cls1继承过来的 

                                                                                                                                                                     

那如果他是继承的话,有一些函数,比如说           void printInfo();        假设他现在是个泛型,

同时又是一个抽象的方法                            abstract void printInfo(); 

这边是一个抽象带有泛型的类        abstract class Cls1        也是ok的

也是遵循以前继承的道理,你要把里面 的printInfo()实现出来

错误提示:         Multiple markers at this line
                            - Cannot instantiate the type 
                             Cls1>

因为abstract class Cls1        是一个抽象

抽象类是不能初始化的,可以去掉    第39行,第40行

     代码如下

 

 运行结果

 泛型类可以实现泛型接口:

我们比如说再来一个interface cls3        也是泛型

里面有一个抽象方法

这是一个接口

跟以前的写法也是一样的,

以前的写法  是      没有,然后

                                        interface cls3
                                                {

                                                    abstract void printInfoCls3(String t);
                                                }

这就是我们以前说的接口,无非在这个接口上加了一个泛型

也就是这个抽象方法,可以实现,输出整型数,字符串都是ok的

 那我们的cls2可以继承cls1

 Cls2也可以implements这个接口

 class Cls2 extends Cls1 implements Cls3

既然你要实现接口的话,就要实现接口里面的方法

 我们在使用Cls2的时候        第53行

                        cls.printInfoCls3(100);

虽然Cls2那面写的都是T,但是      public Cls2(T a,T2 b){
                                                        super(a);
                                                                this.b=b;
                                                    }

这两个T不一样                public void printInfoCls3(T t) {
                                                // TODO Auto-generated method stub
                                                System.out.println(t);

                                                        }

下面这个T是隶属于        interface Cls3这个接口的,取决于你传递进来是什么数据

上面的那个T是        Cls2 cls = new Cls2(100,"冰糖李子");里面的,它取决于你给他实例化的时候,设定的是具体的哪个参数

当然,刚好我们写了Integer   和    cls.printInfoCls3(100);  里面的100

如果我们把        cls.printInfoCls3(100); 改成字符串呢?        第53行

错误提示:The method printInfoCls3(Integer) in the type Cls2 is not applicable for the arguments (String)        不行了

所以说T如果产生某种冲突的话,也是不允许的

 你这时候即继承了Cls1都叫T,又实现了这个接口,在这种情况下,你如果名字一样

你要遵循在class Cls2 extends Cls1 implements Cls3

        下面所有的T表示的都是同一种类型

不然他这面会产生类型上的冲突

 

 这种情况下改变一个T3试试

 我把class Cls2 extends Cls1 implements Cls3

里面的T3去掉可以吗?        第22行

也不行,因为public void printInfoCls3(T3 t)

必须在class Cls2 extends Cls1 implements Cls3

被包含

 你要支持T3,你就要做出一系列的修改

Cls2 cls = new Cls2(100,"冰糖李子");你要跟T3绑定起来

而且必须是一个String

如果这时候你把 cls.printInfoCls3("测试");   改成cls.printInfoCls3(100);

也不行

 完整代码

 

运行结果

 注意:泛型类可以实现泛型接口,

但是要注意,既要继承又要实现接口的 时候,要保证它里面具备了这些泛型的占位符

三、限制泛型可用类型

        在定义泛型类别时,默认在实例化泛型类的时候可以使用任何类型,但是如果想要限制使用泛型类型时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口。

        当没有指定泛型继承的类型或接口时,默认使用extends Object,所以默认情况下任何类型都可以做为参数传入

                         

         

 当没有指定泛型继承的类型或接口时,默认使用extends Object,所以默认情况下任何类型都可以做为参数传入:

这就是我们之前的做法

 

 系统在编译它的时候是默认加了一个extends Object

你写不写它的效果是一样的,也就是对T他没有任何的限制,所以在使用它的时候任何类型都可以作为参数传入

 

 那如果某种场景我们必须对这个T做一些监管,限制使用泛型类型,

可以使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口。

如果我变成了        abstract class Cls1

如果你这样写,你没办法给这面赋一个整型数的

 

 这个时候只能把

    Cls2 cls = new Cls2(100,"冰糖李子");

Integer    变成   String类型        这面的100也只能改成字符串

Cls2 cls = new Cls2("","冰糖李子");

这就是我们说的限定了T,

 

 可以用继承,可以用某个接口

我们添加一些具体的写法进来

我要求这个T必须继承Animal                                               

一写进来Cls2 cls = new Cls2("","冰糖李子");

必须变成                                                                                                               

Cls2 cls = new Cls2(new Dog(),"冰糖李子");

 

 那如果我现在有一个接口,接口里面有一个抽象的方法                                                                             
interface Move                                                                                                                      
{                                                                                                                                                
    abstract void test();
}

如果你对于T做一些限制要求,必须要实现Move这个接口                                                 

我们以前实现接口是        class A implements Move {              

                                                }       这样一个写法

A这面去实现Move里面未实现的方法·        叫做test

 如果这面也用Move的话                                                                                                

abstract class Cls1                                                                    

是用  extends      abstract class Cls1                                                           

还是    implements     abstract class Cls1                                      

发现还是得用extends      abstract class Cls1                                         

                                                                                                                                        

注意他跟我们传统的        implements是不一样的                                      

 

 

 为什么        abstract class Cls1           多了extends?

因为他可能继承某个类        ,或者限定了它实现某个接口                                             

四、类型通配声明

同一泛型类,如果实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能互相赋值。

        Generic f1 = new Generic();

        Generic f2 = new Generic();

        f1 = f2;          //发生编译错误

        Generic f= f1 ;         //f1和f类型并不兼容,发生编译错误f=f2;

                                                       //f2和f类型同样不兼容,也会发生编译错误

        泛型类实例之间的不兼容性会带来使用的不便。我们可以使用泛型类通配符(?)声明泛型类的变量就可以解决这个问题。

新建一个工程

 现在有一个Cls1,实例化一下(记得抽象类不能实例化)

 同样的我们再来一个c2,来一个Double类型的,                                                                               

然后我们让c1 = c2;        他是不允许的                                                                    

错误提示        Type mismatch: cannot convert from Cls1 to Cls1

不能把c2转化为c1,因为Double和Integer是有区别的                                             

 那如果我们现在有Object,行不行?                                                                                       

更大的类,去做一些匹配                                                                                                 

错误提示   Type mismatch: cannot convert from Cls1 to Cls1

他也是不行的                                                                                                                             

反过来也不行

类型通配声明        例子

        泛型通配的方式

      ·  “?”代表任意一个类型                                                                   

                Generic  f1 = new Generic();              

                Generic f = f1;                                                                                   

        ·和限制泛型的上限相似,同样可以使用extends关键字限定通配符的上限              

                Generic f1 = new Generic();                        

                Generic f =f1;                                                 

       · 还可以使用super关键字将通配符类型限定为某个类型的下限

                Generic f1 = new Generic();                                           

                Generic f =f1;                                                                                  

                        //它必须是Dog 的父亲

                                                                                                                                                                                                                   

也就是说我们用一个

这个时候你会发现c3可以引用c1

 同样的c3可以引用c2;

这个就是我们说的通配符,用?来表示

和限制泛型的上限相似,同样可以使用extends关键字限定通配符的上限:

也就是说,你可以管理这个问号

比如说我们来个c4,我们c4这面要求是一个Dog

比如说我的c4里面的泛型是一个Dog

这种情况下我的c3可以等于c4,因为这个问号是通配所有的

 那如果对于问号管制的话,        Cls1 c3;

发现很多东西都不能用了,因为他必须是String 的子类或者String

 那如果我们把他改成Integer 呢?

发现只有c1这一条是可以的

 如果改成Animal                 Cls1 c3;呢?

1和2 不行,4是可以的,                对?号产生了一定的范围

只有它的上限是Animal 的时候才可以

 还可以使用super关键字将通配符类型限定为某个类型的下限:

比如我这面用super,就不行了,它必须是Animal的父亲

 如果把这面改成一个Dog 呢?

 改成Animal也是可以的

       五、泛型方法

        不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法。其定义格式为:

        访问修饰符  <泛型列表>  返回类型  方法名  (参数列表){

                实现代码

        }

        在泛型列表中声明的泛型,可用于该方法的返回类型声明、参数类型声明和方法代码中的局部变量的类型声明

        类中其他方法不能使用当前方法声明的泛型

        提示:是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前

 不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法。:

也就是说,这个泛型是属于方法的,不是属于类的,也就是说我们可以在普通类中去定义一个泛型方法。

类中其他方法不能使用当前方法声明的泛型:

也就是说我这个泛型是有时效性的。它是有区域性的,有一个它的作用域,有点像局部变量。你在当前方法中有泛型列表,在其他方法中不能用

是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前:

也就是我们说的普通类可以有泛型方法

                                              

你有了泛型类,为何还要泛型方法呢?

新建一个工程

假设classA里面有一个泛型

          

错误提示:Multiple markers at this line
    - Syntax error, type parameters are only available if source level is 1.5 or 
     greater

需要换到1.5版本以后的

找到这里 

 

 看见JDK那行了嘛

对勾去掉,换成1.5版本以后的

 然后就没有错误提示了

 运行结果,可行

 那如果我在这里打印一个100呢?

编译都通不过

错误提示:        The method printInfo(String) in the type A is not applicable for the arguments (int)

因为他要求你传String,但是你的arguments是100

 等于说这个方法,

被里面的泛型给限制了                class A
                                                 {
                                                        public void printInfo(T t){
                                                                  System.out.println(t);
                                                               }
                                                        }

那么泛型方法是什么意思呢?我不应该让我的t         被你的类限制掉

比如说我现在有一个class  B

我可以把他声明为普通的方法        class B

注意:泛型方法是        

  访问修饰符  <泛型列表>  返回类型  方法名  (参数列表){

                实现代码

        }

也就是说我的泛型列表可以放在返回类型的前面        void前面我放一个

                public void printInfo(T t){
                                System.out.println(t);
                            }

 

 运行结果

我们得出的结论,泛型方法更加灵活,它可以不受泛型类的约束

如果你泛型类在实例化的时候,确定了泛型的类型,以及你方法里面所有的东西   T  都被定死掉了

就出现了刚才我们的A         只能打哈哈,不能打1234

这个东西比我们以前做的方法的重载,更加的牛逼

 以前方法重载是什么意思呢?

                public void print1(int a){
                        System.out.println(a);
                    }

再来个char a 这就叫方法的重载

                public void print1(char a){
                                        System.out.println(a);
                    }

        

你即便方法重载也要写这么多遍

那泛型方法它的好处,比方法重载更加牛逼

不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法:

也就是我的T         第11行,只对我本方法有效

跟这个类class  B没有关系,跟其他的方法也没有关系

也就是说你能不能用到t        呀?

错误提示:  t cannot be resolved to a variable

 当然泛型列表中的个数也可以做多个                

        public void printInfo(T t,T2 t2){
                        System.out.println(t+t2);
            }
    

这其实也是个方法的重载,但是这面t2不让加   

错误提示:he operator + is undefined for the argument type(s) T, T2

 分开写呢?

 

 为什么不让加呢?因为他如果在后面实例化,确定类型以后是可让加的,

,你这面没有实例化,它的方法类型是不确定的,不让你乱加

 

 当然        public void printInfo(T t,T2 t2){
                                System.out.println(t);
                                System.out.println(t2);
                    }

也是泛型方法,只是对                public void printInfo(T t){
                                                        System.out.println(t);
                                                            }

做了重载

我们重载的意思是,返回值,跟这个名字一样,参数列表可以不一样

 在泛型列表中声明的泛型,可用于该方法的返回类型声明、参数类型声明和方法代码中的局部变量的类型声明:

也就是说            public void printInfo(T t,T2 t2){
                                System.out.println(t);
                                        System.out.println(t2);
                                    }
可以返回一个T    public T printInfo(T t,T2 t2){
                                           System.out.println(t);
                                            System.out.println(t2);
        
                                                return t;
                                         }

这样子是可以的

 

类型声明:        public T printInfo(T t,T2 t2)
局部变量:                System.out.println(t);

五、泛型方法

        什么时候使用泛型方法,而不是泛型类呢?  

                添加类型约束只作用于一个方法的多个参数之间,而不涉及类中的其他方法时。

                施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型参数

                     

  添加类型约束只作用于一个方法的多个参数之间,而不涉及类中的其他方法时。:

我们不希望这个方法当中的数据类型被这个类给限制了,而是自由的我想打印什么,都可以,不被类的方法限制的时候

施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型参数:

类型约束:

也就是说        public void printInfo(T t)这个泛型T也可以进行类型的约束

    

   前面加上

                        class Animal
                                {    
                                    public void eat(){
                                        System.out.println("动物吃");
                                       }
                                }

                                          

                             class Dog extends Animal
                                {
                                    public void eat(){
                                        System.out.println("啃骨头");
                                            }
                                        }

                                class Cat extends Animal
                                {
                                    public void eat(){
                                        System.out.println("吃鱼");
                                            }
                                        }

中间加上    

他必须是一个上限,是Animal的子类        

                            public void printInfo2(T t){
                                                t.eat();
                                            }

这就叫类型约束

这时候来个            b.printInfo2("哈哈");  可以嘛?

错误提示:Bound mismatch: The generic method printInfo2(T) of type B is not applicable for the 
 arguments (String). The inferred type String is not a valid substitute for the bounded 
 parameter

 

 这时候只能                b.printInfo2(new Dog());
                                    b.printInfo2(new Cat());
                                    b.printInfo2(new Animal());

也就是我们之前讲的对泛型的限制,放在泛型方法里面是同样适用的

 

 运行结果

 静态方法:

我们比如把

public void printInfo2(T t)变成

public static void printInfo2(T t)

警告:        第71行,第72行,第73行

The static method printInfo2(Dog) from the type B should be accessed in a static way

 

 出现这种情况,完全可以    B.printInfo2(new Dog());

静态方法就是要求我们这样做

不用非得实例化,类的名字加上方法名,做一个静态的调用

静态方法不能使用其所在类的类型参数:

因为静态方法本身就是和这个类脱离的

注意:这个T会被重置,编译的时候

第33行的T      public void printInfo(T t)         到最后会变成object

第44行的T     public static void printInfo2(T t)                  到最后会变成Animal

 

 注意:不管你是泛型方法还是普通方法,你不能搞一摸一样的

Duplicate method print1(int) in type B

 

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号