Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static method in class have same signature as default method in interface

I have below scenario :

class C {
    static void m1() {}
}

interface I {
    default void m1() {}
}

//this will give compilation error : inherited method from C cannot hide public abstract method in I
class Main extends C implements I {

}

Below are my questions:

  1. I am aware that instance method will override the default methods but what if static methods in class have same signature as default method in Interface?

  2. If static method m1() in class C would be public then compilation error will be :

    static method m1() conflicts with abstract method in I.

so when the access modifier was default it was trying to hide and when it is public it is conflicting. why is this difference? what is the concept behind it?

like image 592
user2185089 Avatar asked Aug 09 '17 05:08

user2185089


People also ask

Can we have static and default methods in interface?

Defining a static method within an interface is identical to defining one in a class. Moreover, a static method can be invoked within other static and default methods.

What is difference between static method and default method in interface?

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces. A static method is a method that is associated with the class in which it is defined rather than with any object.

What is static method signature?

Static method definition. The first line of a static method definition, known as the signature, gives a name to the method and to each parameter variable. It also specifies the type of each parameter variable and the return type of the method. Following the signature is the body of the method, enclosed in curly braces.

Can we have static method in interface?

Similar to Default Method in Interface, the static method in an interface can be defined in the interface, but cannot be overridden in Implementation Classes. To use a static method, Interface name should be instantiated with it, as it is a part of the Interface only.


3 Answers

Ultimately that boils down to the fact that when you have something like this:

class Me {
    public static void go() {
        System.out.println("going");
    }
}

These both would be allowed:

Me.go();
Me meAgain = new Me();
meAgain.go(); // with a warning here

Intersting is that this would work too for example:

Me meAgain = null;
meAgain.go();

Personally I still see this as design flaw that could not be retracted due to compatibility - but I wish the compiler would not allow me to access the static method from an instance.

Your first question is not related to java-8 per-se, it has been like this before java-8:

interface ITest {
    public void go();
}

class Test implements ITest {
    public static void go() { // fails to compile

    }
}

default methods just follow the same rule here. Why this happens is actually detailed quite a lot on stack overflow - but the underlying idea is that potentially this would cause confusion on which method to call (imagine ITest would be a class that Test would extends and you do ITest test = new Test(); test.go(); -> which method are you calling?)

I think that for the same reasons this is not allowed also (which is basically your second question, otherwise you would have a static and non-static method with the same signatures)

static class Me {
    static void go() {

    }

    void go() {

    }
}

It's interesting that this is sort of fixed (I guess that they realized it would be really bad to do the same mistake again) in method references:

static class Mapper {
    static int increment(int x) {
        return x + 1;
    }

    int decrement(int x) {
        return x - 1;
    }
}


Mapper m = new Mapper();
IntStream.of(1, 2, 3).map(m::increment); // will not compile
IntStream.of(1, 2, 3).map(m::decrement); // will compile
like image 127
Eugene Avatar answered Oct 19 '22 03:10

Eugene


Answering your 1st question:

Both the "static method in class" and the "default method in interface" are available to the class Main, and hence if they have the same signature, it will create ambiguity.

For example:

class C{
    static void m1(){System.out.println("m1 from C");}
}

public class Main extends C{
    public static void main(String[] args) {
        Main main=new Main();
        main.m1();
    }
}

Output: m1 from C

Similarly,

interface I{
    default void m1(){System.out.println("m1 from I");}
}

public class Main implements I{
    public static void main(String[] args) {
        Main main=new Main();
        main.m1();
    }
}

Output: m1 from I

As you can see, both these can be accessed similarly. So this is also the reason for conflict when you implement I and extend C.

Answering your second question:

If your classed and interfaces are in the same package, the default and public access modifier should work similarly.

Also, m1() in C is static which cannot be overridden, and hence it cannot be considered as implementation of m1() in I and so the compilation issue.

Hope that helps!

like image 39
OutOfMind Avatar answered Oct 19 '22 01:10

OutOfMind


I will answer your first question since the second is already answered

I am aware that instance method will override the default methods but what if static methods in class have same signature as default method in Interface?

I am assuming you are using JDK 1.8 and hence the confusion. default modifier in an interface method is not talking about its access specifications. Instead it mentions that the interface itself need to implement this method. Access specification for the method is still public. Starting from JDK8 , interfaces allow you specify methods with default modifer to allow to extend interfaces in a backward compatible way.

In your interface you had to give default void m1() {} for the compilation to be successfull. Normally we simply define them in an abstract way like void m1(); in an interface You had to implement the method because you specified the method as default. Hope you understand.

like image 1
Fayaz Avatar answered Oct 19 '22 01:10

Fayaz