java 泛型 父子_Java 基础:泛型

本文介绍 Java 中的泛型,可与 Kotlin 基础:泛型 配合食用。

一、为什么要有泛型

效率、成本

减少样板代码的编写

二、泛型的分类

泛型类

泛型方法

三、泛型的关键字

3.1 T

T 代表任意一个类型,可以为任意字符串,一般为:T、U、S、E、K、V。

T、U、S:任意类型

E:集合的元素类型

K、V:Map 的 key 和 value 类型

3.2 ?

? 是泛型通配符,代表任意一批类型。

四、泛型类、方法的定义

4.1 泛型类的定义

class AClass ...

class AClass ... //没有 T super BClass 这种写法复制代码

在类名后声明。在该类中,可以

使用 T 作为对象的类型声明

T a;

使用 T 作为泛型类型对象的类型参数

List list;

使用 T 作为方法返回类型前的声明(所以泛型类中的泛型方法可以省去返回类型前的 )

见泛型方法的定义

4.2 泛型方法的定义

public void ...

复制代码

在方法返回类型前声明。在该方法中,可以

使用 T 作为方法的返回类型

public T...

使用 T 作为方法的参数类型

public void doSomething(T t) ...

使用 T 作为方法的泛型参数的类型参数

public void doSomething(List listT)...

五、泛型类、方法的使用

5.1 泛型实现类

指类型参数指定为一个确定的单一类,如 String 对应 AClass,它表示:

一个泛型实现类,类型参数是 String(即 AClass,使用时 T 已经被指定为 String)

5.2 通配类

5.2.1 AClass>

它代表一批泛型实现类,类型参数可以是任何类。

5.2.2 AClass extends BClass>

它代表一批泛型实现类,这批实现类的特点是:

它们的类型参数只能是 BClass 的子类。

它们自己,都是 AClass extends BClass> 的子类。

这种泛型实现类与通配类的父子关系,和泛型实现类的类型参数与通配类的类型参数的父子关系相同的关系,称为协变。

当实现类转为 AClass extends BClass> 时:

可以 get 到 BClass,因为所有实现类的类型参数的共同上界就是 BClass。

不能 set 任何值,因为不确定实现类的类型参数是哪个 BClass 的子类。

5.2.3 AClass super BClass>

它代表一批泛型实现类,这批实现类的特点是:

它们的类型参数只能是 BClass 的父类。

它们自己,都是 AClass super BClass> 的子类。

这种泛型实现类与通配类的父子关系,和泛型实现类的类型参数与通配类的类型参数的父子关系相反的关系,称为逆变。

当实现类转为 AClass super BClass> 时:

不能 get 到 BClass,只能 get 到 Object,因为所有实现类的类型参数的共同上界只有 Object。

可以 set BClass 及其子类,因为一定是覆盖真正的实现类的类型参数的。

六、代码示例

public class ChangeJava{

class A{

}

class B extends A{

}

class C extends B{

}

class AClass{

private T mT;

void set(T u){

mT = u;

}

T get(){

return mT;

}

}

private void doSomething(){

AClass aClass = new AClass<>();

AClass aClass1 = new AClass<>();

aClass1 = aClass; // 报错

AClass aClassA = new AClass<>();

AClass aClassB = new AClass<>();

AClass aClassC = new AClass<>();

AClass extends B> aClassExtendB1 = aClassA; // 报错

AClass extends B> aClassExtendB2 = aClassB;

AClass extends B> aClassExtendB3 = aClassC;

B b2 = aClassExtendB2.get(); // 可以 get 到 B

aClassExtendB2.set(); // 报错,set 任何值都会报错

AClass super B> aClassSuperB1 = aClassA;

AClass super B> aClassSuperB2 = aClassB;

AClass super B> aClassSuperB3 = aClassC; // 报错

Object o = aClassSuperB1.get(); // 只能 get 到 Object

aClassSuperB1.set(new A()); // 报错,set 除 B 及其子类以外的类型就会报错

aClassSuperB2.set(new B());

aClassSuperB2.set(new C());

}

}

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,是一种强类机制,它可以让你在编译时检查类错误,从而提高代码的安全性和可读性。在使用时,我们经常会遇到父类和子类的转换问题。 首先,我们需要明确一点:子类不能转换成父类。这是因为Java中的是不协变的。例如,如果有一个类A和它的子类B,那么List<A>和List<B>之间是不存在继承关系的。 下面我们来看一个例子: ```java public class Animal { //... } public class Dog extends Animal { //... } public class Test { public static void main(String[] args) { List<Animal> list1 = new ArrayList<>(); List<Dog> list2 = new ArrayList<>(); list1 = list2; // 编译错误 } } ``` 在这个例子中,我们定义了Animal类和它的子类Dog。然后我们定义了两个List,分别是List<Animal>和List<Dog>。如果将List<Dog>赋值给List<Animal>,会出现编译错误。这是因为List<Animal>和List<Dog>之间不存在继承关系。 那么,如果我们想要让子类转换成父类,应该怎么办呢?这时我们可以使用通配符来解决问题。通配符可以表示任意类,包括父类和子类。例如,我们可以将List<Dog>赋值给List<? extends Animal>,这样就可以实现子类转换成父类了。 下面我们来看一个使用通配符的例子: ```java public class Animal { //... } public class Dog extends Animal { //... } public class Test { public static void main(String[] args) { List<Animal> list1 = new ArrayList<>(); List<Dog> list2 = new ArrayList<>(); list1 = list2; // 编译错误 List<? extends Animal> list3 = new ArrayList<>(); list3 = list2; // 正确 } } ``` 在这个例子中,我们定义了List<? extends Animal>来表示任意继承自Animal的类。然后我们将List<Dog>赋值给List<? extends Animal>,这样就可以实现子类转换成父类了。 总结一下,Java中的是不协变的,子类不能转换成父类。如果需要实现子类转换成父类,可以使用通配符来解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值