builder模式中的java类型推理

builder模式中的java类型推理,java,generics,design-patterns,type-inference,builder,Java,Generics,Design Patterns,Type Inference,Builder,我想创建一个参数化(通用)类MyType及其生成器。生成器将有一些忽略类型T的方法和一些使用该类型的方法。但似乎使用这种模式,我必须重复T声明: how to omit this declaration? | V MyType<String> myType = Builder.<String>

我想创建一个参数化(通用)类
MyType
及其生成器。生成器将有一些忽略类型
T
的方法和一些使用该类型的方法。但似乎使用这种模式,我必须重复
T
声明:

                     how to omit this declaration?
                                   |
                                   V
MyType<String> myType = Builder.<String>of()
                               .method1(argument_can_be_of_any_type)
                               .method2(argument_must_be_of_type_T = String)
                               .build();
如何省略此声明?
|
v
MyType MyType=Builder.of()
.method1(参数可以是任何类型的参数)
.method2(参数必须是类型为字符串的参数)
.build();
是否可以使用一些java语法技巧或其他设计模式来省略第二个类型声明,从而使API更加用户友好?例如:

List<String> aList = Lists.emptyList();
List aList=Lists.emptyList();

List aList=newlinkedlist();

我不想在构建器中强制执行任何方法的顺序,因为我的原始答案没有像广告中所宣传的那样有效,所以我做了一些修改。(感谢shmosel发现问题,感谢Daniel Pryden提出解决方案。)

/*Box.java的内容*/
公共类箱
{
私有内容;
私有对象数据;
受保护的框(T内容、对象数据){
this.contents=目录;
这个数据=数据;
}
公共静态BoxBuilder(){
返回新的BoxBuilder();
}
公共T getContents(){
返回内容;
}
}
/*BoxBuilder.java的内容*/
公共类BoxBuilder
{
私有对象数据;
带有任何内容的公共BoxBuilder(对象o){
这个数据=o;
归还这个;
}
//从参数推断新类型
带有BoxContent的公共类型BoxBuilder(T内容){
TypedBoxBuilder=新的TypedBoxBuilder();
builder.setData(数据);
builder.setContents(目录);
返回生成器;
}
}
/*TypedBoxBuilder.java的内容*/
公共类TypedBoxBuilder
{
私有内容;
私有对象数据;
公共类型dboxbuilder(){
}
带有任何内容的公共类型dboxbuilder(对象数据){
这个数据=数据;
归还这个;
}
带有目录的公共类型dboxbuilder(T目录){
this.contents=目录;
归还这个;
}
公共盒子构建(){
返回新框(内容、数据);
}
公共内容(T内容){
this.contents=目录;
}
公共void setData(对象数据){
这个数据=数据;
}
}
以下是客户端代码:

Box<String> box = Box.builder() // Returns BoxBuilder
        .withBoxContent("FOO") // Returns TypedBoxBuilder<String>
        .withAnything(42) // Returns TypedBoxBuilder<String>
        .build(); // Returns Box<String>
String c = box.getContents();
Box-Box=Box.builder()//返回BoxBuilder
.withBoxContent(“FOO”)//返回TypedBoxBuilder
.withAnything(42)//返回TypedBoxBuilder
.build();//返回框
字符串c=box.getContents();
这同样有效:

Box<String> box = Box.builder() // Returns BoxBuilder
        .withAnything(42) // Returns BoxBuilder
        .withBoxContent("FOO") // Returns TypedBoxBuilder<String>
        .build(); // Returns Box<String>
String c = box.getContents();
Box-Box=Box.builder()//返回BoxBuilder
.withAnything(42)//返回BoxBuilder
.withBoxContent(“FOO”)//返回TypedBoxBuilder
.build();//返回框
字符串c=box.getContents();

请发布
Builder
类。method2的参数是否需要为String类型?(换句话说,我们可以从该参数推断build()返回值的最终类型吗?或者它可以是任何类型吗?相关:@ChrisRaser是的,method2的参数必须是字符串。这就是我想要实现的-在没有显式declaration@piotrek,我在下面发布了一个修订的解决方案(有其他人提供的有用建议)。这是一个糟糕的主意。如果使用原始类型,泛型参数将毫无用处,更不用说它将删除同一语句中任何不相关的泛型。是否错过了此
method2(参数\u必须\u是\u类型的\u)
?这太接近了。您需要的是两种生成器类型,
builder
TypedBuilder extensed builder
。然后
builder()
可以返回
builder
(非泛型)和
with boxcontent(T)
可以返回
TypedBuilder
@shmosel,很好的捕获。我没有发现删除其他泛型的问题。代码编译并运行正确,但是当我看到你的评论时,我检查了一下,你是对的——它不是类型安全的。丹尼尔,我知道你要去哪里了,我想,我对它做了一些修补,但它仍然有问题,shmosel发现了。我希望看到一种很好的方法来做类似的事情(从生成器的参数安全地推断生成实例的类型),但我看不出有什么办法可以让它发挥作用。@shmosel,Daniel,我正在努力弥补自己的不足。我采纳了你的两个建议,并把至少能像广告所说的那样起作用的东西放在一起。我仍然没有100%相信这是一个好主意,但考虑到有限的背景,我会给piotrek一些回旋余地。很好的努力来改进你的答案。这似乎是个好主意现在天气很好。
Box<String> box = Box.builder() // Returns BoxBuilder
        .withBoxContent("FOO") // Returns TypedBoxBuilder<String>
        .withAnything(42) // Returns TypedBoxBuilder<String>
        .build(); // Returns Box<String>
String c = box.getContents();
Box<String> box = Box.builder() // Returns BoxBuilder
        .withAnything(42) // Returns BoxBuilder
        .withBoxContent("FOO") // Returns TypedBoxBuilder<String>
        .build(); // Returns Box<String>
String c = box.getContents();