40

C# 6.0 引入了nameof()运算符,该运算符返回一个字符串,该字符串表示放入其中的任何类/函数/方法/局部变量/属性标识符的名称。

如果我有这样的课程:

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

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

我可以像这样使用运算符:

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

这很有用,因为在编译时会检查正确的字符串。如果我拼错了某些属性/方法/变量的名称,编译器会返回错误。此外,如果我重构,所有字符串都会自动更新。例如,请参阅本文档以了解实际用例。

Java中是否有与该运算符等效的?否则,我怎样才能获得相同的结果(或类似的结果)?

4

6 回答 6

20

它可以使用运行时字节码检测来完成,例如使用 Byte Buddy 库。

看到这个库:https ://github.com/strangeway-org/nameof

该方法在这里描述:http: //in.relation.to/2016/04/14/emulating-property-literals-with-java-8-method-references/

使用示例:

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

    @Test
    public void properties() {
        assertEquals("summary", Person.$(Person::getSummary));
    }
}
于 2017-10-11T03:36:27.757 回答
17

可悲的是,没有这样的事情。我一直在寻找这个功能,而答案似乎是一般来说,这个东西不存在。

请参阅获取字段名称

当然,您可以使用“命名”注释对您的字段进行注释,以从本质上为您自己的类实现此目标。实际上,有很多框架依赖于类似的概念。即便如此,这也不是自动的。

于 2016-11-28T18:24:52.423 回答
6

你不能。

您可以使用反射获得方法或字段,但您必须将方法名称硬编码为字符串,这会消除整个目的。

属性的概念不像 C# 那样内置在 java 中。getter 和 setter 只是常规方法。您甚至无法像在问题中那样轻松地引用方法。您可以尝试使用反射来获取 getter 方法的句柄,然后切断它get以获取它相似的“属性”的名称,但这很丑陋且不一样。

至于局部变量,根本不可能。

于 2016-11-28T18:24:37.617 回答
2

你不能。

如果您使用调试符号进行编译,则 .class 文件将包含一个变量名称表(这是调试器将变量映射回源代码的方式),但不能保证它会存在并且它不会在运行时公开。

于 2016-11-28T18:32:14.153 回答
1

我也很恼火Java中没有可比性,所以我自己实现了它:https ://github.com/mobiuscode-de/nameof

您可以像这样简单地使用它:

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

这只会返回字符串

"property"

它也是 on Maven 中心,所以你可以像这样将它添加到你的项目中:

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

或者对于 Gradle:

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

我意识到它与来自奇怪路的库非常相似,但我认为最好不要引入奇怪的$/$$表示法和增强的字节码工程。我的库只使用一个代理类,在该代理类上调用 getter 来确定传递方法的名称。这允许简单地提取属性名称。

我还创建了一篇关于该库的博客文章,其中包含更多详细信息

于 2022-02-05T21:08:14.957 回答
0

Lombok 有一个实验性功能@FieldNameConstants

添加注释后,您将获得Fields带有字段名称的内部类型。

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

String s = MyClass.Fields.myProperty; // s == "myProperty"
于 2022-02-03T07:29:03.297 回答