【问题标题】:Java generics constraint require default constructor like C#Java 泛型约束需要像 C# 这样的默认构造函数
【发布时间】:2019-11-10 01:14:40
【问题描述】:

在 C# 中,我可以对要求泛型类型具有默认无参数构造函数的泛型参数设置类型约束。我可以在 Java 中做同样的事情吗?

在 C# 中:

    public static T SomeMethodThatDoesSomeStuff<T>() where T : class, new()
    {
            // ... method body ...
    }

class 和 new() 约束意味着 T 必须是可以使用带零参数的 new 运算符调用的类。我对 Java 泛型知之甚少,我可以使用 extends 来命名所需的超类。我可以使用它(或任何其他支持的操作)来实现上述功能吗?

【问题讨论】:

标签: java generics


【解决方案1】:

没有;在 Java 中,典型的解决方案是传递一个类,而 doc 需要 0-arg 构造函数。这肯定不是静态检查,但不是太大的问题

/** clazz must have a public default constructor */
public static <T> T f(Class<T> clazz)
    return clazz.newInstance();

【讨论】:

    【解决方案2】:

    没有。

    由于类型擦除,&lt;T&gt; 的类型在运行时是未知的,所以本质上不可能实例化它。

    【讨论】:

    • 好吧。问题是,与Java 中的C# 相反,我们不能指定构造函数的约束——即指定接口必须提供的构造函数类型。如果我们能做到这一点,即使使用类型擦除,上面的方法也可以正常工作,而且非常有用。遗憾的是它不起作用,这意味着我们必须使用反射来实例化类型,并且必须在 API 中指定“必须提供参数较少的公共构造函数”——这是糟糕的设计缺陷。
    • 类型擦除并不是一个问题。该类在编译时是已知的,因此至少如果 JLS 中存在这样的约束,编译器可以轻松实施
    • @usr-local-ΕΨΗΕΛΩΝ:是的,但它不会很有用。
    • 就个人而言,但这只是我的看法,情况恰恰相反。昨天我们确实遇到了这样的问题,并且有类似的限制,我们可以在运行 Web 应用程序之前更容易地找到它
    【解决方案3】:

    Java 不进行结构类型,因此您不能将T 限制为具有特定的构造函数或static 方法。只允许子类型和超类型限制。

    所以,传递一个适当的抽象工厂。在这里或几乎在任何情况下使用反射是非常不合适的。现在有一个合适的通用 JDK 类型,形式为 java.util.function.Supplier

    public static T someMethodThatDoesSomeStuff<T>(
        Supplier<T> factory
    ) {
    

    调用为:

    驴驴 = someMethodThatDoesSomeStuff(BigDonkey::new);

    (方法引用不必是构造函数。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      相关资源
      最近更新 更多