Type of Class
David Holmes
david.holmes at oracle.com
Fri Feb 21 08:14:58 UTC 2014
On 21/02/2014 3:38 AM, Stephen Colebourne wrote:
> In JDK 5, three methods were added to java.lang.Class [1]
> - isAnonymousClass()
> - isLocalClass()
> - isMemberClass()
>
> Unfortunately, these do not cover the complete range of possible types of class.
I think they do once you realize that the static modifier is also needed
information. But it isn't pretty :)
> Would it be reasonable to add the following methods:
> - isNestedClass()
This would be !isTopLevelClass() but otherwise
isAnonymousClass() || isLocalClass() || isMemberClass()
> - isInnerClass()
isAnonymousClass() || isLocalClass() || (isMemberClass() && !static)
> - isTopLevelClass()
! (isAnonymousClass() || isLocalClass() || isMemberClass())
and for completeness:
- isStaticNestedClass() == isMemberClass() && static
> While JVM/spec experts may know the difference, it is a surprisingly
> tricky area. For example, the current isMemberClass() method could do
> with much better Javadoc to explain what a member class actually is
> (as it seemed hard to google).
I agree. And I have to confess that I don't even mention member classes
in my treatise on nested types in Chapter 5 of JPL 4e; and worse I give
the wrong definition for isMemberClass in the reflection chapter
(equating it to nested class)! But I do also comment on the lack of
ability to ask whether it is a static nested class or an inner class.
> FWIW, I was just trying to tell the difference between a nested class
> and an inner class, in order to determine which classes can be
> instantiated without reference to a surrounding object. The answer
> seems to be (cls.isMemberClass() &&
> Modifiers.isStatic(cls.getModifiers()) which is not the most obvious
> code.
Actually it is more complex than that. You can define an inner class in
a static context (static method, static initializer) and in that case
there is no enclosing instance. Not sure how to detect that:
innerClass() && getEnclosingMethod/Constructor() == null ||
(getEnclosingMethod().isStatic())
?
Cheers,
David
> In addition, I suffered from the absence of an isNormalClass() -
> probably a better name for this.
>
> Currently, you can determine if a class is an interface, annotation,
> primitive or array, leaving the "normal" case as a quadruple negative.
> This leaves such a user-written method vulnerable to any new type of
> class that gets added in a future JDK:
>
> boolean isNormalClass(Class cls) {
> return !cls.isInterface() && !cls.isAnnotation() &&
> !cls.isPrimitive() && !cls.isArray();
> }
>
> Stephen
> [1] https://blogs.oracle.com/darcy/entry/nested_inner_member_and_top
>
More information about the core-libs-dev
mailing list