Java/Scala以类型安全的方式获取Field引用

Mag*_*nus 10 java reflection scala field-names type-safety

Java声称面向对象且类型安全,而Scala更是如此.

内部类字段由名为Field的类表示,您可以通过Reflection API获取对它的引用.

我的问题:这些语言是否提供了以类型安全的方式获取Field引用的任何方法?(如果不是,为什么不呢?看起来像一个明显的缺陷)

将Object映射到某个外部表示(例如,模板中的html字段或数据库中的列名称)时,这将非常有用,以使引用名称自动保持同步.

理想情况下,我想说的是:

&(SomeClass.someField).name() 
Run Code Online (Sandbox Code Playgroud)

获取字段声明的名称,类似于java enums允许的说法:

MyEnum.SOME_INSTANCE.name()
Run Code Online (Sandbox Code Playgroud)

[update:]在阅读反馈后,这个功能会以某种方式违反Reflection API的意图,我同意Reflection是针对编译时未知的事情而设计的,这就是为什么必须使用它来实现它是如此荒谬得知事情在编译时已知,非常类,即字段,它的编译!

编译器为枚举提供了这个,所以如果编译器能够访问枚举字段的引用以允许MyEnum.SOME_INSTANCE.name(),那么它没有逻辑上的原因它也不能为普通的类提供相同的功能. .

有没有技术上的原因为什么这个功能不适用于普通课程?我不明白为什么不这样做,我不同意这个功能会使事情"复杂化"......相反,它会极大地简化目前繁琐的Reflection API技术.为什么强迫开发人员使用Reflection来查找编译时已知的内容?

[更新#2]至于此功能的实用程序,您是否尝试过使用JPA或Hibernate中的Criteria API动态构建查询?你有没有看到人们想出的荒谬的解决办法,试图避免传递一个不安全的字符串表示字段来查询?

[更新#3]最后,一种名为Ceylon的新JVM语言已经注意到了这个调用并让这件事变得微不足道!

Jon*_*eet 6

我的问题:这些语言是否提供了以类型安全的方式获取Field引用的任何方法?

编译时类型安全吗?不是我知道的,至少在Java中.Java中反射的正常目的是让代码能够处理它之前不知道的类型 - 我很少(根据我的经验)处于你希望能够引用字段的位置一种已知的类型.它确实发生了,但并不常见.

(如果不是,为什么不呢?看起来像一个明显的缺陷)

每个功能都需要设计,实现,测试,并且必须满足提供比语言中增加的复杂性更多价值的平衡.

就个人而言,我可以想到我更喜欢在Java中看到的功能.

  • 我认为这是因为人们没有*看到它而罕见的唯一原因.我认为如果这个特性变得可用,将会出现一整类编程模式,以便在编译时解决当前繁琐的仅在运行时解决的问题. (2认同)
  • @Magnus:我认为"目前在运行时被繁琐地解决"为"想要能够引用已知类型的字段".我不是说*不会有用 - 而且我知道C#团队已经考虑了类似的东西(http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof -we-trust-a-dialogue.aspx)但我仍然认为这不是你所暗示的那个改变世界的启示. (2认同)
  • 感谢您的链接,非常有趣的讨论!然而,我的提议是,针对字段而不是方法,避免了所描述的"过载歧义"缺陷,并且范围界定问题似乎不是问题:只需遵循常规字段范围规则.尽管如此仍有启发性的讨论. (2认同)

小智 5

很遗憾,Java 仍然缺少这个特性。此功能不会增加额外的复杂性,因为它会干扰语言的其他方面。此外,作为一个很少使用的功能并不是借口。每种语言都充满了特性,大多数项目都使用了其中的一小部分。

我真的不明白为什么语言允许我这样做:

Field field = MyClass.class.getField("myField"); // 语法冗长,运行时求值,非类型安全,必须处理反射操作异常

但它不允许我这样做(类似):

字段字段 = MyClass::myField; // 语法紧凑,在编译时求值,类型安全,没有例外!

(“::”运算符只是一个建议,从 java 8 或 c++ 借来的)