【问题标题】:Benefit of Generic Constructors泛型构造函数的好处
【发布时间】:2011-10-12 21:06:54
【问题描述】:

为非泛型类使用泛型构造函数有什么好处? Java 规范允许以下内容:

class NonGeneric {
  <T> NonGeneric() { }
  ...
  NonGeneric ref = new <String> NonGeneric();
}

能否提出一个现实的例子来说明它何时增强了类的类型安全性?怎么会比一开始就使用 Generic 更好呢。

我了解 Java 设计者希望构造函数与方法更加一致。 鉴于构造函数可能有副作用,泛型构造函数可以使用泛型来改变一些不保留引用的参数,如

<T> NonGeneric(T obj, List<T> list) {
  list.add(obj);
  // Don't hold a reference to list
}

【问题讨论】:

    标签: java generics polymorphism


    【解决方案1】:

    我能想到的唯一用途是构造函数在运行时需要使用通用对象,但在完成后不存储该对象。

    例如:

    <T> NonGeneric(T[] blank, List<T> list) {
        // Sort that list
        T[] array = list.toArray(blank);
        Arrays.sort(array);
    
        // Pull out the values as strings
        this.list = new ArrayList<String>(array.length);
        for (T value : array) {
            this.list.add(value.toString());
        }
    }
    

    这很可能只是语言设计者决定做的事情,以防万一有人想要它,因为没有理由阻止人们这样做。

    【讨论】:

    • 是的,它允许用构造函数替换泛型方法(但你为什么要这样做?)。我从来没有真正在野外见过一个。对我来说,这是一种语言本可以没有的复杂性(正如 C# 后来在引入其 Java 泛型版本时所做的那样)。
    【解决方案2】:

    是的,我多次考虑过同样的问题。

    假设(有 xx 原因为什么它不是这样)如果泛型构造函数可以为整个类定义正式的泛型类型(就像泛型类声明那样)会很好......也就是说,如果定义 Generic构造函数会让你在那个类中有通用字段......

    例如,如果您想避免泛化:

    EntityRequestCallback extends RequestCallback
    

    但是您希望 RequestCallback 是通用的 RequestCallback&lt;E extends Entity&gt;,您不能这样做,因为只有两种类型的请求 PUT/POST 使用实体。只有 PUT/POST 请求的构造函数包含实体参数。

    public class RequestCallback {
    
            /** GET/DELETE requests */
        public RequestCallback(String gttUrl, HttpMethod method,) {
            this.gttUrl = gttUrl;
                    this.method = method;
        }
    
            /** PUT/POST requests */
        public RequestCallback(String gttUrl, HttpMethod method, Entity entity) {
            this.gttUrl = gttUrl;
                    this.method = method;
            this.entity = entity;
        }
    }
    

    但是该类不能是通用的,因为您将为没有实体的请求创建 RequestCallback,这意味着您将实例化

    new RequestCallback();  //without specifying generic parameter - worse than nothing
    

    所以这里唯一可能的方法是泛化:

    EntityRequestCallback<E extends Entry> extends RequestCallback
    

    这样您就可以拥有通用字段:

    public E entity;
    

    在这个特定示例中,无论如何,泛化是正确的选择,但在某些情况下,泛化不会。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      • 2019-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-12
      相关资源
      最近更新 更多