泛型·学习笔记

"嗨,阿米戈!"

"嗨,艾莉!"

"今天,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 类的方法。"

"嗯,这很聪明。"

相关推荐
xcl09255 小时前
商超智能运营实战:数据驱动提升门店效率与体验指南
java·mfc·宠物
Flynt7 小时前
OpenJDK禁AI代码半年了,现在执行得怎么样?答案是:全靠自觉
java·开源·ai编程
这个DBA有点耶12 小时前
2026年分布式数据库有哪些主流选择?先评估这5个维度再决定
数据库·分布式·dba
古法安卓12 小时前
Android-日志系统源码解析
android·java·android studio
用户77833661321114 小时前
用 React Hook 封装搜索数据:useSerp 的防抖、缓存与错误处理
python·api
小夏coding14 小时前
从"一把梭"到"精妙拆解" —— 滑动窗口计时框架的设计演进
java·后端
这个DBA有点耶15 小时前
从MySQL 5.7到8.0:JSON查询性能差在哪?虚拟列索引vs多值索引怎么选
数据库·mysql·架构
胡写代码15 小时前
数据库审计字段,别再每张表各写一套了——我统一成这 6 个字段
数据库
MacroZheng15 小时前
同事问我:"Claude Code经常失忆,不怕它把项目搞炸?",我:"怕,三个Markdown文件给它装个永不丢失的外置大脑!"
java·人工智能·后端
十年Java程序媛16 小时前
深度实战:JDK21 虚拟线程 + HikariCP 生产正确配比、坑点、监控全套
java·spring boot