Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is void not covariant in Java?

If I have this interface:

public interface Foo {
    void bar();
}

Why can't I implement it like this?

public class FooImpl implements Foo {
    @Override
    public Object bar() {
         return new Object();
    }
}

It seems like void should be covariant with everything. Am I missing something?

Edit: I should have been clearer that I'm looking for the design justification, not the technical reason that it won't compile. Are there negative consequences to making void covariant to everything?

like image 823
MattWallace Avatar asked Jan 08 '13 16:01

MattWallace


3 Answers

void is only covariant with void because the JLS says so:

A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2, if and only if the following conditions hold:

  • If R1 is void then R2 is void.

  • If R1 is a primitive type, then R2 is identical to R1.

  • If R1 is a reference type then:

    • R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or

    • R1 = |R2|

like image 113
NPE Avatar answered Sep 19 '22 13:09

NPE


covariance means that if your methods return type is a Supertype object you can return sub-type Object at runtime, void is not the super type of java.lang.Object(or any Object for that matter except itself as answered by MR NPE)

like image 33
PermGenError Avatar answered Sep 20 '22 13:09

PermGenError


Technically void cannot be a covariant return type as the caller needs to know the stack layout. Calling a function that returns an object would result of an object-ref on the top of the stack after the INVOKEVIRTUAL/INTERFACE. Void return type leaves nothing on the top of the stack, hence the functions are binary incompatible.

So the JLS rightfully says it's not possible.

like image 42
bestsss Avatar answered Sep 18 '22 13:09

bestsss