Understanding inner generic classes

时间:2015-06-30 19:22:18

标签: java generics

I wrote the following code:

public class Test<T> {

    public void method(){
        B b = new B();
    }

    public class B{ }
}

//Some method in some class contains the following lines    
Test<Integer> t = null;
Test.B b = t.new B(); //warning Test.B is a raw type

Why did I get this warning? The declation of the inner type B doesn't contain type parameter, therefore it's not a generic type. Moreover, the specification gives us the following:

A class is generic if it declares one or more type variables

The class B doesn't declare the type variables. So why is it a generic type?

6 个答案:

答案 0 :(得分:5)

虽然内部类B没有声明任何类型变量,但它的一个实例隐式引用外部类的实例,这样做。

  

为什么我会收到此警告?

Test<Integer> t = null;
Test.B b = t.new B(); //warning Test.B is a raw type

因为您使用原始类型声明了变量b。相反,你可以声明:

Test<Integer>.B b = t.new B(); // no warning!

答案 1 :(得分:3)

我同意泛型类的规范并未明确涵盖您的场景。但raw types的规范确实如此:

  

更准确地说,原始类型被定义为以下之一:

     
      
  • 通过获取泛型类型声明的名称而不带伴随类型参数列表而形成的引用类型。

  •   
  • 元素类型为原始类型的数组类型。

  •   
  • 原始类型R的非static成员类型,不是从R的超类或超级接口继承的。

  •   

答案 2 :(得分:2)

您并不真正使用通用类型。我将在一个稍微详细的例子中解释它:

public class Test<T> {  
    public B method(T t) {
        B b = new B(t);
        return (b);
    }

    public class B {
        T value;

        public B(T value) {
            this.value = value;
        }
    }
}

在这里您可以清楚地看到,B取决于通用参数T,而不是通用本身。作为explained by Andy ThomasB的实例只能与Test的实例共存创建。因此,B是(间接)通用的。在您给出的示例中:

Test<Integer> t = null;
Test.B b = t.new B(); //warning Test.B is a raw type

b未指定通用参数,但t会指定。这就是你收到警告的原因。

编写此代码的正确方法是:

Test<Integer> t = null;
Test<Integer>.B b = t.new B();

有了这个,B被完全指定,类型匹配。

答案 3 :(得分:2)

虽然B未参数化,但Test.B b = t.new B();包含Test的原始引用,该引用已参数化。当我将警告线更改为Test<Integer>.B b = t.new B();

时,我收到警告消失

答案 4 :(得分:1)

What you're trying is not working because B's type is not B but Test<T>.B

To get this to work, make class B static.

public static class B{ }

答案 5 :(得分:1)

library(RCurl) url <- "https://logo.clearbit.com/basf.com" png <- getBinaryURL(url, httpheader = "image/png", ssl.verifypeer = F) # download writeBin(png, con = tf <- tempfile(fileext = ".png")) # save shell.exec(tf) # open file on windows 是一个内部类。没有B的实例,它就不可能存在。因此,它还取决于Test的任何类型参数。编译时,类Test将转换为以下内容:

B

(如果你编译它然后反编译它就会得到你的结果。)

您可以看到它的构造函数需要public class Test$B { public Test$B(Test paramTest) {} } 。虽然在编译时会删除类型参数,但如果您自己编写了类,那么您可能会给它一个类型参数以传递给Test