2014-05-23 48 views
7

Si prega di passare attraverso l'intera domanda per avere un'idea completa.Perché non posso fare un riferimento statico al metodo statico di una classe interna su una classe generica?

prima lasciare la classe Box è dato come segue: -

public class Box <T>{ 
    private T t; 

    public void set(T t){ 
     this.t = t; 
     System.out.println("value:\n"); 
     System.out.printf("%s", t.toString()); 
    } 
    public T get() { 
     return t; 
    } 
    static int retInt(){ 
     return 5; 

    } 
    public <U extends Number> void inspect(U u){ 
      System.out.println("T: " + t.getClass().getName()); 
      System.out.println("U: " + u.getClass().getName()); 
     } 

} 

classe generica Util come riportato qui di seguito: -

public class Util<T>{ 
    private T t; 

    //Generic method 
    public <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) { 
     return p1.getKey().equals(p2.getKey()) && 
       p1.getValue().equals(p2.getValue()); 
    } 

    /* Static generic or non-generic methods can be declared in generic class 
     but they can not make use of generic parameter type(as generics static  
     methods using class type variable must know the type argument 
     (i.e value of type parameter); and knowledge of type argument is 
     possible only when object of same generic class are instantiated 
     (meaning assigning value of generic type parameter <T> or better to 
     say declared object have it's type argument; for example 
     as in List<T> replace T with Integer,String, Float etc); 
     but static method may be called without having 
     instance of class; so such declaration for static generic method are 
     not allowed) here it is <T>; like for example as shown below 

     public static int checkFun(T t){ 
      return 5; 
     } // this generate compiler error complaining "can not make static 
     // reference to non-static type T".   
    */ 


    public static <K> boolean cmp(Box<K> b1, Box<K> b2){ 
     // implement comparator to compare but here 
     return true; 
    } 

    // Inner class Pair 
    public class Pair <K, V> { 
     private K key; 
     private V value; 

     // Generic constructor 
     public Pair(K key, V value) { 
      this.key = key; 
      this.value = value; 
     } 

     public void setKey(K key) { 
      int i = 6; 
      if(i >4 || i<9); 
      this.key = key; 
     } 

     public void setValue(V value) { 
      this.value = value; 
     } 

     public K getKey(){ 
      return key; 
     } 

     public V getValue(){ 
      return value; 
     } 

    } 

    public void main1() {   
     //The complete syntax for invoking this method would be: 
     // <Integer, String> new Util<T>(). 
     Pair<Integer, String> p1 = new Pair<Integer,String>(1, "apple"); 
     Pair<Integer, String> p2 = new Pair<Integer, String>(2, "pear"); 
     boolean same = compare(p1, p2); 
     //boolean same = true; 
     if(same)System.out.println("it is true: they are the same"); 
     else System.out.println("nah! they are not the same..."); 

     //boolean sm = compare(); 
    } 

    public static void main (String[] args) /*throws FileNotFoundException */{ 
     //new Util<Integer>(). main1(); 

     Util<Integer> util = new Util<>(); 
     util.main1(); 
    } 
} 

Sopra codice compila ed esegue bene, il mio disagio si trova qui:

Se si aggiunge il modificatore static al metodo

public <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) -------(1) 
// called in method main1() 

e renderlo

public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2)  -------(2) 

allora compilatore si lamenta che non può fare un riferimento statico del tipo non-statico pari che metodo simile

public static <K> boolean cmp(Box<K> b1, Box<K> b2) -------(3) 

anch'esso statico ma doesn Mi lamento. Anche se non usiamo il parametro di tipo <T> in entrambi i metodi but a big but nel metodo stiamo parlando da eq-1 l'argomento che utilizza è dalla classe interna Pair (quindi il ragionamento della mia ambiguità può essere spiegato con riferimento a questa funzione).

Ma ancora; logicamente, ritengo che l'aggiunta del modificatore static al metodo in eq-1 non dovrebbe generare errore in fase di compilazione perché ovunque venga chiamato il metodo in eq-2 sarà chiamato a chiamare tale metodo con l'argomento corretto in eq-2 e dovrebbe essere chiamato come un metodo statico.

Domanda: - Qual è la spiegazione per non usare il modificatore static per il metodo:

public <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) 

Grazie per l'aiuto.

risposta

9

Il motivo di ciò è il parametro type sulla classe Util e la coppia inner class non è statica. Poiché Pair è una classe interna non statica, può utilizzare il parametro di tipo T di Util (anche se in questo caso non lo fa). Pertanto, quando viene utilizzato Pair, è necessario specificare una T, accedendovi nel contesto di un'istanza di Util (dove T è implicitamente disponibile) o qualificando accedendovi tramite uno specifico Util<T>, ad es. Util<Integer>.Pair<String,Object>. Un altro modo per pensarci è che il tipo di Coppia dipende dal parametro type di Util e Util<String>.Pair<K,V> non è compatibile con Util<Object>.Pair<K,V>.

Per mantenere il parametro di tipo T sul Util e mantenere coppia come una classe interna non statica, è possibile modificare la firma di confrontare

public static <T, K, V> boolean compare(Util<T>.Pair<K, V> p1, Util<T>.Pair<K, V> p2) 

o

public static <K,V> boolean compare(Util<?>.Pair<K,V> p1, Util<?>.Pair<K,V> p2) 

che è possibile perché l'istanziazione di T non è rilevante per il corpo del metodo.

In alternativa, dal momento che coppia non si riferisce a niente (non statico) all'interno di Util è possibile modificare la definizione di coppia per essere

public static class Pair <K, V> { /* ... */ } 

Infine per completezza, se Util non ha avuto un tipo parametro poi

public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) 

e

public class Pair<K, V> { /* ... */ } 

sarebbe più che bene.

+0

, Grazie amico.Come credo che hai coperto quasi tutto il pezzo. Avevo una specie di soluzione al problema ma la prima spiegazione che hai dato per mantenere il parametro tipo T ha parzialmente rimosso il mio dubbio. Ma ancora non riesco a capire come il compilatore si lamenta di non usare il modificatore statico. Hai detto preventivo ** Quindi la Coppia deve essere usata in un contesto in cui esiste una particolare T disponibile ** unquote. Come ho detto nella mia domanda (e credo, dove potrei sbagliarmi) che ** T ** saranno disponibili informazioni durante la creazione dell'oggetto di ** Coppia ** classe (qui nel metodo ** main1() ** che è non statico). – zeal

+0

come ho detto sopra metodo di chiamata ** main1() ** richiede argomento (valore) per digitare il parametro in modo che l'oggetto della classe ** Pair ** avrà automaticamente il valore di ** T **, che oggetto della classe Pair può utilizzare (anche se qui non li usano). Quindi, per favore getta un po 'di luce sul problema qui in modo che la mia confusione venga rimossa. – zeal

+0

@zeal hai ragione che è un po 'poco chiaro, ho cambiato quella frase della risposta. Spero che ora abbia più senso. Ho anche aggiunto alcune note sui caratteri jolly generici che mancavano prima. –