2
package generics;
public class InnerClassGenerics{
     class Innerclasss{

    }
    public static void main(String[] args) {
        InnerClassGenerics icg=new InnerClassGenerics();
        Innerclasss innerclass=icg.new Innerclasss();
    }
}

Above code is possible and compiles fine!!!


Why is the below code doesn't compile, and is it possible to parametrize inner classes?

package generics;
public class InnerClassGenerics<T>{
    class Innerclasss<T>{

    }
    public static void main(String[] args) {
        InnerClassGenerics<String> icg=new InnerClassGenerics<>();
        Innerclasss<String> innerclass=new Innerclasss<>();
    }
}

In the above code if the class is made as static it works fine!!! Why is it not possible without static keyword?

msrd0
  • 7,816
  • 9
  • 47
  • 82
  • 1
    This has *nothing* to do with generics, just saying. – Smutje Oct 19 '14 at 14:20
  • possible duplicate of [Java inner class and static nested class](http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class) – Smutje Oct 19 '14 at 14:21
  • Your type parameter `` in inner class is hiding `` from outer class. Anyway you should correct your example (you are trying to create non-static inner class out of the blue, without using any instance of outer class). – Pshemo Oct 19 '14 at 14:24
  • 2
    Just change `Innerclasss innerclass=new Innerclasss<>();` to `InnerClassGenerics.Innerclasss innerclass=icg.new Innerclasss();`. – Tom Oct 19 '14 at 14:26

2 Answers2

3

Normally if there wouldn't be any generic type on outer class you could write code like this:

Outer outer = new Outer();
Inner inner = outer.new Inner();

because each method in inner class already knows what types should it be using.

But situations is little more complicated when outer class uses generic types. Since inner class have access to all members of its outer class (or classes), it also needs to know about generic type used in outer class(es) to ensure type safety while manipulating generic values.

Take a look at this code:

class Outer<T> {
    private T someValue;

    class Inner {
        T getOuterValue(){
            return someValue;
        }
        void setOuterValue(T value){
            someValue=value;
        }
    }
    //rest of code
}

This means that instance of Inner class also depends on generic type from its outer class(es). That is why while creating reference to inner class you need to explicitly use outer class with generic type by writing it as

Outer<String> outer = new Outer<>();
Outer<String>.Inner inner = outer.new Inner();
^^^^^^^^^^^^^

or explicitly say that outer class uses raw type (which is discouraged) like

Outer.Inner inner = outer.new Inner();

So to make your code work you need to:

  1. add outer class type (preferably with its generic type)

  2. invoke constructor of inner class on instance of outer class (just like non-static methods can't be invoked without instance, non-static (inner) classes must be created using outer class instance)

    InnerClassGenerics<String>.Innerclasss<String> innerclass = icg.new Innerclasss<>();
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^                                 ^^^^
             point 1                                           point 2
    

Also you shouldn't give same names to generic types in nested classes and its outer classes, like in this case

public class InnerClassGenerics<T>{
    class Innerclasss<T>{
        ...
    }
}

because T from Innerclasss hides T from its outer class InnerClassGenerics (not that it causes current problem, but it can make your life difficult later).

Pshemo
  • 122,468
  • 25
  • 185
  • 269
-2

So you have this class definition, and it won't compile because you have 2 types called T. Make it like this and it'll compile:

public class OuterClass <O>
{
    public class InnerClass <I>
    {
    }
}

Also, notice that you are instantiating a non-static class from a static method. You complete code should look like this:

public class OuterClass <O>
{
    public static class InnerClass <I>
    {
    }

    public OuterClass ()
    {
    }
    public InnerClass<O> getInnerClass ()
    {
        return new InnerClass<O>();
    }

    public static void main (String[] args)
    {
        OuterClass<String> outer = new OuterClass<>();
        InnerClass<String> inner = outer.getInnerClass();
    }
}

The code above needs Java 8 to compile.

msrd0
  • 7,816
  • 9
  • 47
  • 82