从单个构造函数参数推断泛型类类型参数

hujrc8aj  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(446)

我想要的是:
大多数时候,泛型类 TestBuilder<X, X> ,这意味着t和o属于同一类型。因此,我创建了两个不同的构造函数。我想打一些新的电话,比如 new TestBuilder<>(...) (我打电话给 <> 这里没有名字)。
存在以下4个构造函数示例:
1) 工作构造函数调用

// Anonoumous, working
new TestBuilder<>(String.class, Integer.class)
    .withOnNext(new Action1<Integer>()
    {
        @Override
        public void call(Integer integer)
        {   
        }
});

// not anonoumous, classified, working
new TestBuilder<String, String>(String.class)
    .withOnNext(new Action1<String>()
    {
        @Override
        public void call(String string)
        {
        }
});

2) 构造函数调用有问题或不工作

// Anonoumous and working
// PROBLEM: withOnNext is called with Object instead of String
new TestBuilder<>(String.class)
    .withOnNext(new Action1<Object>()
    {
        @Override
        public void call(Object o)
        {
        }
});

// Anonoumous and NOT working
// this is what I want to work!
new TestBuilder<>(String.class)
    .withOnNext(new Action1<String>()
    {
        @Override
        public void call(String string)
        {
        }
});

问题
有办法让第四个构造器工作吗?我不想被迫给构造函数两个类如果我只用一个参数调用它,第二个泛型类应该从第一个“继承”。。。而不是不得不写 new TestBuilder<String, String>(String.class) 我想写信 new TestBuilder<>(String.class) 或者至少 new TestBuilder<String>(String.class) ...

这是test builder类的外观:

public class TestBuilder<T, O>
{
    public TestBuilder(Class<T> eventClass)
    {
        this(eventClass, (Class<O>)eventClass);
    }

    private TestBuilder(Class<T> eventClass, Class<O> observableClass)
    {
        init();
    }

    public TestBuilder<T, O> withOnNext(Action1<O> actionNext)
    {
        mActionNext = actionNext;
        return this;
    }
}
vsnjm48y

vsnjm48y1#

我不认为java能够在没有某种提示的情况下推断出第二种泛型类型。一种方法是在变量声明中给出类型:

TestBuilder<String, String> testBuilder = new TestBuilder<>(String.class);
 testBuilder.withOnNext(new Action1<String>() {
     @Override
     public void call(String string) {
         //...
     }
 });

但是您仍然需要声明这两个泛型参数。
我要做的是封装 T 以及 O 在静态工厂方法中是相同的:

public  class TestBuilder<T, O> {
    public static <T> TestBuilder<T, T>  create(Class<T> eventClass) {
        return new TestBuilder<T, T>(eventClass);
    }
    // ...
}

然后这样称呼:

TestBuilder.create(String.class).withOnNext(...);

另一种选择是将信息封装在继承自的单独类中 TestBuilder :

public class SimpleTestBuilder<T> extends TestBuilder<T,T> {
    public SimpleTestBuilder(Class<T> eventClass) {
        super(eventClass, eventClass);
    }
}

public class TestBuilder<T, O> {
    private TestBuilder(Class<T> eventClass, Class<O> observableClass) {
    }
    // ...
}

用作

new SimpleTestBuilder<>(String.class).withOnNext(...);

另一个好的选择是封装信息 O 与相同 T 在静态方法中:

public  class TestBuilder<T, O> {
    public static <T> TestBuilder<T, T>  create(Class<T> eventClass) {
        return new TestBuilder<T, T>(eventClass);
    }
    // ...
}

用作

TestBuilder.create(String.class).withOnNext(...);
6za6bjd0

6za6bjd02#

您可以为第一个构造函数引入一个helper类型变量,如下所示:

public class TestBuilder <T, O>
{
    public <H extends T, O> TestBuilder(Class<H> c)
    {
        this((Class) c, (Class) c);
    }

    public TestBuilder(Class<T> c1, Class<O> c2)
    {
        // ...
    }

    public static void main(String[] args)
    {
        TestBuilder<String, String> hw = new TestBuilder<>(String.class);
        System.out.println(hw);
    }
}

这将产生一些 unchecked 警告构造函数,但不在调用站点。但是请注意,有些人可能会考虑这种广告实践,特别是因为不是每个人都知道构造函数类型参数。为了完整性,构造函数的显式调用必须如下所示:

new<String> TestBuilder<>(String.class).doStuff()

相关问题