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

后端 未结 4 544
南笙
南笙 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:25

    In java, Not everything is an object.

    You can have

    A a = new A()
    Class cls = a.getClass()
    

    or directly from the class

    A.class
    

    With this you get the object for the class.

    With reflection you can get methods and fields but this gets complicated. Since not everything is an object. This is not a language like Scala or Ruby where everything is an object. Reflection tutorial : http://download.oracle.com/javase/tutorial/reflect/index.html

    BTW: You did not specify the public/private/protected , so by default your things are declared package private. This is package level protected access http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

    0 讨论(0)
  • 2021-01-23 05:29

    I take it you want this info for logging and such. It is most unfortunate that such information is not available although the compiler has full access to such information.

    One with a little creativity you can get the information using reflection. I can't provide any examples for asthere are little requirements to follow and I'm not in the mood to completely waste my time :)

    0 讨论(0)
  • 2021-01-23 05:46

    I'm not sure if I fully understand your question. You are being unclear in what you mean by A.class syntax. You can use the reflections API to get the class from a given object by:

    A a = new A()
    Class c = a.getClass()
    

    or

    Class c = A.class;
    

    Then do some things using c.

    The reflections API is mostly used for debugging tools, since Java has support for polymorphism, you can always know the actual Class of an object at runtime, so the reflections API was developed to help debug problems (sub-class given, when super-class behavior is expected, etc.).

    The reason there is no b.field or c.method, is because they have no meaning and no functional purpose in Java. You cannot create a reference to a method, and a field cannot change its type at runtime, these things are set at compile-time. Java is a very rigid language, without much in the way of runtime-flexibility (unless you use dynamic class loading, but even then you need some information on the loaded objects). If you have come from a flexible language like Ruby or Javascript, then you might find Java a little controlling for your tastes.

    However, having the compiler help you figure our potential problems in your code is very helpful.

    0 讨论(0)
  • 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 <type>.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.

    0 讨论(0)
提交回复
热议问题