Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this class compile even though it does not properly implement its interface?

Tags:

java

generics

a List then Why does the code (below) compile? Surely MyClass2 should return a List<Integer> ?

public class Main {
  public static void main(final String[] args) {
    MyClass myClass = new MyClass();
    List list = myClass.getList();
    System.out.println(list);
    System.out.println(list.get(0).getClass());

    MyClass2 myClass2 = new MyClass2();
    List list2 = myClass2.getList();
    System.out.println(list2);
    System.out.println(list2.get(0).getClass());
  }

  public interface Int1 {
    public List getList();
  }

  public interface Int2 extends Int1 {
    @Override
    public List<Integer> getList();
  }

  public static class MyClass implements Int2 {
    @Override
    public List<Integer> getList() {
      return Arrays.asList(1, 2, 3);
    }
  }

  public static class MyClass2 implements Int2 {
    @Override
    public List getList() {
      return Arrays.asList("One", "Two", "Three");
    }
  }
}

I have noticed if you try to make it a List<String> then you get an error "java: Main.MyClass2 is not abstract and does not override abstract method getList() in Main.Int2". I don't quite understand why you don't get this in the example above.

Note: The solution to the problem in my project is to make the interface itself generic, i.e. Int1<X> (of course I use better names than this, its just an example).

like image 987
Paul Richards Avatar asked Jul 18 '13 08:07

Paul Richards


People also ask

What happens if a class has implemented an interface but has not provided implementation for that method defined in interface?

So it specifies a set of methods that the class has to implement. If a class implements an interface and does not provide method bodies for all functions specified in the interface, then the class must be declared abstract.

Why is an interface not implemented?

It means that you should try to write your code so it uses an abstraction (abstract class or interface) instead of the implementation directly. Normally the implementation is injected into your code through the constructor or a method call.

When a class implements an interface does not provide implementation for all the methods?

Must we implement all the methods in a class that implements an interface in Java? Yes, it is mandatory to implement all the methods in a class that implements an interface until and unless that class is declared as an abstract class. Implement every method defined by the interface.

What happens when a class implements an interface?

When a class implements an interface, you can think of the class as signing a contract, agreeing to perform the specific behaviors of the interface. If a class does not perform all the behaviors of the interface, the class must declare itself as abstract. A class uses the implements keyword to implement an interface.


1 Answers

I suspect, the compiler should be giving you warning for Unchecked conversion, rather than marking it as compiler error. Let's understand why does it warn you:

You have following two methods to implement to satisfy the contract of interface you implement:

public List getList();
public List<Integer> getList();

Now, if in your class, you just provide implementation of the first method, it can handle the request for the 2nd method. You can return a List<Integer> with the return type being List. That's because a List<Integer> is nothing but a List at runtime, due to type erasure.

But, if you just give the 2nd method implementation, it won't satisfy the contract of first method. First method says, it can return any type of List, since it has used raw type in the return type. So, it can return List<Integer>, List<Object>, List<String>, anything. But the 2nd method can only return List<Integer>.

Compiler will do this type checking at compile time and it will give you warning, that List requires unchecked conversion to List<Integer>, because the conversion will anyhow succeed at runtime, due to type erasure.


This is the similar case as below:

List<String> listString = new ArrayList<String>();
List rawList = new ArrayList();

listString = rawList;  // Warning: Unchecked conversion
rawList = listString;

Suggested Reading:

  • Can I cast to a parameterized type?
like image 74
Rohit Jain Avatar answered Nov 15 '22 14:11

Rohit Jain