Instantiate an object from a dynamically generated class - java

I am currently trying to achieve something like this:
Based on this class, I try to create a new instance of the class Class<? extends AbstractValidator> returned by the method getValidator().
public abstract class AbstractEnumDefinition
extends AbstractRequestFieldDefinition {
private Vector<String> values = new Vector<String>();
public abstract void define(String lang);
protected void addEnumDefinition(String value){
values.add(value);
}
public Vector<String> getValues(){
return values;
}
#Override
public Class<? extends AbstractValidator> getValidator() {
return new AbstractValidator() {
#Override
public boolean isValid(String value) {
return values.contains(value);
}
#Override
public String getDefaultValue() {
return "";
}
}.getClass();
}
}
Say I create this class:
public class LanguageDefinition extends AbstractEnumDefinition {
public LanguageDefinition() {
super();
}
#Override
public void define(String language) {
addEnumDefinition("BEL-fr");
addEnumDefinition("BEL-nl");
addEnumDefinition("BEL-en");
}
}
Later in my code, I call
new LanguageDefinition().getValidator().getConstructor().newInstance()
The class I am trying to instantiate here is not declared anywhere, but "generated dynamically"/"dynamically created" within the AbstractEnumDefinition class.
When trying to do this, I get an java.lang.InstantiationException for
be....servlets.model.extraction.filter.editor.AbstractEnumDefinition$1
I guess this is due to the fact that this Class has to be explicitly created before hand, and not referenced dynamically?
Is there some kind of solution that would allow me to not have to write one class per validator?
Thanks for the help,
Eric

I can only make assumptions since i don't see the code where you are actually using the class, but you should check: http://docs.oracle.com/javase/6/docs/api/java/lang/InstantiationException.html
One thing it mentions is the instantiation can fail is the class is an abstract class (perfectly logical since you can't instantiate abstract classes).
Also, i don't see why you need to return the class and then create and object. Why not just define a Validator Interface and have your method return a Validator object.

That does not work for anonymous classes as far as I know, you have to convert your class to a named inner class:
But even that will not work, properly because you might not have a default constructor. Inner classes get implicit constructor arguments to keep the reference to the enclosing class. Unfortunately Closures do not work so well in static languages.
In summary inner classes that are non-static can not be instantiate outside of an instance of the enclosing class.

Related

Can I call a static method on a generic class parameter

I have a collection of classes that implement RaeInterface:
public interface RaeInterface {
public static String SCHEMA_ID(){return ""; };
}
Each of the implementing classes have a different SCHEMA_ID() defined.
Id' like to pass a class to a method and use the static SCHEMA_ID() method on the class. I can pass the class to a method just fine, but getting at the static SCHEMA_ID() proves frustratingly hard.
public <T extends RaeInterface> void get( Class klass){
klass.SCHEMA_ID(); // <-- cannot resolve method.
}
Any suggestions on how to resolve this or is this even possible in Java 8?
Static methods cannot override in implementation of the Interface. If you want to override use default methods in interface.
Interface :
public interface RaeInterface {
default String SCHEMA_ID() {
return "";
}
}
Your mention method :
public <T extends RaeInterface> void get(T klass) {
klass.SCHEMA_ID();
}
Implement class :
class B implements RaeInterface {
#Override
public String SCHEMA_ID() {
return "B";//the ID
}
}
class C implements RaeInterface {
#Override
public String SCHEMA_ID() {
return "C";//the ID
}
}
I think you want an instance method in your interface:
public String schemaId();
Each implementing class can (and must if not abstract) implement this method. It doesn’t need to use any instance stuff for the implementation.
Your calling method gets much simpler and doesn’t need any generics:
public void get(RaeInterface instance){
instance.schemaId();
}
For inspiration you may look at how the java.util.Comparator interface is used. Usually classes implementing this interface don’t contain any instance variables, so you would think the compare method could just as well be static. Its probably only non-static to allow different implementations.
If you really insist on a static method, Sergey Lagutin is correct that reflection will solve your problem. But again, it’s getting more complicated and I don’t see why you should want such a solution.

What is the best practice in Java to set a constant required in subclasses?

I have the following situation:
A parent class has a function that depends on a constant. But the only valid place to define that constant is in subclasses (parent class cannot define the constant's value, but it can be used with the constant undefined in 99% of use cases - the constant is a default to use if a specific configuration element is missing).
However, I would like to enforce that any child class inheriting from that parent class must define the value for the constant, since any child classes have to be able to use the other 1% of functionality.
What is the best practice to implement this enforcement in Java, ideally at compile time? (clearly, at runtime, I can simply check if the constant is null/empty in the method using it).
My own solution was to implement a value-getter for the constant as an abstract method in the parent class, and call that in combination with the real setter in the constructor; something like this:
public class HelperClass1 {
private String myConstant;
public void setMyConstant() {} // implemented obviousy
public void myMethod() { // Called from ParentClass's methods
// Do something useful with myConstant
}
}
import HelperClass1;
public abstract class ParentClass {
ParentClass() {
HelperClass1.setMyConstant( getMyConstantValue() );
}
public abstract void getMyConstantValue();
}
public class ChildClass1 extends ParentClass {
public void getMyConstantValue() { return "BUZZ"; }
}
public class ChildClass2 extends ParentClass {
} // Fails to compile without getMyConstantValue()
However, (a) This implementation has a problem (I can't use ParentClass itself, since it's now abstract) without subclassing; and (b) since I'm not a Java developer, I'm afraid that this isn't the best or the most elegant solution. So I'd like to know if there's a best practices approach that improves on what I implemented.
Provide two constructors for the parent class:
One is a protected constructor which takes the constant as an argument.
The other is private constructor which can construct instances of the parent class without setting the constant.
Provide a factory method for the parent class which can call the private no-constant constructor.
Classes that want to get an instance of the parent class can call the factory method. But child classes that want to inherit from the parent class have to call the protected constructer, which can validate that a valid constant was passed.
public class ParentClass {
private final SomeClass myConstant;
protected ParentClass(SomeClass aConstant) {
if (null == aConstant) {
throw new IllegalArgumentException("...");
}
myConstant = aConstant;
}
private ParentClass() {
myConstant = null;
}
public static ParentClass getInstance() {
return new ParentClass();
}
}
public class ChildClass {
public ChildClass() {
super(new SomeClass(42));
}
}
This isn't perfect. Someone could write a child class that passes a bad constant to the superclass constructor, and it wouldn't actually fail until some code tried to construct an instance of the child class.

Overcome duplicated methods static reference on super

We all know that in Java, if you declare a static method in a Abstract class, that method will belong to the Abstract class, and not to its child. (There is no abstract static)
I have a simple database system that has a Abstract Model class:
public abstract class Model<T> {
// WON'T WORK (unfortunately I can't use abstract static)
public static T find(int id) {
...
}
}
As you can see, I can't create a static method on that class that returns a generic, since that method is not inherited, so it belongs to the abstract class.
A workaround is to make a protected method on the abstract class and then a static method on each of its children:
public abstract class Model<T> {
protected T find(int id) {
...
}
}
public class User extends Model {
public static User find(int id) {
User dummy = new User();
return (User) dummy.find(id);
}
}
I feel that there are better ways of doing that.
Any ideas?
I can think of two possible options, although one is a bit of a hack. The first one would be to make Model<T> a normal class and adding a static method to get the model like this:
//I do not know how you want to do the user class, I just made it take the models class
private static final Model<User> MODEL = new Model<User>(User.class);
public static Model<User> model() {
return MODEL;
}
You would use it like this: User.model().find(id)
Another option would be to add a public static variable to the class and static importing that variable to invoke methods on it as if it were the class and not the Model instance. For example:
public class User {
public static Model<User> User = new Model<User>(User.class);
}
Importing it using static import my.package.User.User; would allow you to use User user = User.find(id); where the first User is the class name and the second User is the static variable.
Otherwise, you will have to put the static methods in each class, because unfortunately you cannot inherit or override them.
You could use a static generic method with a type that extends the parent class. You will, however, need an instance of the type in order to do the return of type T. The easiest way is to pass in the caller, but it could just be an empty instance.
For example, you can do the following:
//No more generic Model
public abstract class Model
{
//Our generic static method; we need caller to get something of type T to return.
public static <T extends Model> T find(int id, T caller)
{
...
return caller.getMyReturnObject(id);
}
}
To invoke this you would just do
Model model = find(someId, new Model{...})
where new Model{...} can be replaced by this if you invoke it within a class that is a child of Model.
If you need to create a new instance of T in the method, then you will still need to pass in something as T (the caller still works) and use reflection to create the new instance (using something like (T) type.getClass().newInstance(); instead of new T()).

Can you get the subclass of a Method that was inherited?

Take a look at this code:
public class Main {
public class A {
public final void method() {}
}
public class B extends A {}
public static main() {
try {
Method method = B.class.getMethod("method");
//Returns the name of Main$A, but I want Main$B
System.out.println(method.getDeclaringClass().getName());
} catch (NoSuchMethodException e) {}
}
}
I'm trying to get the class out of an inherited method that I previously have taken from a subclass. The reasoning for this is in my application, I store all methods with a specified annotation by object into a Set<Method> and store the object itself in a Map<Class<?>, Object> which is to easily invoke the method later.
I understand that it would make sense for method.getDeclaringClass() to return Main$A, since that's where it was declared, not Main$B, but I was just wondering if there was an alternative to solve my problem.
You're trying to reindex the class methods in a way that is incompatible with the java standards. I don't think there is a workaround for this; your code should reflect the way things are structured; i.e.
populate your map with the class returned by getDeclaringClass().

What is Java's 'self' keyword

I'm trying to write a factory method in an abstract class in Java (so I want it to return a new instance of the extending class, rather than the super-class).
In PHP I'd do this using the self keyword:
abstract class Superclass {
public static function factory($arg) {
return new self($arg);
}
private function __construct($arg) {}
abstract public function doSomething() {}
}
Does Java have a keyword like self I can use for this?
No; in Java, static methods are not inherited in the same way as non-static methods are. A subclass will have the static methods of its superclass, but when they execute, they will execute in context of the superclass - so there is no keyword that can be used in static methods to find out what class the method was invoked through.
Edit: A more precise formulation is that static methods are not inherited at all; however, the language allows us to use Subclass.foo() to call the static method Superclass.foo().
Based on what you seem to want to achieve, you might want to implement the Abstract Factory pattern. It goes approximately like this:
public abstract class Superclass {}
public class SubclassA extends Superclass {}
public class SubclassB extends Superclass {}
public abstract class AbstractFactory {
public abstract Superclass Create();
}
public class FactoryA extends AbstractFactory {
public Superclass Create() {
return new SubclassA();
}
}
public class FactoryB extends AbstractFactory {
public Superclass Create() {
return new SubclassB();
}
}
Now, you can e.g. create a method that takes an AbstractFactory (which, in reality, will be either a FactoryA or a FactoryB). Calling Create() on this object will produce either a SubclassA or a SubclassB.
Edit: Fixed compilation error (forgot to make the factories extend AbstractFactory).
If you absolutely have to you can use this code form a static context:
Class cls = new Object() { }.getClass().getEnclosingClass();
Object instance = cls.newInstance();
Your class need to have a nullary constructor.
You need some hacks to achieve this. One way I can think of to obtain this is:
public static <T extends SuperClass> T factory(Class<T> clazz) {
return clazz.newInstance();
}
I don't think it is possible in Java to find out the name of the "current" subclass. And especially some dynamic object generation won't be possible.
So you'll need to define that static function in every subclass instead.

Categories

Resources