java泛型 null_Java泛型

1、什么是泛型

泛型就是 参数类型化 ,简单说就是在定义类 接口 方法时时不支持具体的参数类型的。只有在实际使用时才确定。

2、为何用泛型

我觉得有两点好处

a.  明确类型 避免类型转换

如,没有泛型前,从List中取数据都是Object类型的 需要强制转换为确定的类型

public static void main(String[] args) {

List myList = new ArrayList();

myList.add(new Integer(1));

Integer value = (Integer)(myList.get(0));

System.out.println("value=" + value);

}

b.  提高代码复用

如有Father类 每个父亲可能有不同的职业 有点的教师 有点的医生...

如何表示呢,搞多个类表示不同的职业? 可以 但不友好!

使用泛型 如下:把职业类型化

使用:

Father fatherTeacher = new Father<>(new Teacher());

Father fatherDoctor = new Father<>(new Doctor());

public class Father {

private T job;

public Father(T job){

this.job = job;

}

public void work(){

System.out.println("my job is "+ job);

}

}

3、如何使用泛型

泛型可以使用在类(泛型类)、 接口(泛型接口、 方法(泛型方法)中。

泛型类: 如上述的例子

泛型接口:

样例

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public interface Work{public voidwork(T t);

}

继承泛型接口public class Father implements Work{privateT job;publicFather(T job){this.job =job;

}

@Overridepublic voidwork(T t) {

System.out.println("my job is "+t);

}

}

View Code

泛型方法:方法的参数调用时才确定

例如下 :在泛型类中定义了一个泛型方法 (E是一种类型,跟类中的T 可能一样可能不一样)

泛型方法必须使用<> 表示类型

public class Father implements Work{

private T job;

public Father(T job){

this.job = job;

}

@Override

public void work(T t) {

System.out.println("my job is "+ t);

}

public void printWork(E e){

System.out.println("my job is "+ e);

}

}

调用:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public static voidmain(String[] args) {

Father fatherTeacher = new Father<>(newTeacher());

fatherTeacher.printWork(newTeacher());

}

View Code

输出:my job is com.yangfei.test.fanxing.Teacher@13221655

4、泛型擦除

泛型只在编译时有效 运行时是没有泛型的,称之为泛型擦除。

如下的示例 输出结果为true (java中一个类只会加载一次 生成Class类型对象)

说明两个类是没有泛型的区别的(编译后都被转成了Object)。

Class list_int = new ArrayList().getClass();

Class list_string = new ArrayList().getClass();

System.out.println(list_int==list_string);

泛型擦除的目的: 就是为了运行时不会创建过多的类 避免因泛型的区别导致加载的类泛滥。

泛型擦除非真正擦除: 否则运行时如何转换成实际的类型呢

List sd = new ArrayList();

sd.add("yangfei");

String str = list.get(0)

但取值的时候怎么知道要转成String类型的呢?

擦除并非真正的完全擦除,泛型信息还是会保存在class字节码的常量池中,

在使用了泛型的代码调用处会生成一个signature签名字段,signature指明了这个常量在常量池的地址,调用时强制转换

这样我们就找到了参数化类型。

5、协变

数组是协变的 什么意思

如果class A extends B 那么B[] array = new A[] 也是成立的,这是协变。

而泛型是不支持协变的

即 List是不可以赋给List

6、 ?和T的区别

T表示一个类型 在使用时确定。

?时通配符 表示任意类型。

使用场景不一样

a. 在泛型类定义是使用T

b.在使用泛型时 可用?

如:

Father> fatherTeacher = new Father(new Teacher());

有啥好处,我们知道泛型不支持协变的,有了通配符后,可以有如下表示

父子类:class Son extends Mather; 则如下写法也是合法的

List extends Mather> lists = new ArrayList();

其实List> 相当于List extends Object>

7、PECS原则

PECS原则的全拼 : "Producer Extends Consumer Super"

表示 extends T> 一般用于生产者,生产数据。外部只从中读数据;< ? super T> 一般用于消费者,需要消费数据,外部需要往其中写数据。

7.1 extends T> 表示可能是T或者T的子类 (上边界通配符)

这种情况一般只能取 不能存非null之外的任何类型

如下class Son extends Mather; class Daughter extends Mather;

public static void main(String[] args) {

Mather[] matherArr = new Mather[]{new Daughter(),new Son()};

List extends Mather> lists = Arrays.asList(matherArr);

lists.add(null); //因为任何类型都可以用null表示

lists.add(new Daughter()); //此处会编译报错

Mather mather = lists.get(0);

}

存非null值会报错 ,因为不知道具体是什么类型,Mather的子类和子类间并没有直接关系 没法赋值,所以没法存

取出来的值 只能是父类型(所有子类都可以转为父类)

7.2 super T> 表示可能是T或者T的父类 (下边界通配符)

这种情况一般只用于存数据 ,可以存T或T的子类,因为T的子类可以转换为T类型,而T类型也可以自动向上转为任何父类

取出的数据向上转换只能是object类型

public static void main(String[] args) {

Mather[] matherArr = new Mather[]{new Daughter(),new Son()};

List super Mather> lists = Arrays.asList(matherArr);

lists.add(null);

lists.add(new Daughter());

Object mather = (Object)lists.get(0);

}

8、不支持泛型数组

Java是不支持泛型数组的,如下编译会报错

List[] array = new ArrayList[5];

为何不支持:数组支持协变,泛型运行时类型擦除,这样容易引起误解

如下: List类型数组 因为类型参数,可以把List也放入数组中,导致内容错误。

ArrayList[] intArr = new ArrayList[10];

Object[] obj = intArr;

ArrayList listStr = new ArrayList();

listStr.add("yangfei")

obj[0] = listStr;

ArrayList listInt = intArr[0];

Integer i = listInt.get(0);//想要获取Integer,但却是String

9、静态方法与类的泛型

一个泛型类只有在初始化时才能明确其类型 ; 而静态方法不属于实例。所以静态方法不能使用类的泛型

如下:标红会编译报错

public class Father implements Work{

private T job;

public Father(T job){

this.job = job;

}

@Override

public void work(T t) {

System.out.println("my job is "+ t);

}

public static void printWork(T e){

System.out.println("my job is "+ e);

}

}

解决方法:可使用泛型方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值