Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generic puzzle

I have Java classes:

abstract class Parent {
    abstract void test(Object pObject, Map<String, Object> pData);
}

public class Test extends Parent {
    @Override
    void test(Object pObject, Map<String, Object> pData) {
    }
}

And would like to refactor the code to:

abstract class Parent<T> {
    abstract void test(T pObject, Map<String, Object> pData);
}

public class Test extends Parent {
    @Override
    void test(Object pObject, Map<String, Object> pData) {
    }
}

Eclipse (4.4.2 if it's matter) tells me that code in Test class is invalid (compile time errors) and correct test() method signature must be:

@Override
void test(Object pObject, Map pData) {
}

My question is WHY!?

Actually, real story is a bit longer. I've a lot of children class (like Test) and don't wish to change them and prefer to use generic (i.e. <T> class) for new children of Parent class. And in both cases second parameter of test() method must be Map<String, Object>.

Any ideas?

like image 403
FoxyBOA Avatar asked Dec 24 '22 15:12

FoxyBOA


2 Answers

My question is WHY!?

When you extend a raw version of Parent, then all the generic information within the class is just ignored. Therefore, you are extending a Parent, which looks like:

abstract class Parent {
    abstract void test(Object pObject, Map pData);
}

In order to preserve the type-parameters for the Map parameter, you can just specify that you're extending a Parent<Object>. Now this code should compile fine:

public class Test extends Parent<Object> {
    @Override
    void test(Object pObject, Map<String, Object> pData) {
    }
}
like image 116
Konstantin Yovkov Avatar answered Jan 13 '23 14:01

Konstantin Yovkov


In the first example, Parent is a plain class and you have sub-clased it in the expected manner, all is good.

In the second example, instead of extending Parent<T> you have extended the generic erased Parent which removes all generics from the class even if they don't involve T.

try

public class Test extends Parent<Object> {
    @Override
    void test(Object pObject, Map<String, Object> pData) {
    }
}
like image 21
Peter Lawrey Avatar answered Jan 13 '23 15:01

Peter Lawrey