Home > Net >  In Java, how does one get the class implementing an interface from within the interface?
In Java, how does one get the class implementing an interface from within the interface?

Time:08-17

I have this interface

public interface Deserializable{
    static <T> T deserialize(byte[] bytes) {
        ReflectionDeserializer rd = new ReflectionDeserializer();
        return rd.Deserialize(bytes);
    }
}

There is a problem in that ReflectionDeserializer needs a class instance in its constructor. In this case, the class I want to pass in is the class of whatever class the implements statement is on, so if I have public class Cat implements Deserializable, I want the interface to put Cat.class into the constructor.

How do I do this?

CodePudding user response:

I have run into this with persistence framework development before. You must pass the desired class into the static method.

static <T extends Deserializable> T deserialize(byte[] bytes, Class<T> targetType) {
    ReflectionDeserializer rd = new ReflectionDeserializer();
    return rd.Deserialize(bytes, targetType);
}

then your RefDes will have something like this

    public <T extends Deserializable> T deserialize(byte[] bytes, Class<T> targetType) {
        T target = targetType.newInstance();
        populateFromBytes(target, bytes);
        return target;
}

This is obviously not production quality code but the basic idea is how I've achieved this in the past. I might have minor details confused about the <> syntax works but this is how I solved this problem for my current project.

CodePudding user response:

You mention "I need the method to be static to be overridable by implementing classes"

That is contradictory, static methods can't be overridden. However, I think what you want is to have it default so that you provide a basic implementation, that can eventually be overridden by another implementation.

If you do that and you declare an abstract getClazz(), you will be able to do as such:

public interface Deserializable<T extends Deserializable> {
    default T deserialize(byte[] bytes) {
        ReflectionDeserializer rd = new ReflectionDeserializer();
        return rd.Deserialize(bytes, getClazz());
    }

    Class<T> getClazz();
}

... So if your class wants to override the deserialize it will be able to do so, else it just returns its implementing class and lets the default implementation to do the job for it.

CodePudding user response:

You might want to consider a different approach to this problem, where Deserializable becomes a generic class holding type T, and has a method that deserializes and returns type T

public class Deserializable<T> {


public <T> T deserialize(byte[] bytes) {
    ReflectionDeserializer rd = new ReflectionDeserializer(T.getClass());
    return rd.Deserialize(bytes);
}


   }

So whenever you'd want to deserialize your Cat object you'd just do

return new Deserializable<Cat>().deserialize(bytes);

You won't have to sort of redundantly state Cat twice like in this example

return Cat.deserialize(bytes, Cat.class)
     

CodePudding user response:

Use getClass(). It is implemented on all Objects and returns the concrete runtime Class for the object it's called on.

  • Related