Considérez les éléments suivants:
public class GenericTest {
static void print(int x) {
System.out.println("Int: " + x);
}
static void print(String x) {
System.out.println("String: " + x);
}
static void print(Object x) {
System.out.println("Object: " + x);
}
static <T> void printWithClass(T t) {
print(t);
}
public static void main(String argsp[]) {
printWithClass("abc");
}
}
8 Réponses :
Java prend en charge la méthode de remplacement (reliure de type dynamique), mais pas ce que vous essayez d'atteindre (la surcharge est un polymorphisme statique et non dynamique).
Pour réaliser ce que vous voulez réaliser en Java, vous avez besoin d'une double envoi. . P>
Modèle de visiteur devrait être votre ami ici. P>
Je vous ai écrit un échantillon de code. P>
public class Test {
public static void main(String argsp[]) {
PrintTypeImpl typeImpl = new PrintTypeImpl(new StringType(), new IntType(), new ObjectType());
typeImpl.accept(new PrintVisitor());
}
static final class PrintVisitor implements TypeVisitor {
public void visit(IntType x) {
System.out.println("Int: ");
}
public void visit(StringType x) {
System.out.println("String: ");
}
public void visit(ObjectType x) {
System.out.println("Object: ");
}
}
interface TypeVisitor {
void visit(IntType i);
void visit(StringType str);
void visit(ObjectType obj);
}
interface PrintType {
void accept(TypeVisitor visitor);
}
static class StringType implements PrintType {
@Override
public void accept(TypeVisitor visitor) {
visitor.visit(this);
}
}
static class ObjectType implements PrintType {
@Override
public void accept(TypeVisitor visitor) {
visitor.visit(this);
}
}
static class IntType implements PrintType {
@Override
public void accept(TypeVisitor visitor) {
visitor.visit(this);
}
}
static final class PrintTypeImpl implements PrintType {
PrintType[] type;
private PrintTypeImpl(PrintType... types) {
type = types;
}
@Override
public void accept(TypeVisitor visitor) {
for (int i = 0; i < type.length; i++) {
type[i].accept(visitor);
}
}
}
}
Parce que les génériques Java ne sont pas génériques comme vous pensez qu'ils sont. Lorsque le code Java générique est compilé, toutes les informations de type se sont effectivement supprimées, et seul le type de base connu reste. Dans ce cas, le type est Generics in Java n'est vraiment que le compilateur de compilateur, où le compilateur supprime les moulages qui seraient autrement nécessaires et induit une contrainte de temps de compilation. En fin de compte, tout ce qui reste est le type de base lorsque cela est réellement compilé en code octet. P>
Ce processus s'appelle Erasure de type forte>. Ce Question précédente est utile de comprendre ce qui se passe réellement. p> objet code>. P>
Parce que cela peut savoir que seul le temps d'exécution, mais en réalité, puisque Java est une langue compilée et non un scripté, il est décidé de temps de compilation.
Les génériques Java permettent "un type ou une méthode de fonctionnement sur des objets de différents types tout en fournissant Vous pouvez bien sûr essayer quelque chose comme: p> static <T extends String> void printWithClass(T t) {
print(t);
}
Ceci est à cause de Erasure de type Java : votre < pré> xxx pré>
est en fait un sucre syntaxique sur p> être juste, que "sucre syntaxique" permet au compilateur de faire très belle et Vérification importante, mais à l'exécution, il n'y a qu'une seule copie de la méthode Si vous avez des génériques expérimentées dans d'autres langues (C #, des modèles C ++, une tentative d'effondrement de type C ++, une effusion de type dépend de ce que vous savez, mais c'est ainsi que cela fonctionne sous la couverture. < / p> p> printwithclass code>, et il utilise java.lang.Object code> comme type de votre variable t Code>. P>
Il ne s'agit pas d'effacement de type, il s'agit des limites génériques disponibles à la compilation i>. Si nous utilisons chaîne: abc code>.
@Daniel Absolument - parce que la méthode deviendrait Void statique Imprimable (String T) Code> ALORS. Mais il resterait une méthode unique, avec un seul type, lié au moment de la compilation pour appeler une surcharge unique de la méthode Static Imprimer CODE>.
static void printWithClass(Object t) {
print(t);
}
Les génériques sont interprétés par le compilateur et appliquent une vérification de type supplémentaire pour éviter tout problème de coulée d'exécution. Les informations de type générique sont perdu au moment de l'exécution . Donc, au moment de l'exécution, quelle imprimable reçoit est simplement objet et non à la chaîne et donc votre résultat. P>
Il ne s'agit pas d'effacement de type, c'est un problème de compilation et la même chose se produirait si les génériques de la méthode stockée JVM sont enregistrées au moment de l'exécution. Il ne s'agit pas non plus de Type Inference - le compilateur infers Le problème est que lorsque le compilateur génère du code pour PrintWithClass code>, il nécessite une signature de méthode spécifique à associer à l'appel code> impression code>. Java n'a pas d'envoi multiple. Il ne peut donc pas mettre une signature vague dans la table de la méthode et décider quoi d'invoquer au moment de l'exécution. la seule limite supérieure sur t code> est objet code> strud>, donc la seule méthode qui correspond est impression (objet) code>. < / p>
Exemple supplémentaire pour clarifier:
Number: 1234
Voir cette question sur obtenir le type de T - Obtenez un type de classe générique à l'exécution < / a>