1

I have this container:

public class DIContainer {
    protected static DIContainer instance;
    protected Hashtable<Class<?>, Class<?>> classMap;

    protected DIContainer(){
        this.classMap = new Hashtable<Class<?>, Class<?>>();
    }

    public static DIContainer getInstance(){
        if (DIContainer.instance == null)
            DIContainer.instance = new DIContainer();
        return DIContainer.instance;
    }

    public void regClass(Class<?> interf, Class<?> classToReg){
        this.classMap.put(interf, classToReg);
    }

    public Object create(Class<?> interf, boolean lazy) throws Exception{
        if(!this.classMap.containsKey(interf))
            throw new Exception("No such class registered with "+interf.getName()+" interface");
        else if(lazy == false)
            return this.classMap.get(interf).newInstance();
        else
            return this.classMap.get(interf);

    }
}

And I need to lazy create an object, if lazy creation option is chosen (so it would create some sub-object that would implement same interface). So when first method would be called for that sub-object, it would instantiate 'real' object. How could I do it as I don't know exact method that would be used? How can I check for if any method was called for that object?

Now I only tried this as lazy creation as you can see: return this.classMap.get(interf);

But it gives me an error: java.lang.ClassCastException Do I need some other method to check if any call was made to that sub-object, because after creation is done, I will be out of 'create' method and when method will be called I need to check it somehow?

Here are my test interface and it's implementation class:

public interface Interface1 {
    public String getName();
    public void setName(String name);
}

public class Class1 implements Interface1{
    String name;
    Class1(){}

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }


}

And this is how I test it:

public class Main {

    public static void main(String[] args) throws Exception{
        DIContainer dic = DIContainer.getInstance();
        dic.regClass(Interface1.class, Class1.class);
        Interface1 t1 = (Interface1) dic.create(Interface1.class, true);

P.S. If I set lazy creation to false, then it works.

Andrius
  • 19,658
  • 37
  • 143
  • 243

1 Answers1

0

In your case, the line return this.classMap.get(interf); returns a Class object, which you previously put inside the map with the this.classMap.put(interf, classToReg) line. The Class object definitely cannot be cast to the Interface1 interface, as it does not implement it, which results in the ClassCastException.

What you actually need is to return a kind of a wrapper that implements the Interface1 interface and wraps the lazily instantiated class. When any of the interface's method is called, the wrapper instantiates the actual object and delegates the call.

If you want to lazy-init an arbitrary class, the most straight forward option would be to use Java's dynamic proxy.

Forketyfork
  • 7,416
  • 1
  • 26
  • 33