通用声明混淆

时间:2014-03-22 15:47:39

标签: java generics

我正在阅读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>();
        }

上述两个有什么区别?

3 个答案:

答案 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>();
    }
}

来自Java Generics FAQs:

  

类的类型参数的范围是整个的定义   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(类似于实例变量,不能在静态方法中使用)