【问题标题】:Access to class' Fields without using reflection?不使用反射访问类的字段?
【发布时间】:2015-09-09 09:07:41
【问题描述】:

有没有办法在不使用反射的情况下访问类上的特定Field

考虑这个类:

class MyType {
    public int theNumber;
}

我想在哪里访问theNumberjava.lang.reflect.Field

这肯定有效:

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

但是,我想对字段名称进行编译检查,所以最好是这样(但当然我的示例无法编译):

Field f = MyType.class::theNumber;

这是可能的还是我的编译器能力的方式?

【问题讨论】:

标签: java reflection


【解决方案1】:

您可以使用注释处理器扩展 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() 引发错误

当然,您必须编写代码来检查反射调用或生成访问器。

而且你想获得的信息必须可以从源代码中提取出来,因为所有的魔法都发生在编译期间而不是运行时

【讨论】:

  • 哇,我在那里学到了一些新东西,不知道注释处理器。我一定会去看看的!
【解决方案2】:

有趣的问题。不,如果不使用 java.lang.reflect 就无法做到这一点,但鉴于类的内置 class 伪属性,我明白你为什么要问。

【讨论】:

  • 是这样想的。现在我正在使用一个枚举,其值等于类中的字段名称。希望摆脱这种情况,因为枚举中的每个字段名称都重复。
【解决方案3】:

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

MyType_.theNumber

由额外的“预处理器”实现。您可以在这方面进行调查。

【讨论】:

    【解决方案4】:

    不,不是……但你可以通过接口和闭包来实现它

    public interface Getter<T, V> {
        V get(T object);
    }
    
    public static Getter<MyType, Integer> theNumberGetter = (MyType myType) -> { myType.theNumber };
    

    【讨论】:

    • 不访问Field,它访问给定实例上字段的
    • 明白...但我猜他只想要Field,以便他以后可以访问值
    • 好吧,如果您在编译时知道该字段的名称,那么只需 myTypeInstance.theNumber 似乎是更直接的方法。
    • 他在编译时确实知道该领域......但有时要编写通用代码,您需要这样的构造。让我们看看@Geir 怎么说
    • 如上所述,我在编译时确实知道该字段。我正在尝试编写一个通用的 SQL 构建器,它在引用表列名时是类型安全的,并且也不需要列名的重复(例如在枚举中定义它们)。例如db.select(MyType::thenumber).from(...)。 @truthslie 和 @jacek-cz 似乎提供了一些有价值的线索,我会跟进!
    猜你喜欢
    • 2015-09-24
    • 1970-01-01
    • 2012-01-23
    • 1970-01-01
    • 2021-10-01
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多