当前位置: 首页 > 知识库问答 >
问题:

为什么我必须投回Constructor.new实例?

颛孙正谊
2023-03-14

根据文档,newInstance()返回一个T:https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#newInstance()

所以,如果我有一个返回T的方法,为什么我必须强制转换构造函数的返回。newInstance()到T?

protected <T extends ParentClass> T getConfig() {
  return (T) _childClassConstructor.newInstance();
    

共有1个答案

朱鸿畅
2023-03-14

泛型是编译器想象的产物:运行时(java.exe)不知道它的意思,也不在乎,而且大多数情况下,甚至没有这些信息(“擦除”)。是的,公共签名确实包含泛型信息,但就运行时而言,它实际上是一个注释。

那么,它到底有什么用呢?

嗯,它把事情联系起来了。它可以告诉编译器:所以,我有这个方法,它需要2个参数。这两个参数可以是您喜欢的任何参数,但它们必须是相同的类型。如果不是,则运行时不会进行核心转储或其他任何操作,只是。。这意味着软件有缺陷。所以,如果您看到不符合此规则的代码,请将其标记为错误,以便我知道需要修复它。

这就是泛型所能做的。但幸运的是,这相当有用!

如果你使用泛型,而它们只出现在一个地方,那基本上是无用的,或者说是黑客行为。在这里,您已经这样做了:T只显示一次,作为这个方法的返回类型,其他任何地方都不会显示。实际上,这总是表明代码作者不了解java泛型的功能。

在这种情况下,您有效地完成了将其转换为巫术任意方法的工作—此方法将调整其返回类型,使其符合调用者的意愿。给定class Parent和class Joe extends Parent和class Jane extends Parent,则这将起作用:

Joe c = getConfig();

如何知道它的返回类型实际上是Joe?它不是。它适应你想要的样子。

这是一件坏事,因为如果你看代码,它实际上不是这样工作的:

class ConfigTool {
    private final Class<? extends Parent> c;

    public ConfigTool(Class<? extends Parent> c) {
        this.c = c;
    }

    public <T extends ParentClass> T getConfig() {
        return (T) c.newInstance();
    }
}

以及:

ConfigTool tool = new ConfigTool(Jane.class);
Joe joe = tool.getConfig();

将只编译。当然,在运行时也会爆发:getConfig()方法最终会生成Jane的一个实例,该实例不能分配给Joe类型的变量,这表明“这是如何修复代码”的答案并不简单,因为您所写的内容是无意义/不可能的。

你大概打算做以下两件事之一:

要么:

public ParentClass getConfig() {
    return c.newInstance();
}

当然,也许c是代表Joe的类实例,但也可能是Jane。API所能做出的唯一promise是,无论该类实例是什么,它所生成的任何实例都将可分配给Parent类型的变量。毕竟,Parent p=new Joe() 有效,就像父级p=new Jane()一样

没有必要涉及泛型。泛型更高一个“元”级别:它将类型系统本身转变为一种编程语言,在这里您不需要这样做。

您可能需要的另一种选择是将您的getConfig()方法的返回类型链接到此对象的类实例的特定类型:

class ConfigTool<T extends Parent> {
    private final Class<T> c;

    public ConfigTool(Class<T> c) {
        this.c = c;
    }

    public T getConfig() {
        return c.newInstance();
    }
}

请注意,在这段代码中,完全不需要强制转换,上面的代码是按照编写的方式编译的。泛型也很有用,因为T显示在两个地方:类

 类似资料:
  • 关于在最新版本的GCC和Clang中编译有几个问题:实验::filessystems链接器错误 但是现在< code>filesystem已经被c 17接受,所以不再需要< code>experimental或< code>-lstdc fs标志,对吗? 错了,我甚至不能 只给了我< code >实验版本,我怎么能包括正式接受的版本呢?

  • C++20概念的一个特点是,在某些情况下,您必须编写。例如,[expr.prim.req]/3中的这个示例:

  • 我知道不同的平台有不同的UI需求,但为什么我必须下载源代码并自己编译它呢?为什么我不能为我的平台下载一个可运行的版本?

  • 我正在为一个班级作业制作一个石头剪刀游戏,我正在尝试编写一个方法,根据用户获胜、计算机获胜还是平局,返回整数1、2或3。我们不能简单地返回信息“你赢了!”或者“你输了!”或“平局!”在该方法中,我们必须返回整数。然而,当我这样键入代码时,Eclipse中会出现一个编译器错误警告,告诉我“此方法必须返回int类型的结果。”这不是我在这里要做的吗?帮助谢谢

  • 如果我有一个Kotlin函数 我想从Java调用,我必须这样做: 看起来很难看。为什么我不能像

  • 问题内容: 如果我制作了一个不实现Serializable的Composite-id类,例如: 发生错误,例如: hibernate实体类不必是可序列化的。那么,为什么Composite- id类必须实现Serializable?我读了这个主题,但是没有给我足够的信息。 问题答案: 会话对象需要可序列化,因此它引用的所有对象也必须可序列化。id用作索引会话中已加载对象的键。如果是Composite