使用接口作为类型参数并使用生成器模式的Java泛型
我有一个接口Foo和一个实现Foo的枚举栏。然后我使用一个简单的生成器模式类结果。请参阅下面的代码使用接口作为类型参数并使用生成器模式的Java泛型,java,generics,interface,builder-pattern,Java,Generics,Interface,Builder Pattern,我有一个接口Foo和一个实现Foo的枚举栏。然后我使用一个简单的生成器模式类结果。请参阅下面的代码 public interface Foo {} public enum Bar implements Foo { BAR } public class Result<T> { public Result(T result) {} public static <T> Result<T> of(T result) { retur
public interface Foo {}
public enum Bar implements Foo { BAR }
public class Result<T> {
public Result(T result) {}
public static <T> Result<T> of(T result) {
return new Result<>(result);
}
public Result<T> set() {
return this;
}
}
公共接口Foo{}
公共枚举栏实现Foo{Bar}
公开课成绩{
公共结果(T结果){}
公共静态结果(T结果){
返回新结果(Result);
}
公共结果集(){
归还这个;
}
}
尝试生成Bar.Bar类型的结果并将其分配给结果变量时,此操作正常:
Result<Foo> r1 = Result.of(Bar.BAR);
Result r1=Result.of(Bar.Bar);
但下面给出了一个编译错误:
Result<Foo> r2 = Result.of(Bar.BAR).set();
Result r2=Result.of(Bar.Bar.set();
不兼容的类型。必需:结果,找到:结果
谁能解释一下原因吗
谁能解释一下原因吗
因为泛型很难,编译器很难猜出你的意思
在Java8中它变得更好了。您的第一次尝试将无法在Java7及以下版本上编译
of
是一种通用方法。Java上的类型推断查看周围的上下文(本例中为赋值变量的类型),以确定目标类型参数。在您的示例中,它可以推断出Foo
,因为Bar.Bar
是Foo
的一个子类型
Result<Foo> r1 = Result.of(Bar.BAR).set();
Result<Foo> r2 = Result.<Foo>of(Bar.BAR).set();
在第二个示例中,链接方法使问题变得更加困难。而且set
不是通用方法。因此,它取决于调用它的表达式的类型。由于方法链接,编译器不能依赖于调用的的上下文。它采用它所看到的类型,即Bar
的Bar.Bar
。然后调用变为(澄清类型)
((结果)Bar.Bar).set();
其中set
的返回类型为Bar
因为
结果
不是结果
,因此一个表达式不能分配给另一个表达式
谁能解释一下原因吗
因为泛型很难,编译器很难猜出你的意思
在Java8中它变得更好了。您的第一次尝试将无法在Java7及以下版本上编译
of
是一种通用方法。Java上的类型推断查看周围的上下文(本例中为赋值变量的类型),以确定目标类型参数。在您的示例中,它可以推断出Foo
,因为Bar.Bar
是Foo
的一个子类型
Result<Foo> r1 = Result.of(Bar.BAR).set();
Result<Foo> r2 = Result.<Foo>of(Bar.BAR).set();
在第二个示例中,链接方法使问题变得更加困难。而且set
不是通用方法。因此,它取决于调用它的表达式的类型。由于方法链接,编译器不能依赖于调用
的的上下文。它采用它所看到的类型,即Bar
的Bar.Bar
。然后调用变为(澄清类型)
((结果)Bar.Bar).set();
其中set
的返回类型为Bar
因为
Result
不是Result
,因此一个表达式不能分配给另一个表达式。第一个示例编译,因为根据Java8的目标类型推断,T
被推断为Foo
,而不是Bar
Result<Foo> r1 = Result.of(Bar.BAR);
在赋值操作符将结果赋值给r1
之前,调用set()
方法。这里,Result.of(Bar.Bar).set()
必须单独考虑,而不考虑r1
的类型,因此T
被推断为Bar
而且,Java的泛型是不变的,因此即使条是Foo
,结果也不是结果。但是您可以使用通配符来解决这种情况
Result<? extends Foo> r1 = Result.of(Bar.BAR).set();
而且,这不是,;您的of
方法只是一个工厂方法。构建器模式使用单独的类,其全部目的是构建目标类的实例
public class Result<T> {
// Prevent anyone except the Builder class from instantiating
// this class by making the constructor private.
private Result(T result) {}
public static class Builder<T>
{
private T result;
public void setResult(T result)
{
this.result = result;
}
public Result<T> build()
{
return new Result(result);
}
}
public Result<T> set() {
return this;
}
}
公共类结果{
//防止除生成器类之外的任何人实例化
//通过将构造函数设为私有来初始化该类。
私有结果(T结果){}
公共静态类生成器
{
私人T结果;
公共无效设置结果(T结果)
{
this.result=结果;
}
公共结果生成()
{
返回新结果(Result);
}
}
公共结果集(){
归还这个;
}
}
第一个示例之所以编译,是因为根据Java8的目标类型推断,T
被推断为Foo
,而不是Bar
Result<Foo> r1 = Result.of(Bar.BAR);
在赋值操作符将结果赋值给r1
之前,调用set()
方法。这里,Result.of(Bar.Bar).set()
必须单独考虑,而不考虑r1
的类型,因此T
被推断为Bar
而且,Java的泛型是不变的,因此即使条是Foo
,结果也不是结果。但是您可以使用通配符来解决这种情况
Result<? extends Foo> r1 = Result.of(Bar.BAR).set();
而且,这不是,;您的of
方法只是一个工厂方法。构建器模式使用单独的类,其全部目的是构建目标类的实例
public class Result<T> {
// Prevent anyone except the Builder class from instantiating
// this class by making the constructor private.
private Result(T result) {}
public static class Builder<T>
{
private T result;
public void setResult(T result)
{
this.result = result;
}
public Result<T> build()
{
return new Result(result);
}
}
public Result<T> set() {
return this;
}
}
公共类结果{
//防止除生成器类之外的任何人实例化
//通过将构造函数设为私有来初始化该类。
私有结果(T结果){}
公共静态类生成器
{
私人T结果;
公共无效设置结果(T结果)
{
this.result=结果;
}
公共结果生成()
{
返回新结果(Result);
}
}
公共结果集(){
归还这个;
}
}