2014-10-04 15 views
6

costruttori Java possono essere generici: http://docs.oracle.com/javase/tutorial/java/generics/methods.htmlJava costruttori generici sintassi e scopo

Tuttavia non riesco a trovare un buon esempio di come dichiarare e invocare il costruttore generico. Inoltre non capisco lo scopo del costruttore generico poiché l'ambito del parametro type è limitato al costruttore.

Avere classe con il costruttore generico:

public class MyClass { 

    public <T> MyClass(T data) { 
     // ... 
    } 

} 

invochiamo come:

MyClass obj = new <Integer>MyClass(12); 

Quindi le mie domande sono:

  1. Qual è lo scopo del costruttore generica? Puoi mostrare un esempio da JDK o dal tuo esempio?

  2. Perché dichiarazione come

    Integer val = new <String>Integer(100); 
    

viene compilato senza errori, anche quando la classe Integer non ha costruttore generica?

+0

Solo un ipotesi, ma credo che sia perché compila il tipo è fuori posto Il modo corretto sarebbe 'nuovo Intero (100);' o 'nuovo MyClass (12);'. – Tom

+2

@Tom 'new MyClass ' sarebbe usato se * la classe stessa * avesse un parametro, come 'classe MyClass '. Ma in questo caso, è il costruttore che ha il parametro, e scriverlo in questo modo è il modo standard di chiamare metodi o costruttori generici. – Marco13

risposta

6

Uno scopo di un costruttore generico può essere lo stesso di alcuni metodi generici: per assicurarsi che diversi argomenti facciano riferimento allo stesso tipo.

consideri il seguente esempio (sì, è un po 'forzato, ma dovrebbe mostrare il punto):

import java.util.ArrayList; 
import java.util.Collection; 

public class GenericConstructorTest 
{ 
    public static void main(String[] args) 
    { 
     Collection<String> strings = new ArrayList<String>(); 
     ClassWithParam c0 = new <String>ClassWithParam("String", strings); 
    } 
} 

class ClassWithParam 
{ 
    public <T> ClassWithParam(T data, Collection<T> collection) 
    { 
     collection.add(data); 
    } 
} 

Non importa per la classe o il suo costruttore che tipo esattamente sia utilizzata. È importante solo sapere che la collezione che è stata data come secondo argomento può prendere elementi del tipo che è stato dato come primo argomento.

(Mi piacerebbe mostrare un esempio più realistico e pratico, ma penso che sia piuttosto raramente necessario parametrizzare un costruttore in questo modo, e si potrebbe anche considerare che questo è solo un "effetto collaterale" della possibilità di parametrizzare metodi, e il fatto che non v'è alcuna ragione per non consentire esplicitamente questo per i costruttori ...)


EDIT secondo la richiesta nel commento, e l'esempio in cui gli argomenti dati sono atually usato. È ancora piuttosto inventato. Esempi più realistico potrebbe essere strutturalmente simili e fare riferimento ad alcuni tipi di ascoltatori, ma comporterebbe molto più codice:

public class GenericConstructorTest 
{ 
    public static void main(String[] args) 
    { 
     Callback<String> callback = new Callback<String>(); 
     ClassWithParam c0 = new <String>ClassWithParam("String", callback); 
     c0.execute(); 
    } 
} 

class ClassWithParam 
{ 
    private Runnable runnable; 

    public <T> ClassWithParam(final T data, final Callback<T> callback) 
    { 
     runnable = new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       callback.call(data); 
      } 
     }; 
    } 

    void execute() 
    { 
     runnable.run(); 
    } 
} 

class Callback<T> 
{ 
    void call(T t) 
    { 
     System.out.println("Called with "+t); 
    } 
} 

Il secondo esempio che hai postato

Integer val = new <String>Integer(100); 

non compila in Eclipse con Java 7.Si lamenta

Il costruttore Intero (int) di tipo Integer non è generico; esso non può essere parametrizzato con argomenti

In Java 8, questo è permesso, anche se emette ancora un avvertimento:

argomenti di tipo non utilizzati per il costruttore generico non Integer (int) di tipo Integer; non deve essere parametrizzato con argomenti

(Se questa differenza è ciò che si sta effettivamente interessati, si potrebbe considerare chiedendo questo come una questione a sé stante)

+3

FWIW, * compila * con il compilatore Sun Java 7. Non so se sia il compilatore Sun o il compilatore Eclipse che è in errore, però. –

+0

@OliverCharlesworth Interessante, avrei dovuto provare questo. Non stampa nemmeno un avvertimento. Forse scriverò il JLS per vedere se questo può essere considerato un bug nel compilatore Eclipse (da una breve websearch, sembra che ci siano * bug * correlati, ma non ne ho ancora trovato uno che corrisponda esattamente a * questo * caso) – Marco13

+0

È difficile immaginare un uso pratico di tale costruttore: modifica la raccolta di input ma non può quindi memorizzarlo in un campo di classe o semplicemente restituirlo. – ako