Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.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 使用相同的getter泛化第三方类,而不使用反射_Java_Generics_Java 8 - Fatal编程技术网

Java 使用相同的getter泛化第三方类,而不使用反射

Java 使用相同的getter泛化第三方类,而不使用反射,java,generics,java-8,Java,Generics,Java 8,下面是一个示例代码: class A { private Header header; private Data data; } class B { private Header header; private Data data; } class C { private Header header; private Data data; } class G { private Class messageType; priv

下面是一个示例代码:

class A {
    private Header header;
    private Data data;
}

class B {
    private Header header;
    private Data data;
}

class C {
    private Header header;
    private Data data;
}


class G {
    private Class messageType;
    private Header header;
    private Data data;

    public G(Object message) {
        messageType = message.getClass();   
        if (message instanceof A) {
            header = ((A) message).getHeader();
            data = ((A) message).getData();
        } else if (message instanceof B) {
            header = ((B) message).getHeader();
            data = ((B) message).getData();
        } else if (message instanceof C) {
            header = ((C) message).getHeader();
            data = ((C) message).getData();
        }
    }
}
模型类
A
B
C
不能更改,因为它们来自不同的库(请注意,这些属性只是简化的)。 因此,当我收到这些实例时,我希望以一种通用的方式来处理它们,这就是为什么我创建了一个
G
model类。有没有一种方法可以将属性分配给
G
实例,而不必将
G
a
B
C
紧密地联系在一起,而不必使用反射?这不是一个选择,因为它真的很慢。Java 8解决方案还可以。

不太好

你能做的唯一一件事是:将这两个职责分离开来。意思是:

而不是让一个类负责检索属性并执行此“instanceof”切换。。。你可以把它分为两类

意思:首先定义一些“数据传输类”,它为G提供了G需要的东西,比如

class Foo {
  Foo(String header, ...) { ...
  String getHeader() { ...
  ...
然后将“instanceof”切换移动到某种工厂中,其方法如下:

class FooFactory {
  Foo makeFooFrom(Object message) { ...
然后G使用该FooFactory为任何传入消息获取一个Foo对象

但问题是:如果不使用反射,在独立的类中有不同的字段的“隐式”复杂性是无法解决的,这些字段恰好对您具有相同的含义

我的解决方案唯一的“优势”是:G不需要知道关于A、B、C的任何信息。。。它只知道Foo类

但当然,食品工厂需要知道所有这些事情。大多数情况下,复杂性就像水——你可以让它以不同的方式流动,但你不能压缩它或让它“消失”。

不太可能

你能做的唯一一件事是:将这两个职责分离开来。意思是:

而不是让一个类负责检索属性并执行此“instanceof”切换。。。你可以把它分为两类

意思:首先定义一些“数据传输类”,它为G提供了G需要的东西,比如

class Foo {
  Foo(String header, ...) { ...
  String getHeader() { ...
  ...
然后将“instanceof”切换移动到某种工厂中,其方法如下:

class FooFactory {
  Foo makeFooFrom(Object message) { ...
然后G使用该FooFactory为任何传入消息获取一个Foo对象

但问题是:如果不使用反射,在独立的类中有不同的字段的“隐式”复杂性是无法解决的,这些字段恰好对您具有相同的含义

我的解决方案唯一的“优势”是:G不需要知道关于A、B、C的任何信息。。。它只知道Foo类


但当然,食品工厂需要知道所有这些事情。大多数情况下,复杂性就像水——你可以让它以不同的方式运行,但你不能压缩它或让它“消失”。

单一责任原则:G是一个信息,而不是一个信息工厂:

class G {
    private Class messageType;
    private Header header;
    private Data data;

    public G(Class<?> klass, Header header, Data data) {
        this.messageType = klass;
        this.header = header;
        this.data = data;
    }
}

class GFactory {
    private Map<Class<?>, Function<Object, G>> mappings;

    public <T> void register(
             Class<T> klass,
             Function<T, Header> headerExtractor,
             Function<T, Data> dataExtractor) {
        Function<Object, T> cast = klass::cast;
        mappings.put(klass, cast.andThen(t ->
             new G(klass, headerExtractor.apply(t), dataExtractor.apply(t)))); 
    }

    public G createG(Object message) {
        return mappings.get(message.getClass()).apply(message);
    }

    private GFactory() {
        register(A.class, A::getHeader, A::getData);
    }
}
G类{
私有类消息类型;
私有报头;
私人数据;
公共G(类klass、标题、数据){
this.messageType=klass;
this.header=头;
这个数据=数据;
}
}
类工厂{

私有映射单一责任原则:G是消息,而不是消息工厂:

class G {
    private Class messageType;
    private Header header;
    private Data data;

    public G(Class<?> klass, Header header, Data data) {
        this.messageType = klass;
        this.header = header;
        this.data = data;
    }
}

class GFactory {
    private Map<Class<?>, Function<Object, G>> mappings;

    public <T> void register(
             Class<T> klass,
             Function<T, Header> headerExtractor,
             Function<T, Data> dataExtractor) {
        Function<Object, T> cast = klass::cast;
        mappings.put(klass, cast.andThen(t ->
             new G(klass, headerExtractor.apply(t), dataExtractor.apply(t)))); 
    }

    public G createG(Object message) {
        return mappings.get(message.getClass()).apply(message);
    }

    private GFactory() {
        register(A.class, A::getHeader, A::getData);
    }
}
G类{
私有类消息类型;
私有报头;
私人数据;
公共G(类klass、标题、数据){
this.messageType=klass;
this.header=头;
这个数据=数据;
}
}
类工厂{


私有映射没有机会。因为它们没有公共的超类或实现相同的接口,所以您必须像您已经做的那样使用
instanceof
列出它们,或者使用反射。我只能为您提供一个覆盖get方法的类:类G{Data get(a a){return a.getData();}Data get(B){return B.getData();Data get(cc){return C.getData();}}反射“真慢”吗?有些库一直在使用它,没有任何问题。@eis我们在一秒钟内处理1000条消息。反射方法不需要基准测试。是的,我同意你会注意到这种情况。不可能。因为它们没有公共超类或实现相同的接口,你必须用
instanceof
我只能给你提供一个覆盖get方法的类:类G{Data get(a){return a.getData();}Data get(B){return B.getData();Data get(C){return C.getData();}}反射“真的很慢”吗?有些库一直在使用它,没有任何问题。@eis我们在一秒钟内处理1000条消息。反射方法不需要基准测试。是的,我同意你会注意到这种情况。很好!我终于可以摆脱if-else条件了。让我看看是否可以将GFactory的初始化放在spring上下文文件上。看起来像nice解决方案。虽然我不完全理解它在做什么;-)@GhostCat:一个解决方案,你不理解,就不会是一个好的解决方案。但是如果你专注于
寄存器(a.class,a::getHeader,a::getData),它就不难理解了
line作为解决方案的关键。当然,您必须为
B
C
添加行。请注意,如果
A
B
C
可能有子类,而这些子类不在OP的控制范围内,则此解决方案需要额外的工作。@JulioD-很抱歉,您一方面使用了Spring,但您担心r另一方面是反射速度?这没有意义(除非你真的对每条消息从头开始反射)很好!我终于可以摆脱if-else条件。让我看看是否可以将GFactory的初始化放在spring上下文文件上。看起来像一个ni