Méthode statique dans une classe générique?
En Java, j'aimerais avoir quelque chose comme:
class Clazz<T> {
static void doIt(T object) {
//shake that booty
}
}
Mais je reçois
Ne peut pas faire une référence statique pour les non-statique de type T
Je ne comprends pas les génériques delà les utilisations de base et ne peut donc pas faire beaucoup de sens. Cela n'aide pas que je n'ai pas pu trouver beaucoup d'infos sur internet sur le sujet.
Quelqu'un pourrait-il préciser si une telle utilisation est possible, de la même manière? Aussi, pourquoi mon original tentative infructueuse?
Vous devez vous connecter pour publier un commentaire.
Vous ne pouvez pas utiliser une classe de paramètres de type générique dans les méthodes statiques ou des champs statiques. La classe du type de paramètres sont uniquement dans la portée par exemple les méthodes et les champs d'instance. Pour les champs statiques et méthodes statiques, ils sont partagés entre toutes les instances de la classe, même en cas de différents types de paramètres, il est évident qu'ils ne peuvent pas compter sur un paramètre de type.
Il ne semble pas que votre problème devrait exiger l'utilisation de la classe du paramètre de type. Si vous décrivez ce que vous essayez de ne plus en détail, nous pouvons peut-être vous aider à trouver une meilleure façon de le faire.
Java ne sait pas ce que
T
est jusqu'à ce que vous instanciez un type.Peut-être que vous pouvez exécuter des méthodes statiques en appelant
Clazz<T>.doit(something)
mais il semble que vous ne pouvez pas.L'autre façon de gérer les choses est de mettre le type de paramètre dans la méthode elle-même:
qui n'a pas le droit de restriction sur U, mais c'est mieux que rien....
static <U> void some(U u)
, alors si vous ditesA.<String>some("")
, vous dites "exécuter la méthodesome
avec un paramètre de typeString
dans la classeA
". D'autre part,A<String>.some("")
dit "exécuter la méthodesome
sur la classeA
qui a un paramètre de type de typeString
". Qui n'a pas de sens, parce que vous n'avez pas de classe générique de raffinement dans Java. (c'est en partie prévu dans le Projet Valhalla bien)J'ai rencontré ce même problème. J'ai trouvé ma réponse en téléchargeant le code source pour
Collections.sort
dans le cadre java. La réponse que j'ai utilisé était de mettre la<T>
générique de la méthode, pas dans la définition de classe.Donc cela a fonctionné:
Bien sûr, après avoir lu les réponses ci-dessus, j'ai réalisé que ce serait une solution de rechange acceptable sans l'aide d'une classe générique:
T extends XXX
de la syntaxe.Comparable
. Essayez<T extends Comparable<? super T>>
à la place.Il est possible de faire ce que vous voulez en utilisant la syntaxe de méthodes génériques lors de la déclaration de votre
doIt()
méthode (remarquer l'ajout de<T>
entrestatic
etvoid
dans la signature de la méthode dedoIt()
):J'ai eu l'Éclipse de l'éditeur pour accepter le code ci-dessus sans le
Cannot make a static reference to the non-static type T
erreur, puis étendu à la suite de son programme de travail (avec un peu appropriés à l'âge de référence culturelle):Qui imprime ces lignes dans la console quand je le lance:
<T>
masques de la première de la même manière que dansclass C { int x; C(int x) { ... } }
le paramètrex
masques le domainex
.static <E extends SomeClass> E foo(E input){return input;}
pour chaque méthode quand je veux faire quelque chose commestatic <E extends SomeClass>; //static generic type defined only once and reused
static E foo(E input){return input;}
static E bar(E input){return input;}
//...etc...
Je pense que cette syntaxe n'a pas été mentionné encore (dans le cas où vous voulez une méthode sans argument) :
Et de l'appel :
Espère que cela aide quelqu'un.
<String>
simplement parce que cela implique que l'argument de type parce que, vous pouvez l'affecter à une variable. Si vous n'avez pas l'affecter, il déduit simplementObject
.Il est correctement mentionné dans le message d'erreur: vous ne pouvez pas faire une référence statique non-statique de type T. La raison en est le paramètre de type
T
peut être remplacé par tout type d'argument par exempleClazz<String>
ouClazz<integer>
etc. Mais les champs statiques, les méthodes sont partagés par tous les non-statique des objets de la classe.L'extrait suivant est tiré de la doc:
Comme l'a justement souligné par chris dans son réponse vous avez besoin d'utiliser le type de paramètre à la méthode et non pas avec la classe dans ce cas. Vous pouvez l'écrire comme:
D'autres ont répondu à votre question déjà, mais en plus je peux soigneusement recommande d'O'Reilly Java Génériques livre. C'est un subtil et complexe à la fois, et si souvent semble inutile de restrictions, mais le livre fait un assez bon travail en expliquant pourquoi java génériques sont comme elles sont.
Quelque chose comme ce qui suit vous rapprocher
EDIT: mise à Jour exemple avec plus de détail
Lorsque vous spécifiez un type générique pour votre classe, JVM savoir de n'avoir qu'une instance de votre classe, pas de définition. Chaque définition a seulement paramétrées type.
Génériques fonctionnent comme les templates en C++, donc vous devez d'abord instancier votre classe, puis d'utiliser la fonction avec le type spécifié.
Clazz<int>::doIt( 5 )
)Également à mettre en termes simples, il arrive à cause de l ' "Effacement" de la propriété des génériques.Ce qui signifie que bien que nous définissons
ArrayList<Integer>
etArrayList<String>
, au moment de la compilation, il reste que les deux différents types de béton, mais lors de l'exécution de la JVM efface les types génériques et crée une seule classe ArrayList au lieu de deux classes. Ainsi, lorsque nous définissons un type statique méthode ou quoi que ce soit pour un générique, il est partagé par toutes les instances de ce générique, dans mon exemple il est partagé par les deuxArrayList<Integer>
etArrayList<String>
.C'est pourquoi vous obtenez le message d'erreur.Un Paramètre de Type Générique d'une Classe n'Est Pas Autorisé dans un Contexte Statique!@BD à Rivenhill: Depuis cette vieille question a eu un regain d'attention de la dernière année, laissez-nous aller sur un peu, juste pour le plaisir de la discussion.
Le corps de votre
doIt
méthode ne fait rienT
spécifiques à tous. Ici, il est:De sorte que vous pouvez entièrement abandonner toutes les variables de type et du code
Ok. Mais revenons plus près de l'origine du problème. Le premier type de la variable sur la déclaration de la classe est redondante. Seule la seconde sur la méthode est nécessaire. Ici, nous allons à nouveau, mais ce n'est pas la réponse finale, mais:
Cependant, il est tout aussi beaucoup de bruit pour rien, depuis la version suivante fonctionne exactement de la même manière. Tout ce qu'il faut est le type d'interface sur le paramètre de méthode. Pas de type de variables dans la vue de n'importe où. Était-ce vraiment le problème?
Depuis des variables statiques sont partagés par toutes les instances de la classe. Par exemple, si vous avez de code suivant
T est disponible uniquement après qu'une instance est créée. Mais les méthodes statiques ne peuvent être utilisés avant même que les instances sont disponibles. Ainsi, les paramètres de type Générique ne peut pas être référencés à l'intérieur des méthodes statiques et variables