Obtenir le nom d'un champ
Est-il possible en Java afin d'obtenir un nom de domaine en chaîne à partir de la réalité? comme:
public class mod {
@ItemID
public static ItemLinkTool linkTool;
public void xxx{
String fieldsName = *getFieldsName(linkTool)*;
}
}
PS: je suis pas la recherche d'un champ de la classe/nom de la classe ou de l'obtention de Champ de nom de la Chaîne.
EDIT:
Quand je suis à la recherche d'elle je ne serais probablement pas besoin d'une méthode pour obtenir un nom du champ, le Champ de l'instance (à partir du champ "nom de code") suffirait. [par exemple Field myField = getField(linkTool)
]
Il n'est probablement pas quelque chose que je veux en Java lui-même. Je vais prendre un coup d'oeil à l'ASM de la bibliothèque, mais à la fin, je pourrais utiliser la chaîne comme un identificateur pour les champs :/
EDIT2:
Mon anglais n'est pas génial (mais même dans ma langue maternelle j'aurais des problèmes expliquant cela), je suis donc l'ajout d'un exemple de plus. Heureusement nous, ça sera plus clair maintenant:
public class mod2 {
@ItemID
public static ItemLinkTool linkTool;
@ItemID
public static ItemLinkTool linkTool2;
@ItemID
public static ItemPipeWrench pipeWrench;
public void constructItems() {
//most trivial way
linkTool = new ItemLinkTool(getId("linkTool"));
linkTool2 = new ItemLinkTool(getId("linkTool2"));
pipeWrench = new ItemPipeWrench(getId("pipeWrench"));
//or when constructItem would directly write into field just
constructItem("linkTool");
constructItem("linkTool2");
constructItem("pipeWrench");
//but I'd like to be able to have it like this
constructItemIdeal(linkTool);
constructItemIdeal(linkTool2);
constructItemIdeal(pipeWrench);
}
//not tested, just example of how I see it
private void constructItem(String name){
Field f = getClass().getField(name);
int id = getId(name);
//this could be rewritten if constructors take same parameters
//to create a new instance using reflection
if (f.getDeclaringClass() == ItemLinkTool){
f.set(null, new ItemLinkTool(id));
}else{
f.set(null, new ItemPipeWrench(id));
}
}
}
La question est: comment pourrait ressembler le constructItemIdeal méthode? (À partir des réponses et googler autour de moi, je chose qu'il n'est pas possible en Java, mais qui sait..)
- Si le champ n'est pas privé, il est alors possible de connaître le nom du champ visé, à partir notamment de la partie de code, mais l'analyse de bytecode. Vous pouvez utiliser ASM bibliothèque pour cela.
- Qu'entendez-vous par le nom du domaine? C'est que la Chaîne "linkTool" dans votre exemple?
- Entendez-vous le nom d'un champ d'une classe que vous avez écrit vous-même ou une autre classe?
- Notez que
ItemLinkTool
a probablement plus que juste une méthode. Que doit votregetFieldsName
de retour de méthode dans des cas comme ça? - Je ne sais pas si je l'ai écrit clairement, je veux même fonctionnalité que: le présent.getClass().getField("linkTool") juste sans la partie de chaîne de ~ ce.getClass().getField(linkTool).
- Pourquoi auriez-vous besoin d'un Champ réfléchi lorsque vous avez déjà le champ réel?
- Parce que dans la phase 1-je obtenir les Identifiants pour les champs marqués avec
@ItemID
(les champs sont nuls et plus de champs sera de même type), dans la phase suivante, je voudrais aborder les champs par leurs noms, pas des chaînes de caractères (j'ai écrit les raisons ci-dessous). À partir de la chaîne de nom, je serais en mesure d'obtenir un Champ d'instance et ensuite l'utiliser comme un index dans une carte pour obtenir son ID (nécessaire dans le Domaine du constructeur de la classe). Basé sur le Champ de la classe (et probablement d'annotation), je serais en mesure de créer une instance et l'affecter à la valeur d'un Champ. PS: par Domaine je veux dire java.lang.de réfléchir.Champ, pas n'importe quel domaine. - Ma motivation à obtenir le nom du champ est de l'utiliser pour rechercher les choses d'une valeur-clé de la base de données (comme mongodb). J'ai une struct avec les membres (champs) qui représente les données sauvegardées. - je utiliser les noms des membres à la recherche de la db.
Vous devez vous connecter pour publier un commentaire.
Malheureusement, il n'y a aucun moyen de faire ce que vous voulez. Pourquoi?
Dans une ère où nous sommes encore à essayer de prouver que Java n'est pas lente, le stockage des métadonnées d'où ou comment un objet a été construit aurait un grand frais généraux, et depuis il a une très faible plage d'utilisation, il n'existe pas. Pas seulement: il y a un tas de raisons techniques aussi bien.
L'une des raisons est parce que de la façon dont la JVM est mis en œuvre. La spécification de Java
class
format de fichier peut être trouvé ici. Il est tout à fait une bouchée, mais il est très instructif.Comme je l'ai dit précédemment, un objet peut être construit à partir de n'importe où, même des situations où les objets n'ont pas de noms. Seuls les objets définis comme membres de la classe ont des noms (pour la raison évidente d'accès): des objets construits dans les méthodes ne sont pas. La JVM est une variable locale de la table avec un maximum de 65 535 entrées. Ceux-ci sont chargés à la pile et stockée dans la table via l' *charger et *stocker les opcodes.
En d'autres termes, une classe comme
sera compilé dans
Là, vous pouvez voir un exemple clair de
javap -v Test
que, bien que le nomclass_member
est préservée, lemy_local_field
a été donné à l'indice 1 dans la variable locale de la table (0 est réservé pourthis
).Ce serait en soi une douleur pour les débogueurs et, donc, un ensemble d'attributs (pensez métadonnées pour les fichiers de classe) a été conçu. Ces comprennent la LocalVariableTable, LineNumberTable, et LocalVariableTypeTable. Ces attributs sont utiles pour stacktraces (LineNumberTable), et débogueurs (LocalVariableTable et LocalVariableTypeTable). Cependant, ces derniers sont complètement facultatif à inclure dans les fichiers, et il n'y a aucune garantie qu'ils sont:
La même chose vaut pour le reste d'entre eux.
En outre, la plupart des compilateurs ne produisent rien, mais la LineNumberTable par défaut, donc, si vous voulez être hors de la chance même si c'était possible.
Fondamentalement, il serait assez frustrant pour les développeurs d'avoir un
getFieldName(object)
(qui ne serait pas possible, en premier lieu, pour les variables locales), et la seule qui fonctionne lorsque ces attributs sont présents.Si vous êtes coincé dans un avenir prévisible avec l'aide de
getField
avec des Chaînes. Shameless plug: IntelliJ semble gérer refactors avec réflexion assez bien: le fait d'avoir écrit Minecraft mods que je connais le sentiment, et je peux dire que le travail de refactoring est considérablement réduit par l'Ide. Mais la même chose est probablement vrai pour la plupart des Ide modernes: je suis sûr que les gros joueurs, Eclipse, Netbeans et coll. ont bien mis en œuvre refactoring des systèmes en place.Cela n'est possible que par la réflexion.
Utilisation
Class.getDeclaringFields
()et
java.reflection.Field.getName()
Si le terrain est privé, vous pouvez le rendre accessible:
Pour obtenir le champ nom, à l'aller comme ça:
Si vous ne connaissez pas le nom du champ... bien.. alors quel domaine souhaitez-vous obtenir? 🙂 Vous pourriez obtenir TOUS les champs à l'aide de la réflexion et ensuite une boucle à travers eux.. Mais si vous ne connaissez pas le domaine, quel est le sens réel et la logique dans cette action?
Je pense que c'est ce que vous cherchez.
Ma motivation à obtenir le nom du champ est de l'utiliser pour rechercher les choses d'une valeur-clé de la base de données (comme mongodb). J'ai une struct avec les membres (champs) qui représente les données sauvegardées. - Je utiliser les noms des membres à la recherche de la db.
Ma suggestion est de mettre un statique de lecture pour chaque membre important. Exemple:
Espérons-le, Java disposer d'un mécanisme pour cela dans le futur, parce que de nos jours, les métadonnées peuvent être une partie des données. Surtout quand à faire des trucs avec JSON.
Il peut être fait à l'aide d'exécution du byte-code de l'instrumentation, par exemple à l'aide d'Octets Copain de la bibliothèque, voir cette réponse nameof équivalent en Java