2010-11-18 5 views
1

J'ai classes Suiveurs (il est juste un exemple simplifié):Réflexion en classe java générique

public abstract class Material { 
    public abstract String name(); 
    /* ... */ 
} 

public class Wood extends Material { 
    @Override 
    public String name() { 
     return "<WOOD>"; 
    } 
    /* ... */ 
} 

public class Metal extends Material { 
    @Override 
    public String name() { 
     return "{Metal}"; 
    } 
    /* ... */ 
} 

public class Car<T extends Material> { 
    public void printName() { 
     System.out.println(T.name()); // Here is the problem! 
    } 
    /* ... */ 
} 

public class Main { 
    public static void main(String[] args) { 
     Car<Wood> myCar1 = new Car<Wood>(); 
     Car<Metal> myCar2 = new Car<Metal>(); 
     myCar1.printName(); 
     myCar1.printName(); 
    } 
} 

Le problème est indiqué dans le code.

+0

Je ne pense pas que la question n'a rien à voir avec reflection.Please changer le nom du titre et l'étiquette. Non – Emil

Répondre

2

Voici un problème:

name est méthode d'instance (non statique), mais vous essayez de l'appeler comme statique.

Cela devrait fixer

public class Car<T extends Material> { 
    public void printName(T material) { 
     System.out.println(material.name()); 
    } 
    /* ... */ 
} 
+2

qui ne fonctionne pas ... tout d'abord vous ne pouvez pas remplacer les méthodes statiques, donc cela n'a pas de sens. – aioobe

+0

Je veux vraiment la méthode du « nom » était 'static'. Mais si ce n'est pas possible, je dois remodeler mon design. Merci beaucoup. – barroco

+1

Mais cela ne fonctionnera pas. 'Méthodes static' ne sont pas virtuelles, vous finirez toujours avec' Material.name() 'dans ce cas. – aioobe

1

Le problème est que vous essayez d'appeler une méthode d'instance sans avoir une instance de l'objet sur lequel l'appeler.

1

Il y a beaucoup de malentendus dans votre question:

  1. name() n'est pas une fonction statique, therfore vous avez besoin d'une instance d'un objet matériel pour l'appeler.
  2. même si name() étaient statiques, vous ne pouvez pas appeler une méthode statique à partir d'un nom générique.

Une solution? Créer une énumération de matériel:

public enum Material { 
    WOOD("wood"), 
    METAL("metal"); 

    private final String name; 

    Material(String name) { 
     this.name = name; 
    } 
} 

Et dans la classe de voiture est devenu:

public class Car { 
    private final Material m; 

    public Car(Material m) { 
     this.m = m 
    } 

    public void printName() { 
     System.out.println(m.name); 
    } 
    /* ... */ 
} 
0

T définit le type et le name() doit être statique d'être appelé dans ce contexte. En outre, considérez:

public class Car<T extends Material> { 
    protected T material; 
    // initialize material in constructor or wherever you want. 
    .... 
    public void printName() { 
     System.out.println(material.name()); // there is no problem 
    } 
    /* ... */ 
} 
3

C'est probablement comment je l'aurais implémenté. Si c'est satisfaisant ou pas pour votre situation, je ne peux pas le dire.

enum Material { 

    WOOD("<WOOD>"), 
    METAL("{Metal}"); 

    String name; 
    private Material(String name) { 
     this.name = name; 
    } 
    public String toString() { 
     return name; 
    } 
} 

class Car { 
    Material material; 
    public Car(Material material) { 
     this.material = material; 
    } 
    public void printName() { 
     System.out.println(material); 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
     Car myCar1 = new Car(Material.WOOD); 
     Car myCar2 = new Car(Material.METAL); 
     myCar1.printName(); 
     myCar2.printName(); 
    } 
} 
0

Cela ne marchera jamais, puisque votre « T » est seulement un « indice du compilateur », et vous ne pouvez pas accéder à la classe définie par T lors de l'exécution, sauf si vous faites référence explicitement dans vos fonctions.

Ce n'est pas comment les médicaments génériques java travail: lorsque vous compilez votre code, toute référence à bois et métal est perdu, et vos 2 objets « voiture » sont identiques.

Essayez ceci:

myCar1 = new Car<Wood>(); 
System.out.println(myCar1 instanceof Car<Metal>); 
Questions connexes