有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java中的Default/Mixin泛型

我想知道是否可以在类初始化时替换泛型类型(无继承)。 情况如下。 在我的模块中,我有一堆通用的actor+builder类,并将其分发给希望在我的团队中使用它的人,同时使actor和fluent界面的入口点保持通用

要求是人们如何提供他们自己的构建器(而不是扩展)来完成他们想要的工作

当前状态:

class MessageBuilder {
    public MessageBuilder msg(String msg) {
        //do something
    }
}

class Actor {        
    public MessageBuilder newMessage() {
        return new MessageBuilder();
    }
}

class Main {            
    @Test
    public void testActor() {
        Actor actor = new Actor();
        actor.newMessage().msg("sss").send();
    } 
}

所需状态:

class MessageBuilder{    
    public MessageBuilder msg(String msg) {
        //do something
    }

    //more fluent api...    
}

// project specific - dont want to extend from generic one as this should be contains its own fluent interface
class MyCustomMessageBuilder {
    public MyCustomMessageBuilder rawstr(String rawstr) {
        //do something
    }
}

class Actor<T> {
    public T newMessage() {
        return (T)builderFactory.getInstance();
    }
}

class Main {            
    @Test
    public void testActor() {
        Actor<MyCustomMessageBuilder> actor = new Actor(BuilderFactory);
        actor.newMessage().rawstr("sss").send();
    } 
}

共 (2) 个答案

  1. # 1 楼答案

    没有一些已知的技巧是不可能的

    首先,Java使用type erasuremore information on type erasure)实现泛型,因此编译器将:

    Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.

    实际上,这意味着Actor<Builder1>Actor<Builder2>在编译后是完全相同的类。在这两种情况下,newMessage的实现如下:

    class Actor {
        public Object newMessage() {
            ...
        }
    }
    

    newMessage不可能基于类型参数有不同的实现,newMessage也不可能请求T的类型,因为它被删除了

    话虽如此,您可以传入类型信息:

    class Actor<T> {
        private Class<T> klass;
    
        public Actor(Class<T> klass) {
            this.klass = klass;
        }
    
        public T newMessage() {
            return klass.newInstance();
        }
    }
    
    class Main {
        @Test
        public void testActor() {
            Actor<MyCustomMessageBuilder> actor = new Actor<>(MyCustomMessageBuilder.class);
            actor.newMessage().rawstr("sss").send();
        }
    }
    
  2. # 2 楼答案

    我会用工厂的方法。建造商应由工厂提供:

    class Actor<MsgBuilder> {
        private final Supplier<MsgBuilder> messageBuilderFactory;
    
        public Actor(Supplier<MsgBuilder> builderFactory) {
            this.messageBuilderFactory = builderFactory;
        }
    
        public MsgBuilder newMessage() {
            return messageBuilderFactory.get();
        }
    }
    

    这种方式在创建消息生成器时提供了灵活性,而不会牺牲类型安全性,也不需要难看的强制转换