likes
comments
collection
share

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

作者站长头像
站长
· 阅读数 49

第一部分:认识泛型

● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:) 称为泛型类、泛型接口,泛型方法、它们统称为泛型。 public class ArrayList{ ... } ● 作用 : 泛型提供了在编译阶段 约束所能操作的数据类型,并自动进行检查的能力! (也就是在写代码阶段它可以约束我们能够操作的数据类型,比如ArrayList就代表着集合中只能操作字符串类型,提前就把类型确定死),在集合后面添加<标签>。

这样的好处是可以避免强制类型转换,以及可能出现的异常。


为什么在集合后面贴了标签就只能加字符串?原理是什么嘞?《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

我们来查看一下ArrayList的源码:《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

这个E是接收 标签<> 传递过来的类型变量,然后在后面的所有E都变成了String,比如看这个add方法:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

这里的E就是String,所以也就是为什么add方法在使用了泛型后只能添加String字符串

所以泛型的本质就是:把具体的数据类型作为参数传给类型变量

第二部分:泛型类和泛型接口

2.1 自定义泛型类

修饰符 class 类名<类型变量1,类型变量2>{

}

【类型变量可以是一个 也可以是多个,并且尽量用大写E、K、T、V】

例如:

public class MyArrayList{

}

2.2 自定义泛型接口

修饰符 interface 接口名<类型变量1,类型变量2>{

}

【类型变量可以是一个 也可以是多个,并且尽量用大写E、K、T、V】

例如:

public interface A{

}

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

再定义实现类去实现接口:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

通过泛型的标签<>就可以去确定接口的类名变量,你要操作哪个数据,你在实现这个接口的时候,你就应该传哪个数据,得到(重写)的功能就全是针对于它的。

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

第三部分:方法、通配符、上下限

3.1 泛型方法

修饰符<类型变量,类型变量,...> 返回值类型 方法名(形参列表){

}

正确的例如:

public static void test (T t){

}

但下面这种不是泛型方法!!不是它自己定义的,是外面所在的泛型类定义的,它只是在用别人的类型变量 如ArrayList中的get方法:《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

public E get(int index){

return (E) arr[index];

}

如下,String类型和Student类型都可以传给printArray方法

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

3.2 通配符和上下限

引言:

我们模拟一下极品飞车,有很多车的对象,现在要写一个go方法,让不同的车在一起来比赛,如果参数是ArraryList,那么可见上面go(bmws)的话就会报错,改为ArraryList,go(Xiaomi)又会报错wuwuwu

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

有的友友很聪明就会想改为不就好啦,有点像多态~,但是不太对哟。

ArrayList、ArrayList与ArrayList完全没有一点关系滴!(Car是所有车的父类)

所以我们就要了解 —— 通配符

通配符:

● 则是“?”,可以在“使用泛型”的时候代表一切类型; E T K V是在定义泛型的时候使用。(这里注意是使用泛型(不是定义泛型) 比如sun公司已经写好了的ArrayList这种已经有的泛型类)

那我们进行代码改进:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

耶~这样就不报错了耶,可是... 要是添加一只狗进来比赛,貌似也可以...

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

啊这。。。 还真行,狗:我也成车啦?(一点也不严谨!)

这下Java就有了 —— 上下限 这个概念

泛型的上下限: ● 泛型上限: ? extends Car:?能接收的必须是Car或者其子类。 ● 泛型下限: ? super Car:?能接收的必须是Car或者其父类。

就做出改进:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

? extends Car 表示上限,要么Car、要么Car的子类,而Dog没有继承Car所以Dog就会被一脚踢出去!

这下就完美的解决了狗不能作为车子的这类问题~


第四部分:泛型支持的类型

泛型不支持那八种基本的数据类型,只能支持对象类型(引用数据类型)。

泛型集合用包装类

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

至于为什么只能支持对象类型,这就涉及到泛型擦除: 泛型在编译阶段工作,在编译阶段后就没用了会被擦除,所有类型会恢复成Object类,然而如果是基本数据类型不能恢复成Object这种对象类型。Object只能指向对象。

所以!Java又提出了一个观点 —— 包装类

包装类: 就是把基本数据类型包装成对象数据类型

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:


接下来我们再看看如何把基本数据类型变成包装类对象

4.1 手工包装

1.手工包装第一种:(已经过时~)

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

looklook源码:自从版本9开始就把这种给淘汰了

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

2.手工包装第二种:(推荐)

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

为啥第二种更推荐呢?

我们来看看源码:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

这个valueOf已经提前在这个数组cache(缓存池)中 封装好了【-128~127】的所有对象,不需要你自己再去new新的,占用内存。《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:


我们可以做一个小实验 包两个100,看看it1和it2指向的地址是不是一样的(是不是同一个对象)

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

果不其然:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:


但是如果超出范围 就会在堆里new新的对象出来,比如两个130:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

4.2 自动装箱

自动装箱:基本数据类型可以自动转换为包装类型

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

实际跟上面的手动的原理一模一样。

自动拆箱:包装类型可以自动转换为基本数据类型。

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:


那这装箱拆箱的到底有什么用呢?

举个栗子就知道了~

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

就想这个集合直接add(123)为什么不会报错呢?就是因为123 到 Integer实现了自动装箱的过程。把123是当成Integer对象给到的集合,

当我们取数的时候:理论上是用Integer来接

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

但是我们也可以用int来接:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

这里也是涉及到了自动拆箱的过程~

4.3 包装类具备的其他功能

● 可以把基本类型的数据转换成字符串类型。 public static String toString(double d) public String toString()

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

但是程序员觉得这多少有点鸡肋,我们直接《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:不香嘛?

Java觉得也是,然后他又搞了个下面这个玩意。。。(很有用! !)

● 可以把字符串类型的数值转换成数值本身对应的真实数据类型。 public static int parseInt(String s) public static Integer valueOf(String s)

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

但更方便的是int i2 = Integer.ValueOf(str);就可以不用调parseInt:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

double也是如此:

《Java泛型:原理、特性与应用场景》第一部分:认识泛型 ● 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:

· 这里太重要了 必须小结小结:

所以在今后我们将 字符串 处理为 整数或者小数 就会用到这两种方法:

1.Integer.valueOf(str) 或 Integer.parseInt(str);

2.Double.valueOf(str) 或 Double.parseDouble(str);


基本数据类型 转 字符串那个就不提了,反正也太鸡肋了。有简便方法~


为什么有包装类?

因为泛型集合的真正类型是Object,Object不能接基本类型,只能是基本类型的包装对象(包装类)才行【为了万物皆对象】。

八种基本数据类型除了int ->Integer 和 char -> Character,其余的包装类都是首字母大小即可。

泛型这块的知识点就差不多讲完啦~bye

"只要一直在跑,就肯定错不了!"

转载自:https://juejin.cn/post/7400190595283894312
评论
请登录