执行通用 Java 类

我的理解是,通用 Java 类需要在类型上进行参数化才能使用。令我惊讶的是,以下示例代码(其中泛型类尚未参数化)执行时没有任何错误。


public class Box<T> {

  private T t;


  public static void main(String[] args) {

    System.out.println("It actually executed!!!!");

  }


  public void set(T t) { this.t = t; }


  public T get() { return t; }

}  

java Box

产生输出

It actually executed!!!!


在这种情况下,是否有隐式类型传递给泛型类?


慕运维8079593
浏览 124回答 4
4回答

德玛西亚99

您询问的方法是main(),如下所示(我将类和方法编辑到最低限度)。正如您所发现的,它有效。class Box<T> {&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; // do something&nbsp; &nbsp; }}该方法很好,因为它与泛型类型没有关联T。这里,main是一个静态方法,这意味着它在没有对象实例的情况下被调用。泛型不适用于静态方法(或字段),但上面的示例并没有这样做。这是一个不同的示例,尝试定义一个也使用的静态方法T(但它不起作用):class Box<T> {&nbsp; &nbsp; public static void bar(T args) {&nbsp; &nbsp; &nbsp; &nbsp; // do something&nbsp; &nbsp; }}这个例子是一个静态方法,将在没有对象实例的情况下被调用 - 就像这样:Box.bar(someArgs)- 但这是无效的。如果不首先创建某个泛型类型的实例Box,编译器如何知道它T是什么?可以定义一个静态方法来使用泛型类型,但该方法完全独立于T您的示例。对于某些单独的泛型类型,有一种方法可以做到这一点X:class Box<T> {&nbsp; &nbsp; public static <X> void foo(X input) {&nbsp; &nbsp; &nbsp; &nbsp; // do something&nbsp; &nbsp; }}你可以这样称呼它:Box.foo("");

30秒到达战场

您不是“在这里执行课程”。main()相反,您正在类中执行静态方法。允许您这样做的原因是类型擦除。泛型类型仅在编译代码时强制执行。在不声明任何引用或创建Box<T>编译器实例的情况下,没有理由检查泛型类型。当您运行程序时,由于类型擦除,解释器对通用代码一无所知,因此它愉快地运行程序。

绝地无双

Java 与 C 不同。不存在“对于每一个可以想象到的 T/代码库中实际使用的每一个 T 都有一个 Box 类的变体”。只有盒子。例如:new&nbsp;Box<String>().getClass()&nbsp;==&nbsp;new&nbsp;Box<Integer>().getClass()&nbsp;//&nbsp;this&nbsp;is&nbsp;true您不会加载单独的类等。这确实有一些副作用: 不可能从String变量 x 中导出:&nbsp;Box<?> x = new Box<String>();- 该信息现在已经消失了。这称为擦除。实际上,泛型几乎完全是编译器想象的产物。这就像在打字稿中输入信息等:它在编译时就存在,编译器将使用它来告诉您类型未对齐(编译器错误),但是一旦编译器接受所有信息,它就会被编译为一种在运行时完全消除此信息的形式*。这就是为什么上面的代码可以毫无抱怨地工作:你有一个静态方法,<T>这里甚至不存在。让我们放大一下 get 和 set 方法以及 't' 字段: 它们完全是这样的:private Object t; public void set(Object o) { this.t = t; } public Object get() { return t; }只有一个例外:如果在编译时,它没有意义,编译器将拒绝编译它。此外,对于呼叫的任何呼叫者get,都会默默地包含一个演员表。*)不完全是;签名中泛型的任何使用,因此,字段的类型、类自己的定义、和implements行extends以及方法的返回类型或参数类型中,都不会被消除,但它就像是对VM:VM不关心这些东西;它存在的唯一目的是,如果您调用javac类路径上的某些内容,javac 在与这些成员交互时知道泛型是什么。就这些。

慕哥6287543

Java 内部的泛型旨在为您的对象提供编译时类型安全性。对于您的情况,它根本不访问类中方法t内部的变量。main()这样java就会愉快地编译并运行程序了。如果您Box在main()方法内实例化该类:Box b = new Box(); // this is will produce "unsafe operations" noteb.set("this is the string");System.out.println(b.get().getClass().getName());根据最后一个变量赋值,您将在此处获得一个字符串。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java