Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics and Abstract Methods

Tags:

java

generics

I've come across something I find odd in Java and haven't been able to find much information on it. Consider the following code:

public class TestClass {

    private static abstract class AbstractClass {
        abstract List<? extends Object> getList();
        abstract Map<Long, List<? extends Object>> getMap();
    }

    private static final class ConcreteClass extends AbstractClass {
        @Override
        List<String> getList() { 
            return null;
        }

        @Override
        Map<Long, List<String>> getMap() {
            return null;
        }
    }
}

The compiler shows an error on the getMap() method:

getMap() in ConcreteClass cannot override getMap() in AbstractClass
  return type Map<Long, List<String>> is not compatible with Map<Long, List<? extends Object>>

But the same error is not present for the getList() method, yet I would expect either both to work or both to fail. In both cases, the overriding method is delcaring List<String> in place of List<? extends Object>. Can someone explain this?

like image 263
lucasvw Avatar asked Jul 05 '16 19:07

lucasvw


People also ask

What is the difference between abstract class and generic class?

Abstract is used to define something that requires additional definition of functionality before it is considered "complete" (or concrete in Java-certification-test-terms). Generic means it's a class that can handle a wide variety of data types that you define when you instantiate the class.

What are generics methods?

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

Are generics abstraction?

Generic abstraction consists of 'selectively suppressing information instantiated in a representation, so as to make inferences that pertain only to the generic case' (Nersessian, 2008, p. 193).

Is abstract class a generic class?

Abstract Class Now generics seem cool but they really shine when used with abstract classes. An abstract class is a class that itself is never intended to be instantiated, instead they are used to pass properties to sub classes via inheritance.


1 Answers

It's because there exists an implicit conversion from List<String> to List<? extends Object>, but not from Map<Long, List<String>> to Map<Long, List<? extends Object>>.

All generic types are invariant unless you're using wildcard types. Since there is no wildcard in the "outer" Map type's generic type arguments, it can't capture any generic type that doesn't match exactly.

If your map type were Map<Long, ? extends List<? extends Object>> then it would work like you expect.

And the other part if the answer is that subclasses can override or implement a supertype method with a different return type, but only if the return type of the subtype's method is implicitly convertible to the supertype method's return type. (In Java 1.4 and below even that wouldn't work: it would be a compile time error if the types didn't match exactly.)

like image 103
Daniel Pryden Avatar answered Oct 27 '22 15:10

Daniel Pryden