mardi 23 février 2016

Java: How do i best determine whether a local class defined in an initializer block requires an enclosing instance for instantiation?

Right now I'm implementing a method that has one parameter of the type Class and this method returns a boolean if the given class object requires an instance of it's enclosing class for it to be instantiated.

This method currently works as follows:

    if (clazz.getEnclosingClass() == null) {
        return false;
    }
    if (clazz.isAnonymousClass() || clazz.isMemberClass()) {
        return !Modifier.isStatic(clazz.getModifiers());
    }
    if (clazz.getEnclosingConstructor() != null) {
        return true;
    }
    final Method enclosingMethod = clazz.getEnclosingMethod();
    if (enclosingMethod != null) {
        return !Modifier.isStatic(enclosingMethod.getModifiers());
    }

To explain why it is designed as such:

  1. It first checks if it's a top-level class, if so, the algorithm can safely return false
  2. If the class is anonymous or a member class, it requires a closing instance if it's not static (an anynmous class is automatically static if it's declared in a static constructor/method/initializer-block)
  3. The class can now be assumed to be a local class (disregarding arrays and primitives), so it's defined in either a constructor, method or initializer. However, unlike an anonymous class, a local class is never considered static, but still requires an enclosing instance if the local class is defined in a non-static block.
  4. A constructor is never static, so in that case return true
  5. If it's defined in a method, return true if the method isn't static

I need step 6 to determine whether the local class resides in either a Static Initializer Block or an Instance Initializer Block, so I'm done with the implementation for this function.

So here's where the reflection API falls a bit short. There's no method Class.getEnclosingInitializer() or such, nor is there a class that represents an initializer in the reflection package.

Isn't an initializer block a member of a class? In the java 1.8 spec the Member interface only has the implementation classes Field, Executable (with subclasses Constructor and Method), and then there's MemberName that's out of the scope for most users of reflection.

I'm not really sure if the people behind the spec forgot about this situation and local classes actually should be static if declared in a static method/initializer (like anonymous classes). But it seems to me that it's lacking this last bit of consistency from this point of view.

So does anybody have an idea on how to ascertain in which type of initializer block the local class is declared?

I'm not really keen on digging through fields for a synthetic one of a type that equals it's enclosing class, or looping through it's constructors for something akin to that (sidenote: Parameter objects from Constructor.getParameters() always return false on isImplicit() and isSynthetic() no matter what i try... that just seems wrong). So if I can avoid such solutions that would be great.





Aucun commentaire:

Enregistrer un commentaire