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

Reply via email to