2009-08-19 1 views
9

В чем преимущество создания универсального конструктора для не общего класса? 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 
} 

ответ

4

Единственное использование, что я могу думать, если бы конструктор необходимо используйте общий объект во время его запуска, но не сохранили этот объект после его завершения.

Например:

<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()); 
    } 
} 

Это, скорее всего, только то, что разработчики языка решили сделать только в случае, если кто-то хотел его, так как не было никаких причин, чтобы помешать людям делать это.

+0

Да, это позволяет использовать общие методы для конструкторов (но зачем вы хотите?). Я никогда не видел его в дикой природе. Для моих денег это сложность, с которой язык мог бы обойтись без (поскольку C# позже, когда он представил свою версию Java-дженериков). –

0

Да, я думал об этом несколько раз.

Гипотетически (есть причины xx, почему это не так) было бы хорошо, если бы Generic-конструкторы могли определять формальный общий тип для всего класса (как это делает объявление универсального класса) ... То есть, если определить Generic конструктор позволит вам иметь общие поля в этом классе ...

например, если вы хотите, чтобы избежать обобщения:

EntityRequestCallback extends RequestCallback 

но вы хотели RequestCallback порождающим RequestCallback<E extends Entity>, вы не могли бы сделать это потому что только два типа запроса PUT/POST используют Entity. Только конструкторы для запросов PUT/POST содержат параметр Entity.

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; 

В этом конкретном примере обобщение является правильным выбором в любом случае, но бывают случаи, когда обобщения не будет.

Смежные вопросы