web-dev-qa-db-fra.com

nameof équivalent dans Java

C # 6.0 a introduit l'opérateur nameof(), qui renvoie une chaîne représentant le nom de tout identificateur de classe/fonction/méthode/variable locale/propriété placé à l'intérieur.

Si j'ai une classe comme celle-ci:

class MyClass
{
    public SomeOtherClass MyProperty { get; set; }

    public void MyMethod()
    {
        var aLocalVariable = 12;
    }
}

Je peux utiliser l'opérateur comme ceci:

// with class name:
var s = nameof(MyClass); // s == "MyClass"

// with properties:
var s = nameof(MyClass.OneProperty); // s == "OneProperty"

// with methods:
var s = nameof(MyClass.MyMethod); // s == "MyMethod"

// with local variables:
var s = nameof(aLocalVariable); // s == "aLocalVariable".

Ceci est utile car la chaîne correcte est vérifiée au moment de la compilation. Si j'épelle mal le nom d'une propriété/méthode/variable, le compilateur renvoie une erreur. De plus, si je refactorise, toutes les chaînes sont automatiquement mises à jour. Voir par exemple cette documentation pour des cas d'utilisation réels.

Y a-t-il un équivalent de cet opérateur en Java? Sinon, comment puis-je obtenir le même résultat (ou similaire)?

27
Massimiliano Kraus

Malheureusement, il n'y a rien de tel. J'avais recherché cette fonctionnalité il y a quelque temps et la réponse semblait être que, d'une manière générale, ce genre de choses n'existe pas.

Voir Obtenir le nom d'un champ

Vous pouvez, bien sûr, annoter votre champ avec une annotation "Nommée" pour atteindre essentiellement cet objectif pour vos propres classes. Il existe en fait une grande variété de cadres qui dépendent de concepts similaires. Néanmoins, ce n'est pas automatique.

13
nasukkin

Cela peut être fait en utilisant l'instrumentation de code d'octet d'exécution, par exemple en utilisant la bibliothèque Byte Buddy.

Voir cette bibliothèque: https://github.com/strangeway-org/nameof

L'approche est décrite ici: http://in.relation.to/2016/04/14/emulating-property-literals-with-Java-8-method-references/

Exemple d'utilisation:

public class NameOfTest {
    @Test
    public void direct() {
        assertEquals("name", $$(Person.class, Person::getName));
    }

    @Test
    public void properties() {
        assertEquals("summary", Person.$(Person::getSummary));
    }
}
7
jreznot

Tu ne peux pas.

Vous pouvez obtenir une méthode ou un champ à l'aide de la réflexion, mais vous devez coder en dur le nom de la méthode sous forme de chaîne, ce qui élimine tout le but.

Le concept de propriétés n'est pas intégré à Java comme en C #. Les accesseurs et les setters ne sont que des méthodes normales. Vous ne pouvez même pas référencer une méthode aussi facilement que vous le faites dans votre question. Vous pouvez essayer autour de la réflexion pour obtenir un handle vers une méthode getter, puis couper le get pour obtenir le nom de la "propriété" à laquelle il ressemble, mais c'est moche et pas le même.

Quant aux variables locales, ce n'est pas possible du tout.

5
f1sh

Tu ne peux pas.

Si vous compilez avec des symboles de débogage, le fichier .class contiendra une table de noms de variables (c'est ainsi que les débogueurs mappent les variables à votre code source), mais il n'y a aucune garantie que cela sera là et qu'il ne sera pas exposé lors de l'exécution.

2
Muhammad Ramzan