Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
让一个类在java中实现一个未指定的泛型接口_Java_Generics - Fatal编程技术网

让一个类在java中实现一个未指定的泛型接口

让一个类在java中实现一个未指定的泛型接口,java,generics,Java,Generics,我有以下“一般”问题 这是我的通用消息接口 public interface Message<P,R> { void setParams(P Params); // and the corresponding getter void setResults(R results); } 公共接口消息{ void setParams(P Params);//和相应的getter 无效设置结果(R结果); } 为了简单起见,我想通过预定义参数和结果类型

我有以下“一般”问题

这是我的通用消息接口

public interface Message<P,R> {  
    void setParams(P Params); // and the corresponding getter  
    void setResults(R results);  
}  
公共接口消息{
void setParams(P Params);//和相应的getter
无效设置结果(R结果);
}  
为了简单起见,我想通过预定义参数和结果类型来指定大量(接口)消息。因此,如果您使用消息X,您就知道参数和结果类型是什么

比如

public interface MyMessage extends Message<String,String> {}  

公共接口MyMessage扩展消息{}
这很好,现在我想要一个通用的基类,它可以实现任何消息

public class BaseMessage<P,R> implements Message<P,R> {
    P param;
    R results;
    // base implementation
}
公共类BaseMessage实现消息{
P参数;
R结果;
//基本实现
}
上面的问题是我不能有一个实现MyMessage的BaseMessage

多次尝试,如

public class BaseMessage<T extends BaseMessage<P,R>> implements Message<P,R> 
公共类BaseMessage实现消息


public-class-BaseMessage恐怕这样的泛型工厂是不可能的,因为您不能实例化像这样的泛型类型

T a = new BaseMessage<T>();
ta=newbasemessage();
您必须告诉编译器确切的泛型类型参数

您可以做的是创建每个具体消息类型的实例,并将它们存储在一个映射中,对应的类标记作为键。然后,factory方法可以查找正确的消息并直接返回它,或者(如果需要单独的实例)使用message对象创建要返回的实例


在我们当前的项目中,我们有一个类似的设计,不同的是,具体的子类是每个现有的类,具有不同的名称和(不幸的是,大部分(但不是完全)重复的)实现。因此,我们可以使用标准类加载和Spring来实例化它们。

您还没有指定工厂如何决定使用哪个实现类,或者实现类是否需要任何自定义初始化逻辑或参数。假设仅使用默认构造函数实例化已注册的实现类就足够了,您可以执行以下操作:

interface Message<P, R> {
    void setParams(P Params); // and the corresponding getter

    void setResults(R results);
}

interface StringMessage extends Message<String, String> {
}

abstract class MessageImpl<P, R> implements Message<P, R> {
    P param;
    R results;
}

abstract class StringMessageImpl extends MessageImpl<String, String> implements
        StringMessage {

}
class ImplementationMap {
    private Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();

    public <T> void register(Class<T> interfaceClass, Class<? extends T> implementationClass) {
        map.put(interfaceClass, implementationClass);
    }

    public <T> Class<? extends T> get(Class<T> interfaceClass) {
        return map.get(interfaceClass).asSubclass(interfaceClass);
    }
}

public class Test {
    static final ImplementationMap messageImplementors = new ImplementationMap() {{
        register(StringMessage.class, StringMessageImpl.class);
    }};

    static <P, R, M extends Message<P, R>> M create(Class<M> clazz, P p, R r)
            throws Exception {
        M m = messageImplementors.get(clazz).newInstance();
        m.setParams(p);
        m.setResults(r);
        return m;
    }

    public static void main(String[] args) throws Exception {
        StringMessage m = create(StringMessageImpl.class, "p", "r");
    }
}
接口消息{
void setParams(P Params);//和相应的getter
无效设置结果(R结果);
}
接口StringMessage扩展消息{
}
抽象类MessageImpl实现消息{
P参数;
R结果;
}
抽象类StringMessageImpl扩展了MessageImpl实现
StringMessage{
}
类实现映射{
私有映射>映射=新HashMap>();

公共无效寄存器(类interfaceClass,类给定接口
接口消息
接口MyMessage扩展消息
,类
类BaseMessage实现消息
,我看到以下选项:

  • 不要使用
    MyMessage
    并将所有实例替换为
    Message
    。您的工厂将

    public <P,R> Message<P, R> newMessage() { 
        return new BaseMessage<P,R>();
    }
    
    public <M extends Message> M newMessage(Class<M> m) { 
        if (m.isAssignableFrom(MyBaseMessage.class)) {
            return (M) new MyBaseMessage();
        }
        if (m.isAssignableFrom(BaseMessage.class)) {
            return (M) new BaseMessage();
        }
        return null;
    }
    
    公共消息newMessage(){
    返回新的BaseMessage();
    }
    
  • 上课

    class MyBaseMessage extends BaseMessage<String, String> implemens MyMessage
    
    类MyBaseMessage扩展BaseMessage实现MyMessage
    
    工厂将被关闭

    public <P,R> Message<P, R> newMessage() { 
        return new BaseMessage<P,R>();
    }
    
    public <M extends Message> M newMessage(Class<M> m) { 
        if (m.isAssignableFrom(MyBaseMessage.class)) {
            return (M) new MyBaseMessage();
        }
        if (m.isAssignableFrom(BaseMessage.class)) {
            return (M) new BaseMessage();
        }
        return null;
    }
    
    publicmnewmessage(类M){
    if(m.isAssignableFrom(MyBaseMessage.class)){
    返回(M)新的MyBaseMessage();
    }
    if(m.isAssignableFrom(BaseMessage.class)){
    返回(M)新的BaseMessage();
    }
    返回null;
    }
    
  • 不要使用接口

  • 不要使用工厂

  • (如果其他一切都坏了)让你的工厂

    public <M extends Message> M newMessage(Class<M> m) { 
        try {
            return getImplClass(m).newInstance();
        } catch (Exception ex) { /* do proper error handling */ }
    }
    
    publicmnewmessage(类M){
    试一试{
    返回getImplClass(m).newInstance();
    }catch(异常ex){/*执行正确的错误处理*/}
    }
    
    getImplClass()
    :使用javassist在运行时创建一个实现类,该实现类实现接口M并扩展BaseMessage


  • 公共接口MyMessage extends BaseMessage
    这无法工作,在您的示例中,BaseMessage是一个类。感谢您的评论,它确实应该读取公共接口MyMessage extends Message{}。我猜
    M=clazz.newInstance();
    将无法工作,因为M应该是一个接口。是吗?(OP写道)“它将被赋予消息类”)好吧,它应该是接口,正如Arian指出的,被赋予工厂,并且应该返回一个实现类……假设你指的是实现类的对象,我已经更新了我的答案。
    public <M extends Message> M newMessage(Class<M> m) { 
        try {
            return getImplClass(m).newInstance();
        } catch (Exception ex) { /* do proper error handling */ }
    }