为什么MyClass.class存在于java和MyField.field中不存在?

假设我有:

class A { Integer b; void c() {} } 

为什么Java有这样的语法: A.class ,并且没有这样的语法: b.fieldc.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 

请注意, fieldmethod没有等效语法。

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语法没有破坏任何东西,因为class已经是一个关键字。 (IIRC,Java 1.1中添加了语法。)


*如果语言设计师试图改进对此类事物的支持,则会出现各种问题:

  • 这些更改会给语言带来歧义,使编译和其他依赖于解析器的任务变得更加困难。
  • 无论是否将methodfield转换为关键字,这些更改无疑会破坏现有代码。
  • 您不能将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