为什么需要泛型类型然后键入 reasure,尽管我们可以使用对象 Pojo



我有这样的代码:

public class Crate<T> {
private T contents;
public T emptyCrate() {
return contents;
}
public void packCrate(T contents)
{
this.contents = contents;
}
}

现在我们知道 - 最后它将被"转换"为以下代码:

public class Crate {
private Object contents;
public Object emptyCrate() {
return contents;
}
public void packCrate(Object contents) 
{
this.contents = contents;
}
}

那么,如果我已经可以创建像ObjectBased 这样的类,为什么我们需要创建一个泛型呢?

当人们谈论类型擦除时,他们通常关注泛型类本身。但是泛型还有另一个重要的地方:调用站点。

例如,如果您有以下代码:

Crate<Integer> intCrate = new Crate<>();
intCrate.packCrate(0);
Integer contents = intCrate.emptyCrate();

然后,当它被编译时,它实际上变成了:

Crate intCrate = new Crate();
intCrate.packCrate(0);
Integer contents = (Integer) intCrate.emptyCrate();
// ^ Important! This cast.

即有自动插入的铸件。此外,隐式地,有一个检查packCrate的参数是否与Integer兼容,所以你不能写:

intCrate.packCrate("hello");

现在,您可以在没有泛型的情况下执行此操作,自己放入这些强制转换,但编译器无法帮助您了解放入Crate的内容。你可以写这样的东西:

Crate crate = new Crate();
crate.packCrate(0);
String contents = (String) crate.emptyCrate();

这将在运行时失败,因为板条箱包含一个Integer,而不是一个String

泛型只是帮助您不必记住允许传递给实例的内容,以及您将从中得到什么。

你看,java代码被翻译成字节码。那么为什么不用字节码编写程序呢?他们还是被翻译了?或者,准确地说:JIT 编译器会在某个时候将大多数字节码转换为机器代码。那你为什么坚持用java源代码,而不是二进制机器码呢?!

我想上面的问题清楚地表明了我的观点:泛型允许你向人类读者表达意图。它们允许您编写更好的源代码;它们使编译器能够对您的输入进行某些类型的检查 - 正如Andy Turner在另一个答案中很好地总结的那样。

这就是编程语言提供给你的任何抽象的重点:它们帮助你程序员创建源代码,以简洁的方式表达"需要做什么",使人类读者更容易理解正在发生的事情,以及为什么

它会被变成什么并不重要。

相反,编译阶段很重要。泛型保证编译类型的类型安全(修复编译时错误比运行时错误容易得多(。

它还消除了强制转换,并实现了通用算法的能力。

Java 中的所有集合都是泛型的。这是使用泛型的最佳示例。例如,您创建类列表。它将容纳哪些类型的对象?当您创建类List时,您不知道它将包含哪些类型,因此您使用泛型。当你使用List类时,你说,你想把Integers(new List<Integer(。

泛型中的模板参数用于编译时安全。编译器会窒息,如果你写例如:

Crate<Integer> cr;
Object o;
cr.packCrate(o);  // compilation error here

它还可以声明任何用作参数的类都将实现一些方法:

Interface I {
void myMethod();
}
class Crate<T extends I> {
private T contents;
...
public void applyMethod() {
contents.myMethod();      // T shall implement myMethod
}
}

事实上,一切都可以通过显式强制转换来完成,但你只会得到运行时错误,而泛型允许编译时检测错误。

相关内容

最新更新