我正在阅读Brain Goetz的一篇文章。我对以下代码的工厂方法有疑问。
public class BoxImpl<T> implements Box<T> {
public static<V> Box<V> make() {
return new BoxImpl<V>();
}
作者已经写了这个以减少类型参数重新声明的冗余
Box<String> box=new Box<String>();
所以,他使用上面的工厂方法。
Box<String> myBox = BoxImpl.make();
但是,我怀疑<V>
类的make方法中Box
的原因,为什么我们不能使用如下:
public class BoxImpl<T> implements Box<T> {
public static<T> Box<T> make() {
return new BoxImpl<T>();
}
上述两个有什么区别?
答案 0 :(得分:1)
此
public class BoxImpl<T> implements Box<T> {
是泛型类声明。它声明了一个类型变量T
,用于实例类成员。
此
public static<V> Box<V> make() {
return new BoxImpl<V>();
}
是一种通用方法。它声明了自己的泛型变量,并且是static
。它不能使用类类型变量。
类型变量的名称在这里不是问题。名称可以相同,但不会引用相同的类型。
答案 1 :(得分:1)
将该方法设为通用非常重要,因为您无法在T
上下文中使用该类的类型参数static
。所以下面的代码不会编译:
class BoxImpl<T> implements Box<T> {
// Will fail to compile. Cannot use type parameter `T` in static context
public static Box<T> make() {
return new BoxImpl<T>();
}
}
类的类型参数的范围是整个的定义 class,除了类的任何静态成员或静态初始值设定项。 这意味着类型参数不能在声明中使用 静态字段或方法或静态嵌套类型或静态 初始化。
答案 2 :(得分:1)
这种技术(在其他方面,由番石榴收藏品使用)在引入钻石操作员之前非常有用&lt;&gt;在Java 7中,要避免非常嘈杂的代码,如:
// Java 5:
Box<Map<String, List<Integer>> box = new BoxImpl<Map<String, List<Integer>>();
// with static inference
Box<Map<String, List<Integer>> box = BoxImpl.make();
// with diamond operator - Java7
Box<Map<String, List<Integer>> box = new BoxImpl<>();
根据为什么在make方法中声明一个新类型参数V
,这是因为它是静态的,而静态方法不能访问类型参数,因为它们超出了范围,属于一个特定的实例化type(类似于实例变量,不能在静态方法中使用)