泛型·学习笔记

"嗨,阿米戈!"

"嗨,艾莉!"

"今天,Rishi 和我将向大家介绍仿制药。"

"等等,我想我几乎什么都知道了。"

"几乎所有,但不是所有。"

"真的吗?好吧,我准备好倾听了。"

"那我们开始吧。"

"在 Java 中,泛型是具有类型参数的类。"

"至于为什么要发明泛型,看代码中的注释:"

例子

复制代码
ArrayList stringList = new ArrayList();
stringList.add("abc"); // Add a string to the list
stringList.add("abc"); // Add a string to the list
stringList.add( 1 ); // Add a number to the list

for(Object o: stringList)
{
 String s = (String) o; // There will be an exception here when we get to the integer
}

如何使用泛型解决问题:

例子

复制代码
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("abc"); // Add a string to the list
stringList.add("abc"); // Add a string to the list
stringList.add( 1 ); // There will be a compilation error here

for(Object o: stringList)
{
 String s = (String) o;
}

"这段代码根本无法编译,并且在编译期间会注意到由于添加错误的数据类型而导致的错误。"

"是的,我已经知道了。"

"好,好。重复是学习之母。"

"但是 Java 的创建者在创建泛型时有点懒惰。他们没有制作带有参数的完整类型,而是进行了巧妙的优化。实际上,他们没有向泛型添加任何有关类型参数的信息。相反,所有的编译过程中会发生魔法。"

泛型代码

复制代码
List<String> strings = new ArrayList<String>();
strings.add("abc");
strings.add("abc");
strings.add( 1); // Compilation error

for(String s: strings)
{
 System.out.println(s);
}

真正发生了什么

复制代码
List strings = new ArrayList();

strings.add((String)"abc");
strings.add((String)"abc");
strings.add((String) 1); // Compilation error

for(String s: strings)
{
 System.out.println(s);
}

"那很光滑。"

"是的,但是这种方法有一个副作用。 泛型类内部不存储类型参数的信息。 这种方法后来被称为类型擦除。"

"换句话说,如果你有自己的带有类型参数的类,你就不能在类中使用关于它们的信息。"

泛型代码

复制代码
class Zoo<T>
{
 ArrayList<T> pets = new ArrayList<T>();

 public T createAnimal()
 {
  T animal = new T();
  pets.add(animal)
  return animal;
 }
}

真正发生了什么

复制代码
class Zoo
{
 ArrayList pets = new ArrayList();

 public Object createAnimal()
 {
  Object animal = new ???();
pets.add(animal)
  return animal;
 }
}

"在编译期间,所有参数类型都被替换为 Object。并且在类内部没有关于传递给它的类型的信息。"

"是的,我同意,那不是最好的。"

"没那么可怕,我稍后会告诉你如何解决这个问题。"

但还有更多。Java 允许您为类型参数指定父类型。extends 关键字用于此。例如:

泛型代码

复制代码
class Zoo<T extends Cat>
{
 T cat;

 T getCat()
 {
  return cat;
 }

 void setCat (T cat)
 {
  this.cat = cat;
 }

 String getCatName() { return this.cat.getName(); }
}

真正发生了什么

复制代码
class Zoo
{
 Cat cat;

 Cat getCat()
 {
  return cat;
 }

 void setCat(Cat cat)
 {
  this.cat = cat;
 }

 String getCatName() { return this.cat.getName(); }
}

"注意两个事实:"

"首先,你不能只传递任何类型作为参数------你只能传递 Cat 或继承 Cat 的类。"

"其次,在 Zoo 类内部,类型 T 的变量现在可以调用 Cat 类的方法。 右侧的列解释了原因(因为 Cat 将在任何有 T 的地方被替换)"

"是的。如果我们说 Cat 或 Cat 的子类作为类型参数传递,那么我们可以肯定类型 T 将始终具有 Cat 类的方法。"

"嗯,这很聪明。"

相关推荐
Wang's Blog7 分钟前
Java 项目实战: 交友项目 - 圈子功能的表设计方案
java·开发语言·交友
时间售卖铺11 分钟前
MySQL DML 与 DQL 语句详解
运维·数据库·mysql·云原生
codeejun19 分钟前
每日一Go·MySQL-9、索引存储结构|页分裂、页合并、索引高度与磁盘
数据库·mysql
Pniubi22 分钟前
事务(Spring&MySQL)
数据库·sql·spring
文丑颜不良啊25 分钟前
LeetCode601~625题目解析
java·leetcode
MrGet25 分钟前
一步一步学Python(三):文件读写
python
文丑颜不良啊33 分钟前
LeetCode651~675题目解析
java·leetcode
frjc37 分钟前
Spring WebFlux SSE 长连接,可以替换为 Java 21 虚拟线程吗?
java·人工智能·spring·ai·ai编程
是Yu欸1 小时前
先让 T1 Pro 传回一张好用的图:JPEG 抓拍、RTSP 视频与方向校正
python·机器人·音视频
伞伞悦读1 小时前
【第60期】特征值不是重要性:Python 特征分解与 PCA 的前置判断
python