En Java, j'aimerais avoir quelque chose comme:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
Mais je reçois
Impossible de faire une référence statique au type non statique T
Je ne comprends pas les génériques au-delà des utilisations de base et ne peux donc pas donner beaucoup de sens à cela. Cela n'aide pas que je n'ai pas pu trouver beaucoup d'informations sur Internet à ce sujet.
Quelqu'un pourrait-il préciser si une telle utilisation est possible, d'une manière similaire? Aussi, pourquoi ma tentative initiale a-t-elle échoué?
la source
Java ne sait pas ce que
T
c'est jusqu'à ce que vous instanciez un type.Vous pouvez peut-être exécuter des méthodes statiques en appelant,
Clazz<T>.doit(something)
mais il semble que vous ne puissiez pas.L'autre façon de gérer les choses est de mettre le paramètre type dans la méthode elle-même:
ce qui ne vous donne pas la bonne restriction sur U, mais c'est mieux que rien ....
la source
J'ai rencontré ce même problème. J'ai trouvé ma réponse en téléchargeant le code source de
Collections.sort
dans le framework java. La réponse que j'ai utilisée était de mettre le<T>
générique dans la méthode, pas dans la définition de classe.Cela a donc fonctionné:
Bien sûr, après avoir lu les réponses ci-dessus, j'ai réalisé que ce serait une alternative acceptable sans utiliser de classe générique:
la source
T extends XXX
syntaxe.Comparable
. Essayez<T extends Comparable<? super T>>
plutôt.Il est possible de faire ce que vous voulez en utilisant la syntaxe des méthodes génériques lors de la déclaration de votre
doIt()
méthode (notez l'ajout de<T>
entrestatic
etvoid
dans la signature de méthode dedoIt()
):J'ai demandé à l'éditeur Eclipse d'accepter le code ci-dessus sans l'
Cannot make a static reference to the non-static type T
erreur, puis je l'ai étendu au programme de travail suivant (avec une référence culturelle quelque peu adaptée à l'âge):Qui imprime ces lignes sur la console lorsque je l'exécute:
la source
<T>
masque le premier de la même manière que dansclass C { int x; C(int x) { ... } }
le paramètrex
masque le champx
.static <E extends SomeClass> E foo(E input){return input;}
pour chaque méthode quand je voudrais 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 encore été mentionnée (dans le cas où vous voulez une méthode sans arguments):
Et l'appel:
J'espère que cela aidera quelqu'un.
la source
<String>
car il infère simplement l'argument type car vous l'assignez à une variable. Si vous ne l'attribuez pas, il en déduit simplementObject
.Il est correctement mentionné dans l'erreur: vous ne pouvez pas faire de référence statique à un type non statique T. La raison en est que le paramètre type
T
peut être remplacé par n'importe quel argument de type, par exempleClazz<String>
ouClazz<integer>
etc. Mais les champs / méthodes statiques sont partagés par tous les non -des objets statiques de la classe.L'extrait suivant est tiré du doc :
Comme l'a souligné à juste titre chris dans sa réponse, vous devez utiliser le paramètre type avec la méthode et non avec la classe dans ce cas. Vous pouvez l'écrire comme:
la source
Quelque chose comme ce qui suit vous rapprocherait
EDIT: exemple mis à jour avec plus de détails
la source
Lorsque vous spécifiez un type générique pour votre classe, la machine virtuelle Java sait qu'il n'a qu'une instance de votre classe, pas une définition. Chaque définition n'a qu'un type paramétré.
Les génériques fonctionnent comme des modèles en C ++, vous devez donc d'abord instancier votre classe, puis utiliser la fonction avec le type spécifié.
la source
Clazz<int>::doIt( 5 )
)En d'autres termes, cela se produit en raison de la propriété "Erasure" des génériques. Ce qui signifie que bien que nous définissions
ArrayList<Integer>
etArrayList<String>
, au moment de la compilation, cela reste comme deux types concrets différents, mais au moment de l'exécution, la JVM efface les types génériques et crée une seule classe ArrayList au lieu de deux classes. Donc, lorsque nous définissons une méthode de type statique ou quoi que ce soit pour un générique, elle est partagée par toutes les instances de ce générique, dans mon exemple, elle est partagée par les deuxArrayList<Integer>
etArrayList<String>
. C'est pourquoi vous obtenez l'erreur. Un paramètre de type générique d'une classe n'est pas Autorisé dans un contexte statique!la source
@BD at Rivenhill: Puisque cette vieille question a retenu l'attention l'année dernière, continuons un peu, juste pour le plaisir de la discussion. Le corps de votre
doIt
méthode ne fait rien deT
spécifique. C'est ici:Vous pouvez donc supprimer entièrement toutes les variables de type et simplement coder
D'accord. Mais revenons au problème d'origine. La première variable de type sur la déclaration de classe est redondante. Seul le second sur la méthode est nécessaire. C'est reparti, mais ce n'est pas encore la réponse définitive:
Cependant, c'est trop de bruit pour rien, car la version suivante fonctionne de la même manière. Tout ce dont il a besoin est le type d'interface sur le paramètre de méthode. Aucune variable de type en vue nulle part. Est-ce vraiment le problème d'origine?
la source
Puisque les variables statiques sont partagées par toutes les instances de la classe. Par exemple, si vous rencontrez le code suivant
T n'est disponible qu'après la création d'une instance. Mais des méthodes statiques peuvent être utilisées avant même que des instances ne soient disponibles. Ainsi, les paramètres de type générique ne peuvent pas être référencés dans des méthodes et des variables statiques
la source