47

C# 6.0 introduced the nameof() operator, that returns a string representing the name of any class / function / method / local-variable / property identifier put inside it.

If I have a class like this:

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

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

I can use the operator like this:

// 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".

This is useful since the correct string is checked at compile time. If I misspell the name of some property/method/variable, the compiler returns an error. Also, if I refactor, all the strings are automatically updated. See for example this documentation for real use cases.

Is there any equivalent of that operator in Java? Otherwise, how can I achieve the same result (or similar)?

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
  • 2
    Pretty sure Java doesn't have anything exactly equivalent. So like pre C# 6 you're likely going to just have to use string literals instead. – juharr Nov 28 '16 at 18:22
  • `nameof` is syntactic sugar added in the latest version of C# (6). I'm pretty sure that Java (or most popular languages in general) wouldn't have an equivalent. – Abion47 Nov 28 '16 at 18:23
  • 5
    What problem are you trying to solve with having this capability? – OldProgrammer Nov 28 '16 at 18:23
  • 1
    The same kind of problems that I solve using `nameof()` operator :) – Massimiliano Kraus Nov 28 '16 at 18:24
  • Reflection is the closest to this, but still not what you seek I think. – Vucko Nov 28 '16 at 18:27
  • 2
    I'm not a C# guy, but using ``nameof()`` does not sound like clean design if it's not for logging etc. – f1sh Nov 28 '16 at 18:27
  • 1
    @f1sh this feature can be very useful in writing less code and making your design clean. Without it, it would be very difficult and verbose to obtain the same result (through Reflection, for example). Read [this](http://stackoverflow.com/questions/31695900/what-is-the-purpose-of-nameof) for a wider discussion. – Massimiliano Kraus Nov 28 '16 at 18:31
  • 3
    @f1sh I use it myself quite a bit for object-updated events. I pass `nameof(AffectedProperty)` to a relevant property of the event args object to notify listeners as to which property was updated. It's a great way to get compile-time safety for property names. – Abion47 Nov 28 '16 at 18:31
  • 1
    @Servy why did you removed the "c#" tag? I put it because the `nameof` feature belongs to that language... – Massimiliano Kraus Nov 28 '16 at 18:33
  • 7
    The question is not _about_ C#, it is about Java, hence the tag is not relevant. It does contain and mention C#, but that doesn't warrant adding the tag. See also http://meta.stackoverflow.com/a/319194/1743880 – Tunaki Nov 28 '16 at 19:02
  • It seems that the situation has changed, I've shared possible solution in the answer. – jreznot Aug 13 '18 at 11:48
  • 2
    I'll add this to my list of things that C# can do that Java cannot*. * Except via byte-code manipulation. – Josh M. Jan 29 '22 at 01:40

6 Answers6

21

It can be done using runtime byte code instrumentation, for instance using Byte Buddy library.

See this library: https://github.com/strangeway-org/nameof

The approach is described here: http://in.relation.to/2016/04/14/emulating-property-literals-with-java-8-method-references/

Usage example:

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

    @Test
    public void properties() {
        assertEquals("summary", Person.$(Person::getSummary));
    }
}
jreznot
  • 2,694
  • 2
  • 35
  • 53
  • 1
    So I have to use an external library? No thanks. This should be baked into the Java language along with being able to reference a parameter name in a Javadoc comment. – Mike Lowery Nov 23 '22 at 22:21
19

Sadly, there is nothing like this. I had been looking for this functionality a while back and the answer seemed to be that generally speaking, this stuff does not exist.

See Get name of a field

You could, of course, annotate your field with a "Named" annotation to essentially accomplish this goal for your own classes. There's a large variety of frameworks that depend upon similar concepts, actually. Even so, this isn't automatic.

Community
  • 1
  • 1
nasukkin
  • 2,460
  • 1
  • 12
  • 19
6

You can't.

You can get a Method or Field using reflection, but you'd have to hardcode the method name as a String, which eliminates the whole purpose.

The concept of properties is not built into java like it is in C#. Getters and setters are just regular methods. You cannot even reference a method as easily as you do in your question. You could try around with reflection to get a handle to a getter method and then cut off the get to get the name of the "property" it resembles, but that's ugly and not the same.

As for local variables, it's not possible at all.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
f1sh
  • 11,489
  • 3
  • 25
  • 51
  • 1
    This question has nothing to do with C# properties. The question is asking whether you can get the name of a method or field without using the name itself. Your point about reflection requiring the name to get the Method or Field is germane. – Andy Thomas Nov 28 '16 at 18:28
  • The question mentions C# properties very specificly. And I answered the question with "no". So why the downvote? Also, what does "germane" mean? – f1sh Nov 28 '16 at 18:48
  • 1
    Ok, I mentioned C# properties, but obviously they don't exist in Java. It was only an example. The point of my question is to obtain class members/variables/fields/identifiers string representation, and you answered with some useful things. – Massimiliano Kraus Nov 28 '16 at 18:54
  • 1
    @f1sh - You're right - a property was mentioned in an example. "Germane" means relevant. I edited your answer to bring the most relevant parts to the top, and removed the downvote. I think the answer could be further improved by noting that you *can* get the name of a class. – Andy Thomas Nov 28 '16 at 19:19
  • 1
    Using reflection you can _enumerate_ methods and "properties" and can therefore discover the names without hardcoding them in advance - i.e. `.getClass().getDeclaredMethods()` and `.getClass().getDeclaredFields()` – Stephen P Dec 01 '16 at 01:52
  • 2
    @StephenP That's true. But if you want to get the name of a specific one, you'll have to check the method's/field's name with equals or contains, for which you have to type the name as a String literal again. – f1sh Dec 01 '16 at 08:39
  • @StephenP that defeats the whole purpose if you are going to need to hard-code the name anyway. – Orestis P. Aug 11 '19 at 17:41
  • @OrestisP. — using the techniques I'm talking about may not be appropriate for this particular question/situation, but you do _not_ "need to hard-code the name anyway". Given just an object reference, without even knowing what class it is, you can use introspection to discover all kinds of things about it, including class, method, and field names (and a lot more than just the names). If you insist I'm wrong on this point, well, I guess I just have to throw out the actual working code I have that does exactly this. (with no hard-coded names) – Stephen P Aug 12 '19 at 18:35
  • @StephenP I'm not saying that you can't, I mistakenly thought you were proposing reflection as a potential solution to the problem. – Orestis P. Aug 12 '19 at 21:07
3

You can't.

If you compile with debug symbols then the .class file will contain a table of variable names (which is how debuggers map variables back to your source code), but there's no guarantee this will be there and it's not exposed in the runtime.

Muhammad Ramzan
  • 294
  • 6
  • 14
  • 1
    The question asks first about names of classes, methods and fields, which are included in the compiled code, and exposed through reflection. – Andy Thomas Nov 28 '16 at 18:35
  • 1
    @AndyThomas no, it doesn't. Stop downvoting correct answers. – f1sh Nov 28 '16 at 18:42
  • 2
    @f1sh - "returns a string representing the name of the *member/class/field* put inside" – Andy Thomas Nov 28 '16 at 19:08
  • You don't need debug symbols to get the names of classes, methods, and fields (see my comment on f1sh'es answer). You do need them to get the names of arbitrary variables, declared in local scopes, but that's not what the OP was asking about. – Stephen P Dec 01 '16 at 01:56
3

Lombok has an experimental feature @FieldNameConstants

After adding annotation you get inner type Fields with field names.

@FieldNameConstants
class MyClass {
 String myProperty;
}
...

String s = MyClass.Fields.myProperty; // s == "myProperty"
makozaki
  • 3,772
  • 4
  • 23
  • 47
2

I was also annoyed that there is nothing comparable in Java, so I implemented it myself: https://github.com/mobiuscode-de/nameof

You can simply use it like this:

Name.of(MyClass.class, MyClass::getProperty)

which would just return the String

"property"

It's also on Maven Central, so you can add it to your project like this:

<dependency>
    <groupId>de.mobiuscode.nameof</groupId>
    <artifactId>nameof</artifactId>
    <version>1.0</version>
</dependency>

or for Gradle:

implementation 'de.mobiuscode.nameof:nameof:1.0'

I realize that it is quite similar to the library from strangeway, but I thought it might be better not to introduce the strange $/$$ notation and enhanced byte code engineering. My library just uses a proxy class on which the getter is called on to determine the name of the passed method. This allows to simply extract the property name.

I also created a blog post about the library with more details.

Entrusc
  • 197
  • 2
  • 11