Change signature of interface methods in implementations

Every once in a while, I learn a new fact that reminds me to stay humble with my knowledge of Java.

As you know, to implement a method defined in an interface, you are supposed to provide a method with the same signature.
Let’s take:

public interface Test {
	Collection getSomething();
}

If you implement it in this way:

public class TestImpl implements Test {
	public Object getSomething() {
		return null;
	}
}

You’ll get a compiler error, as the return type is not compatible. So the right way it to write:

public class TestImpl implements Test {
	public Collection getSomething() {
		return null;
	}
}

Nothing special here.

Now, what about the other way round? Something like this?

public interface Test {
	Object getSomething();
}
public class TestImpl implements Test {
	public Collection getSomething() {
		return null;
	}
}

Incredibly, this works perfectly, both at compiler and runtime.

Of course, once you think about it, it makes perfect sense. The signature remains compatible, since your new method is still returning an Object, albeit a specific one.

Still, it is surprising. Well, to me at least. It is something that we are not *told*! ;-)

About Eric Lefevre-Ardant

Independent technical consultant.
This entry was posted in java. Bookmark the permalink.

3 Responses to Change signature of interface methods in implementations

  1. Sadek Drobi says:

    Interesting, but does it work only for the return type? i guess so!
    anyway i tried it in dotnet and it doesnt work…

  2. Eric Lefevre says:

    Well, clearly, it would not be able to give a more specialize type for the parameters in an implementation, as you could get an invalid parameter type. So you cannot declare
    void setSomething(Object obj);
    in an interface and implement it with
    void setSomething(String str) {…}
    as you would be running the risk of getting something not compatible with String.

    However, the opposite would be interesting. Say you declare
    void setSomething(String str);
    if you implement it with
    void setSomething(Object obj) {…}
    well, it *could* work! Except that it doesn’t, of course. The compiler flags it.

    Regarding .NET, I’m a bit surprised that you cannot generalize the return type. It could mean that .NET is treating the method signature a bit differently than Java does. If I recall, the definition of a method signature in Java only contains the name and the parameters, but not the return type (or the throws declaration).

  3. David Gageot says:

    I don’t think that this worked before JDK5

Comments are closed.