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