不使用反射如何访问类的字段?

9

有没有一种方法可以在不使用反射的情况下访问类上的特定Field

考虑以下这个类:

class MyType {
    public int theNumber;
}

我想获得对theNumberjava.lang.reflect.Field访问权限。

这肯定会起作用:

Field f = MyType.class.getDeclaredField("theNumber");

然而,我希望对字段名称进行编译检查,所以最好像这样(但我的示例当然无法编译):
Field f = MyType.class::theNumber;

这是否可能,还是我对编译器的能力有误解?

我试图感受您提出问题的背景和动机。我尝试解决类似(或相反)的想法http://stackoverflow.com/questions/32284675/retrieve-information-from-jpa-metamodel 对于“隐藏广告”,我表示抱歉 :) - Jacek Cz
4个回答

4
您可以通过注解处理器扩展Java编译器。这些处理器是在编译过程中扫描源代码的一种方式。虽然它们是与注释一起引入的,但它们能够扫描整个源代码而不仅仅是注释。
通过扫描的源代码,您可以为任何编译的类生成访问器类。这样您就可以消除反射。
如果您只想在IDE中编写代码时获得错误信息,您可以使用javax.annotation.processing.ProcessingEnvironment.getMessager().printMessage()(请参见javax.tools.DiagnosticListener)来生成IDE可以显示的错误信息。
所以基本思路是:
1.编写一个注解处理器,扫描您想要反射的源代码 2.通过javax.lang.model.element.ElementVisitor提取您想要访问的字段
如果您想生成类型安全的对字段的访问:
3.1. 生成将访问此源代码的源代码
如果您想确保对字段的反射调用有效:
3.2. 通过ProcessingEnvironment.getMessager().printMessage()引发错误
当然,您必须编写检查反射调用或生成访问器的代码。
您想要获取的信息必须可从源代码中提取,因为所有魔法都发生在编译时而不是运行时。

哇,我在那里学到了新东西,之前不知道注解处理器。我一定会去查一下的! - Geir

2
有趣的问题。没有办法不使用 java.lang.reflect 来实现,但考虑到类中内置的 class 伪属性,我理解你为什么会问这个问题。

我也这么想。现在我正在使用一个枚举,其中的值等于类中的字段名称。希望能够摆脱它,因为每个字段名称都在枚举中重复出现。 - Geir

0

JPA2元模型(用于类型安全查询“按条件”)具有类似的概念。

MyType_.theNumber

通过额外的“预处理器”来实现。您可以在这个领域进行调查。


-1
不是,但你可以通过接口和闭包实现它。
public interface Getter<T, V> {
    V get(T object);
}

public static Getter<MyType, Integer> theNumberGetter = (MyType myType) -> { myType.theNumber };

它不访问“Field”,而是访问给定实例上该字段的 - T.J. Crowder
明白了...但我猜他只是想要这个“字段”,以便稍后访问值。 - lance-java
好的,要做到这一点,如果您在编译时知道字段的名称,那么myTypeInstance.theNumber似乎是更直接的方式。 - T.J. Crowder
他在编译时确实了解该领域...但有时为了编写通用代码,您需要使用这样的结构。让我们看看@Geir说什么。 - lance-java
正如上面所指出的,我在编译时了解该领域。我正在尝试编写一个通用的SQL构建器,在引用表列名称时是类型安全的,而且不需要重复列名称(例如,在枚举中定义它们)。示例 db.select(MyType :: thenumber).from(...)。@truthslie和@jacek-cz似乎提供了一些有价值的线索,我将跟进! - Geir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接