L'instanciation des génériques de type en java
Je voudrais créer un objet de Génériques de Type java. Veuillez indiquer comment puis-je obtenir le même.
Remarque: Cela peut sembler trivial Génériques Problème. Mais je parie.. il ne l'est pas. 🙂
supposons que j'ai la déclaration de classe, comme:
public class Abc<T> {
public T getInstanceOfT() {
//I want to create an instance of T and return the same.
}
}
- Comment venez-vous à propos de savoir ce que le "T"? La partie du programme "dit" vous qui T à utiliser?
- Je voudrais aussi suggérer que les Génériques FAQ: angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Vous devez vous connecter pour publier un commentaire.
Vous aurez à ajouter la gestion des exceptions.
Vous devez passer le type réel au moment de l'exécution, car il ne fait pas partie de l'octet de code après la compilation, il n'existe aucun moyen de le savoir sans prévoir expressément que c'.
T newT = this.getInstance(T.class)
ne compile pas.Dans le code que vous avez posté, il est impossible de créer une instance de
T
car vous ne savez pas quel type c'est:Bien sûr, il est possible si vous avez une référence à
Class<T>
etT
a un constructeur par défaut, il suffit d'appelernewInstance()
sur leClass
objet.Si vous sous-classe
Abc<T>
vous pouvez même travailler à travers le type d'effacement de problème et ne pas avoir à passer toutClass<T>
références autour de:Class<T>
encore ici, nous peut créer une instance.T
si vous savez que son type (parClass<T>
) et ce type a un constructeur par défaut. Ce n'était cependant pas le cas dans la posté code.Ce que vous avez écrit n'a aucun sens, génériques en Java sont destinés à ajouter la fonctionnalité de polymorphisme paramétrique à des objets.
Ça veut dire quoi? Cela signifie que vous voulez garder certains les variables de type de vos classes indécis, pour être en mesure d'utiliser vos classes avec de nombreux types différents.
Mais votre variable de type
T
est un attribut qui est résolu au moment de l'exécution, le compilateur Java compiler votre classe prouver type de sécurité sans essayer de savoir de quel type d'objet estT
il est donc impossible pour elle de laisser votre utilisation d'un variable de type dans une méthode statique. Le type est associé à une instance d'exécution de l'objet alors quepublic void static main(..)
est associé à la définition de la classe et à la portéeT
ne veut rien dire.Si vous souhaitez utiliser un variable de type à l'intérieur d'une méthode statique, vous devez déclarer la méthode générique (ce parce que, comme expliqué les variables de type d'une classe de modèle sont liées à son instance d'exécution), et non pas la classe:
cela fonctionne, mais évidemment pas avec
main
méthode, car il n'y a aucune façon de l'appeler de façon générique.MODIFIER: Le problème est qu'en raison de type d'effacement juste une classe générique est compilés et transmis à la JVM. Type checker vérifie juste si le code est en sécurité, car il s'est avéré à chaque type de d'une information générique est rejetée.
Pour instancier
T
vous besoin de connaître le type deT
, mais il peut être de plusieurs types en même temps, donc une seule solution exige seulement le montant minimum de réflexion est d'utiliserClass<T>
pour instancier de nouveaux objets:Bien sûr, cela implique que le type que vous souhaitez instancier:
Pour fonctionner avec différents types de constructeurs, vous avez à creuser plus profondément dans la réflexion.
default(T);
ouActivator.CreateInstance(typeof(T));
ArrayList
de créer un T exemple, vous venez de stocker une référence T que vous avez choisi précédemment.Type genericType = typeof(T)
sens parfait dans .net, qui sera résolu au moment de l'exécution et le compilateur ne dérange pas du tout avec cette ligne. Maintenant de ce que j'ai débogué ici, il semble que Java ne sait même pas à l'exécution de ce T représente, comme à tous.Vous avez besoin pour obtenir les informations de type statique. Essayez ceci:
À l'utiliser comme tel:
En fonction de vos besoins, vous pouvez utiliser
Class<? extends T>
à la place.La seule façon de l'obtenir pour fonctionner est d'utiliser Réifiée Génériques. Et ce n'est pas pris en charge en Java (pas encore? il a été prévu pour Java 7, mais a été reporté). En C# par exemple, il est pris en charge en supposant que
T
a un par défaut constructeur. Vous pouvez même obtenir le runtime type partypeof(T)
et obtenir les constructeurs parType.GetConstructor()
. Je ne fais pas de C#, donc la syntaxe peut être nul, mais il est à peu près ressembler à ceci:La meilleure "solution de contournement" pour cela en Java est de passer un
Class<T>
comme argument d'une méthode plutôt que plusieurs réponses déjà souligné.Tout d'abord, vous ne pouvez pas accéder au paramètre de type
T
dans la statique de la méthode main, seul sur la non-statique des membres de la classe (dans ce cas).Deuxième, vous ne pouvez pas instancier
T
parce que Java implémente des génériques avec Type d'Effacement. Presque toutes les informations génériques est effacé au moment de la compilation.Fondamentalement, vous ne pouvez pas faire ceci:
Voici un bon tutoriel sur les génériques.
Vous ne semblez pas comprendre comment les Génériques de travail.
Vous pouvez regarder la http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html
Fondamentalement, ce que vous pourrait faire est quelque chose comme
J'ai été la mise en œuvre de la même aide de l'approche suivante.
J'essayais de trouver une meilleure façon d'atteindre le même.
N'est-il pas possible?
clazz
dans le constructeur (vérifier ma réponse). Si vous le faites dans une méthode, alors il est presque vide de sens, puisque c'est juste un raccourci pour appelersomeObject.getClass().newInstance()
, qui ne semble pas ajouter beaucoup. Même si vous décidez de le faire de cette façon, vous n'avez pas besoin d'une classe générique; un statique méthode générique suffirait.Type D'Effacement Solution De Contournement
Inspiré par @martin réponse, j'ai écrit une classe d'assistance qui me permet de contourner le type d'effacement de problème. À l'aide de cette classe (et un peu moche truc), je suis capable de créer une nouvelle instance d'un type de modèle:
Le laid astuce ici est de faire de la classe
abstract
de sorte que l'utilisateur de la classe est obligé de sous-type il. Ici, je suis sous-classement en ajoutant{}
après l'appel au constructeur. Ceci définit une nouvelle classe anonyme et crée une instance de celle-ci.Une fois le générique de la classe est sous-typés avec concrètes types de modèle, je suis en mesure de récupérer les types de modèle.
Il semble que vous essayez de créer la classe qui sert de point d'entrée de votre application en tant que générique, et qui ne fonctionne pas... La JVM ne savez pas quel type c'est censé être de l'aide lorsqu'il est instancié comme vous démarrez l'application.
Cependant, si c'était le cas plus général, alors quelque chose comme ce que vous cherchez:
ou peut-être:
Abc
classe, il est tout simplement plus de sens d'avoir votre méthode principale dans une salle de classe qui appelleAbc
Il y a hacky des façons de contourner ce quand vous avez vraiment à faire.
Voici un exemple d'une méthode de transformation que je trouve très utile et fournit un moyen pour déterminer la classe d'un générique.
Cette méthode accepte une collection d'objets en entrée et retourne un tableau dont chaque élément est le résultat de l'appel d'un champ de lecture sur chaque objet de la collection d'entrée. Par exemple, disons que vous avez un
List<People>
et que vous voulez unString[]
contenant tout le monde son nom de famille.Le type de champ à la valeur retournée par le getter est spécifié par le générique
E
, et j'ai besoin d'instancier un tableau de typeE[]
pour stocker la valeur de retour.La méthode elle-même est un peu moche, mais le code que vous écrivez qui l'utilise peut être si beaucoup plus propre.
Noter que cette technique ne fonctionne que lorsque quelque part dans les arguments d'entrée il y a un objet dont le type correspond au type de retour, et vous pouvez la conception déterministe de la figure. Si les classes concrètes de vos paramètres d'entrée (ou de leurs sous-objets) peut rien vous dire sur les génériques, alors cette technique ne fonctionne pas.
Code complet est ici: https://github.com/cobbzilla/cobbzilla-utils/blob/master/src/main/java/org/cobbzilla/util/collection/FieldTransformer.java#L28
..par exemple