为了账号安全,请及时绑定邮箱和手机立即绑定

执行通用 Java 类

执行通用 Java 类

慕运维8079593 2024-01-05 14:58:30
我的理解是,通用 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!!!!在这种情况下,是否有隐式类型传递给泛型类?
查看完整描述

4 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞

您询问的方法是main(),如下所示(我将类和方法编辑到最低限度)。正如您所发现的,它有效。


class Box<T> {

    public static void main(String[] args) {

        // do something

    }

}

该方法很好,因为它与泛型类型没有关联T。这里,main是一个静态方法,这意味着它在没有对象实例的情况下被调用。


泛型不适用于静态方法(或字段),但上面的示例并没有这样做。这是一个不同的示例,尝试定义一个也使用的静态方法T(但它不起作用):


class Box<T> {

    public static void bar(T args) {

        // do something

    }

}

这个例子是一个静态方法,将在没有对象实例的情况下被调用 - 就像这样:Box.bar(someArgs)- 但这是无效的。如果不首先创建某个泛型类型的实例Box,编译器如何知道它T是什么?


可以定义一个静态方法来使用泛型类型,但该方法完全独立于T您的示例。对于某些单独的泛型类型,有一种方法可以做到这一点X:


class Box<T> {

    public static <X> void foo(X input) {

        // do something

    }

}

你可以这样称呼它:Box.foo("");


查看完整回答
反对 回复 2024-01-05
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

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



查看完整回答
反对 回复 2024-01-05
?
绝地无双

TA贡献1946条经验 获得超4个赞

Java 与 C 不同。不存在“对于每一个可以想象到的 T/代码库中实际使用的每一个 T 都有一个 Box 类的变体”。只有盒子。例如:

new Box<String>().getClass() == new Box<Integer>().getClass() // this is true

您不会加载单独的类等。

这确实有一些副作用: 不可能String变量 x 中导出: 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,都会默默地包含一个演员表。

*)不完全是;签名中泛型的任何使用,因此,字段的类型、类自己的定义、和implementsextends以及方法的返回类型或参数类型中,都不会被消除,但它就像是对VM:VM不关心这些东西;它存在的唯一目的是,如果您调用javac类路径上的某些内容,javac 在与这些成员交互时知道泛型是什么。就这些。


查看完整回答
反对 回复 2024-01-05
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

Java 内部的泛型旨在为您的对象提供编译时类型安全性。对于您的情况,它根本不访问类中方法t内部的变量。main()这样java就会愉快地编译并运行程序了。


如果您Box在main()方法内实例化该类:


Box b = new Box(); // this is will produce "unsafe operations" note

b.set("this is the string");

System.out.println(b.get().getClass().getName());

根据最后一个变量赋值,您将在此处获得一个字符串。


查看完整回答
反对 回复 2024-01-05
  • 4 回答
  • 0 关注
  • 52 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信