Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics with inner class and inner interface

Tags:

java

generics

Below I have a generic OuterClass, an InnerClass that use OuterClass generics and non-generic InnerInterface.

public class OuterClass<E> {

    public class InnerClass  {

        public E someMethod() {
            return null;
        }
    }

    public interface InnerInterface{
        public void onEvent(OuterClass.InnerClass innerClass);
    }
}

In the main method below, I use two instance of OuterClass, o1 parameterized with , and o2 with . My annonymous inner class myListener tries to use the generic type of the outer class (E). The code as it is below does not compile (Integer i = innerClass.someMethod() - Type mismatch: cannot convert from Object to Integer).

public class Test {
    public static void main(String[] args) {

        OuterClass<Integer> o1 = new OuterClass<Integer>();
        OuterClass<String> o2 = new OuterClass<String>();

        OuterClass.InnerInterface innerInterface = new OuterClass.InnerInterface() {
            @Override
            public void onEvent(InnerClass innerClass) {
                Integer i = innerClass.someMethod();
            }
        };
    }
}

I would like to express that myListener is for o1, and should use E = Integer, without repeating it (without repeating , I already say it when declaring o1). Is that possible?

Many thanks! Faton.

like image 354
Faton Avatar asked Mar 23 '11 09:03

Faton


People also ask

CAN interface have generics?

Generic Interfaces in Java are the interfaces that deal with abstract data types. Interface help in the independent manipulation of java collections from representation details. They are used to achieving multiple inheritance in java forming hierarchies. They differ from the java class.

How do generics work internally?

Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.

Is there any difference between an inner class and nested class?

A class that is defined within another class is called a nested class. An inner class, on the other hand, is a non-static type, a particular specimen of a nested class.

How nested class and inner class are helpful in Java explain with example?

In Java, it is possible to define a class within another class, such classes are known as nested classes. They enable you to logically group classes that are only used in one place, thus this increases the use of encapsulation, and creates more readable and maintainable code.


2 Answers

An inner interface or enum is implicitely static, and static members are not parameterized with the type parameters of the outer class. So InnerInterface should look like this:

public interface InnerInterface<E> {
    void onEvent(OuterClass<E>.InnerClass innerClass);
}

Note that the E parameter of InnerInterface is not the same as the E parameter of OuterClass.

like image 128
Laurent Pireyn Avatar answered Oct 13 '22 00:10

Laurent Pireyn


As always, non-private nested types don't help keeping things simple. Push the boat out and create some new files, even if your IDe works against you.

Anyway, static members of a class do not share the generic parameters of the outer class. This is important for the behaviour of fields, and allows more flexibility on static nested types (such as InnerInterface) even if you don't want it. So, in your case, you need to give your (static) nested interface a generic parameter. For $deity's sake, use a different identifier!

public class OuterClass<E> {
    public class InnerClass  {
        public E someMethod() {
            return null;
        }
    }

    public interface InnerInterface<T> {
        void onEvent(OuterClass<T>.InnerClass innerClass);
    }
}


public class Test {
    public static void main(String[] args) {

        OuterClass<Integer> o1 = new OuterClass<Integer>();
        OuterClass<String> o2 = new OuterClass<String>();

        OuterClass.InnerInterface<Integer> innerInterface =
            new OuterClass.InnerInterface<Integer>() 
       {
            @Override
            public void onEvent(OuterClass<Integer>.InnerClass innerClass) {
                Integer i = innerClass.someMethod();
            }
        };
    }
}

(I've also qualified InnerClass where necessary.)

Edit: It's probably worth just looking at the original anonymous inner class in isolation from the rest of the use:

public interface InnerInterface{
    public void onEvent(OuterClass.InnerClass innerClass);
}

    OuterClass.InnerInterface innerInterface = new OuterClass.InnerInterface() {
        @Override
        public void onEvent(InnerClass innerClass) {
            Integer i = innerClass.someMethod();
        }
    };

Integer only appears once, in a place where it clearly cannot be inferred to be correct.

like image 27
Tom Hawtin - tackline Avatar answered Oct 12 '22 23:10

Tom Hawtin - tackline