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