Understanding Inner Common Classes

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 receive this warning? The division of internal type B does not contain a type parameter, so it is not a general type. Moreover, the specification gives us the following:

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

Class B does not declare type variables. So why is this a typical type?

+5
source share
6 answers

I agree that the specification of the generic classes does not explicitly cover your scenario. But the specification of raw types :

More precisely, the type raw is defined as one of:

  • The type of link that is formed by accepting the name of the declaration of a type type without a list of arguments of a companion type.

  • An array type whose element type is raw.

  • The member type < static type of the raw type R, which is not inherited from the superclass or superinterface R.

+3
source

Although inner class B does not declare any type variables, an instance of it implicitly refers to an instance of the outer class that does.

Why did I receive this warning?

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

Because you declared a variable b with a raw type. Instead, you can declare:

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

You are not using a generic type. I will explain this with a slightly more detailed example:

 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; } } } 

Here you can clearly see that B depends on the general parameter T , not being general. As explained by Andy Thomas , instance B can only be created in coexistence with the instance Test . Therefore, B is (indirectly) general. In this example:

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

B does not indicate a common parameter, but T does. That is why you get a warning.

The correct way to write this code is:

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

In this case, B completely specified and the types correspond.

+2
source

Although B is not parameterized, Test.B b = t.new B(); contains an unhandled reference to Test, which is parameterized. I received a warning to disappear when I changed the warning line to Test<Integer>.B b = t.new B();

+2
source

What you are trying does not work, because type B is not B, but Test<T>.B

To make this work, make class B static.

 public static class B{ } 
+1
source

B is the inner class. It cannot exist without an instance of Test . Thus, it also depends on any parameters of type Test . When compiled, class B converted to the following:

 public class Test$B { public Test$B(Test paramTest) {} } 

(This is what you get if you compile it and then decompile it.)

You can see that its constructor requires Test . Although type parameters are erased during compilation, if you yourself wrote such a class, you will probably pass it a type parameter that will be passed along with Test .

+1
source

All Articles