为什么MyClass.class存在于java和MyField.field中不存在?
假设我有:
class A { Integer b; void c() {} }
为什么Java有这样的语法: A.class
,并且没有这样的语法: b.field
, c.method
?
对于文字文字有什么用处吗?
A.class
语法看起来像是字段访问,但实际上它是在上下文中的特殊语法规则的结果,其中不允许正常的字段访问; 即A
是一个类名。
以下是JLS中的语法:
Primary: ParExpression NonWildcardTypeArguments ( ExplicitGenericInvocationSuffix | this Arguments) this [Arguments] super SuperSuffix Literal new Creator Identifier { . Identifier }[ IdentifierSuffix] BasicType {[]} .class void.class
请注意, field
或method
没有等效语法。
( b.field
:语法允许b.field
,但是JLS声明b.field
表示名为“field”的字段的内容…如果不存在这样的字段则是编译错误。同样适用于c.method
,with 字段 c
必须存在的附加。所以这些结构都不代表你想要的意思……)
为什么存在这种限制? 嗯,我想因为Java语言设计者没有看到需要混淆语言语法/语义来支持方便地访问Field和Method对象。 (有关更改Java以解决问题的一些问题,请参阅下面的* 。)
Javareflection的设计并不容易使用。 在Java中,最好在可能的情况下使用静态类型。 它更有效,更不易碎。 将reflection的使用限制在静态类型不起作用的少数情况下。
如果你习惯于编程到一切都是动态的语言,这可能会让你烦恼。 但你最好还是不打它。
对于文字文字有什么用处吗?
我猜,他们为类支持这个的主要原因是它避免了每次你需要Class.forName("some horrible string")
做一些事情时调用Class.forName("some horrible string")
。 您可以将其称为妥协/小型让步以实现反思。
我猜另一个原因是
语法没有破坏任何东西,因为class
已经是一个关键字。 (IIRC,Java 1.1中添加了语法。)
*如果语言设计师试图改进对此类事物的支持,则会出现各种问题:
- 这些更改会给语言带来歧义,使编译和其他依赖于解析器的任务变得更加困难。
- 无论是否将
method
和field
转换为关键字,这些更改无疑会破坏现有代码。 - 您不能将
b.field
视为隐式对象属性,因为它不适用于对象。 相反,b.field
需要应用于字段/属性标识符。 但除非我们将field
设为保留字,否则我们会出现exception情况,即您可以创建一个名为field
但不能在Java源代码中引用它。 - 对于
c.method
,存在可以存在多个称为c
可见方法的问题。 第二个问题是,如果有一个名为c
的字段和一个名为c
的方法,则c.method
可以是对c
字段引用的对象上的method
字段的引用。
我认为你想要这个信息用于记录等。 最不幸的是,虽然编译器可以完全访问这些信息,但是这些信息不可用。
一个有点创造力的人可以使用reflection获取信息。 我不能提供任何例子,因为没有什么要求可以遵循,我不想完全浪费我的时间:)
我不确定我是否完全理解你的问题。 您不清楚A.class
语法的含义。 您可以使用Reflections API通过以下方式从给定对象获取类:
A a = new A() Class c = a.getClass()
要么
Class c = A.class;
然后使用c
做一些事情。
reflectionAPI主要用于调试工具,因为Java支持多态,你总是可以在运行时知道对象的实际类,所以reflectionAPI是为了帮助调试问题而开发的(当超类时给出的子类)行为是预期的,等等)。
没有b.field或c.method的原因是因为它们在Java中没有任何意义和function目的。 您无法创建对方法的引用,并且字段在运行时无法更改其类型,这些内容在编译时设置。 Java是一种非常严格的语言,没有太多的运行时灵活性(除非你使用动态类加载,但即便如此,你需要有关加载对象的一些信息)。 如果你来自像Ruby或Javascript这样灵活的语言,那么你可能会发现Java对你的品味有一点控制。
但是,让编译器帮助您解决代码中的潜在问题非常有用。
在java中,并非所有东西都是对象。
你可以有
A a = new A() Class cls = a.getClass()
或直接来自class级
A.class
通过这个,您可以获得课程的对象。
通过reflection,您可以获得方法和字段,但这变得复杂。 因为不是一切都是对象。 这不是像Scala或Ruby这样的语言,其中一切都是对象。 反思教程: http : //download.oracle.com/javase/tutorial/reflect/index.html
顺便说一句:你没有指定public / private / protected,所以默认情况下你的东西被声明为package private。 这是包级别保护访问http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html