黑马程序员——————> 深入泛型

------- android培训、java培训、期待与您交流! ----------

首先,可以为任何类,接口增加泛型声明,下面自定义一个Apple类,这个Apple类就可以包含一个泛型声明。

 1 public class Apple 
 2 {
 3     //使用T类型形参定义实例变量
 4     private T info;
 5     public Apple(){}
 6     
 7     //下面方法中使用T类型形参定义构造器
 8     public Apple(T info)
 9     {
10         this.info = info;
11     }
12     
13     public void setInfo(T info)
14     {
15         this.info = info;
16     }
17     
18     public T getInfo()
19     {
20         return this.info;
21     }
22     
23     public static void main(String[] args)
24     {
25         //由于传给T形参的是String,所以构造器参数只能是String
26         Apple a1 = new Apple<>("苹果");
27         System.out.println(a1.getInfo());
28         
29         //由于传给T形参的是Double, 所以构造器参数只能是Double或double
30         Apple a2 = new Apple<>(5.67);
31         System.out.println(a2.getInfo());
32     }
33 }

上面程序定义了一个带泛型声明的Apple类,使用Apple类时就可为T类型形参传入实际类型,这样就可以生成入Apple  Apple.....形式的多个逻辑子类(物理上并不存在)。

JDK在定义List  ArrayList等接口和类时使用了类型形参,所以在使用这些类时为之传入了实际的类型参数。

 

问题:我们如何从泛型类派生子类?

 

当创建了带泛型声明的接口,父类之后,可以为该接口创建实现类,或从该父类派生子类,需要指出的是,当使用这些接口,父类时不能再包含类型形参。例如,下面代码就是错误的。

//定义类A继承Apple类,Apple类不能根类型形参
public class A extends Apple{}

 

定义方法时可以声明数据形参,调用方法时必须为这些数据形参传入实际的数据:于此类似的是,定义类,接口,方法时可以声明类型形参,使用类,接口,方法时应该为类型形参传入实际的类型

如果想从Apple类派生子类,则可以改为如下代码:

//使用Apple类时,为T形参传入String类型
public class A extends Apple


调用方法时必须为所有的数据形参传入参数值,与调用方法不同的时,使用类,接口时可以不为类型形参传入实际的类型参数,所以下面的代码也是正确的。

//使用Apple类时,没有为T形参传入实际的类型参数
public class A extends Apple


如果Apple类派生子类,则在Apple类中所以使用T类型形参的敌方都将被替换成String类型,即它的子类将会继承到String getInfo()和void setInfo(String info)两个方法,如果子类需要重写父类的方法,就必须注意这一点。下面的程序示范了这一点。

public class A1 extends Apple
{
    //正确重写了父类的方法,返回值
    //与父类Apple的返回值完全相同
    
    public String getInfo()
    {
        return "子类" + super.getInfo();
    }
    //下面方法时错误的,重写父类方法时返回值类型不一致
    public Object getInfo()
    {
        return "子类";
    }
}

 

如果使用Apple类时没有传入实际的类型参数,java编译器可能发出警告:使用了未经坚持或不安全的操作——这就是泛型坚持的警告。

此时,系统会把Apple类里的T形参当成Object类型处理。如下程序所示。

 1 public class A2 extends Apple
 2 {
 3     //重写父类方法
 4     public String getInfo()
 5     {
 6         //super.getInfo()方法返回值是Object类型
 7         //所以加toString()才返回String类型
 8         return super.getInfo().toString();
 9     }
10 }

 

并不存在泛型类

我们可以把ArrayList类当成ArrayList的子类,事实上,ArrayList类也确实像一种特殊的ArrayList类:该ArrayList对象只能只能添加String作为集合元素。但实际上,系统并没有为ArrayList生成新的class文件,而且也不会把ArrayList当成新类来处理。

        //分别创建List对象和List对象
        List l1 = new ArrayList<>();
        List l2 = new ArrayList<>();
        //调用getClass()方法来比较l1和l2的类是否相等
        System.out.println(l1.getClass() == l2.getClass());

运行上面的代码片段实际输出的是true.因为不管泛型的实际类型参数是什么,它们在运行时总有同样的类(class)
不管为泛型的类型形参传入哪一种类型实参,对于java来说,它们已然被当成同一个类处理,在内存中也只占用一块内存空间,因此在静态方法,静态初始化块或者静态变量的声明和初始化中不允许使用类型形参。

 

转载于:https://www.cnblogs.com/-9527/p/5208182.html

你可能感兴趣的:(java,移动开发)