why MyClass.class exists in java and MyField.field isn't?

后端 未结 4 551
南笙
南笙 2021-01-23 05:15

Let\'s say I have:

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

Why does Java have this syntax: A.class, and doesn\'t have a syntax

4条回答
  •  栀梦
    栀梦 (楼主)
    2021-01-23 05:47

    The A.class syntax looks like a field access, but in fact it is a result of a special syntax rule in a context where normal field access is simply not allowed; i.e. where A is a class name.

    Here is what the grammar in the JLS says:

    Primary:
      ParExpression
            NonWildcardTypeArguments (
                ExplicitGenericInvocationSuffix | this Arguments)
      this [Arguments]
      super SuperSuffix
      Literal
      new Creator
      Identifier { . Identifier }[ IdentifierSuffix]
      BasicType {[]} .class
      void.class
    

    Note that there is no equivalent syntax for field or method.

    (Aside: The grammar allows b.field, but the JLS states that b.field means the contents of a field named "field" ... and it is a compilation error if no such field exists. Ditto for c.method, with the addition that a field c must exist. So neither of these constructs mean what you want them to mean ... )

    Why does this limitation exist? Well, I guess because the Java language designers did not see the need to clutter up the language syntax / semantics to support convenient access to the Field and Method objects. (See * below for some of the problems of changing Java to allow what you want.)

    Java reflection is not designed to be easy to use. In Java, it is best practice use static typing where possible. It is more efficient, and less fragile. Limit your use of reflection to the few cases where static typing simply won't work.

    This may irk you if you are used to programming to a language where everything is dynamic. But you are better off not fighting it.

    Is there any use that is so common for class literals?

    I guess, the main reason they supported this for classes is that it avoids programs calling Class.forName("some horrible string") each time you need to do something reflectively. You could call it a compromise / small concession to usability for reflection.

    I guess the other reason is that the .class syntax didn't break anything, because class was already a keyword. (IIRC, the syntax was added in Java 1.1.)


    * If the language designers tried to retrofit support for this kind of thing there would be all sorts of problems:

    • The changes would introduce ambiguities into the language, making compilation and other parser-dependent tasks harder.
    • The changes would undoubtedly break existing code, whether or not method and field were turned into keywords.
    • You cannot treat b.field as an implicit object attribute, because it doesn't apply to objects. Rather b.field would need to apply to field / attribute identifiers. But unless we make field a reserved word, we have the anomalous situation that you can create a field called field but you cannot refer to it in Java sourcecode.
    • For c.method, there is the problem that there can be multiple visible methods called c. A second issue that if there is a field called c and a method called c, then c.method could be a reference to an field called method on the object referred to by the c field.

提交回复
热议问题