Reputation: 5198
Sorry for the vague title; I'm not entirely sure what the problem is.
In short: child classes of a certain base class must define 3 specific static methods, hiding the base class' static methods. An implementation description class checks this on initialization. Seemingly at random when running the application, however, I get run time exceptions during initialization saying that I haven't properly reimplemented the methods. But I am working in unrelated classes elsewhere when this happens, as rarely as it does, and simply shuffling the order of the methods fixes it for another long while.
So, three classes: The Base, the Derived, and the AlgImplementation class:
AlgImplementation constructor:
/* verifying that the extending class has implemented these methods */
if (this.getAlgorithmClassName() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassName() method from as specified.");
}
if (this.getAlgorithmClassDescription() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassDescription() method from as specified.");
}
if (this.getAlgorithmClassAnalyticLevel() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassAnalyticLevel() method from as specified.");
}
That's where the problem happens, one of those checks fails. I get the IllegalArgumentException from one or more of the above. I can simply move the order of the implementation around in the derived class, to force a rebuild of that code, and then it works fine.
Base & Derived classes both have the same simple static methods, but the static fields they return are defined differently:
class Derived extends Base {
public static AnalyticLevel getAlgorithmClassAnalyticLevel()
{
return ANALYTIC_LEVEL;
}
public static String getAlgorithmClassName()
{
return NAME;
}
public static String getAlgorithmClassDescription()
{
return DESCRIPTION;
}
}
The above fields are all non-null static final Strings.
Now, in the Derived class I declare a static final AlgImplementation field: public static final AlgImplementation derivedAlg = new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
Finally, the last thing I think you will need to know is that that this AlgImplementation instance does the this for each static method class:
public String getAlgorithmClassName() {
String className = "";
try {
className = (String)algorithmClass.getDeclaredMethod("getAlgorithmClassName", new Class<?>[0]).invoke(null, new Object[0]);
} catch (Exception e) {
throw new UnsupportedOperationException("Required static method getAlgorithmClassName() not implemented on "+this.getClass().getName());
}
return className;
}
So, my question is: How can the check for the derived methods fail if these methods are in fact declared? Is there an issue with declaring a static AlgImplementation field that refers to the very class it is defined in (causing some weird order of compilation issue, or something like that)?
The error is during initialization of Derived class, specifically at the line initializing the static AlgImplementation field, which is why I think there might be a problem with doing that in the Derived class itself.
Upvotes: 2
Views: 140
Reputation: 50031
I suspect the problem is due to initialization order of the static final fields of the classes. By using reflection during class initialization, you're accessing the class before it has fully initialized. If on a derived class, you have the following:
public static final String NAME;
static {
NAME = "some name";
}
public static final AlgImplementation derivedAlg =
new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
then AlgImplementation will check the NAME constant after it has been initialized, and will read the "some name" string. If you reverse the order:
public static final AlgImplementation derivedAlg =
new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
public static final String NAME;
static {
NAME = "some name";
}
then AlgImplementation will read the constant before it has been assigned, and will read null
instead.
I'm not sure if it's possible for this to happen if the NAME is assigned directly by a compile-time constant like this:
public static final String NAME = "some name";
I would have guessed that would prevent the problem, but maybe not. Your statement that "shuffling the order of the methods fixes it for another long while" supports the idea that the problem is due to initialization order. I'd suggest moving the derivedAlg
field after all the other constants to encourage it to be initialized last.
Upvotes: 1
Reputation: 251
Static methods do not participate in class hierarchy. You should always use either staticMethod()
or Class.staticMethod()
instead.
Upvotes: 0