简体   繁体   English

类中的静态方法与接口中的默认方法具有相同的签名

[英]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? 我知道实例方法将覆盖默认方法但是如果类中的静态方法与Interface中的默认方法具有相同的签名呢?

  2. If static method m1() in class C would be public then compilation error will be : 如果class C静态方法m1()是公共的,那么编译错误将是:

    static method m1() conflicts with abstract method in I. 静态方法m1()与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? 它背后的概念是什么?

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: Intersting是这样的,例如:

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: 你的第一个问题与java-8本身无关,它在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?) 为什么出现这种情况实际上是详细的堆栈溢出了不少-但基本思想是, 可能这会导致上调用哪个方法混乱(想象ITest将是一类Test会延伸你做ITest test = new Test(); test.go() ; - >你打电话给哪个方法?)

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

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. “类中的静态方法”和“接口中的默认方法”都可用于Main类,因此如果它们具有相同的签名,则会产生歧义。

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 输出: 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 输出: 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. 因此,当您实现I并扩展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. 另外, C m1()是静态的,不能被覆盖,因此它不能被认为是Im1()实现,因此编译问题。

Hope that helps! 希望有所帮助!

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? 我知道实例方法将覆盖默认方法但是如果类中的静态方法与Interface中的默认方法具有相同的签名呢?

I am assuming you are using JDK 1.8 and hence the confusion. 我假设您正在使用JDK 1.8,因此混淆。 default modifier in an interface method is not talking about its access specifications. 接口方法中的default修饰符不是在谈论其访问规范。 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. 从JDK8开始,接口允许您使用默认修饰符指定方法,以允许以向后兼容的方式扩展接口。

In your interface you had to give default void m1() {} for the compilation to be successfull. 在您的界面中,您必须为编译提供default void m1() {}才能成功。 Normally we simply define them in an abstract way like void m1(); 通常我们只是以一种抽象的方式定义它们,如void m1(); in an interface You had to implement the method because you specified the method as default. 在接口中您必须实现该方法,因为您将该方法指定为默认方法。 Hope you understand. 希望你能理解。

Because class methods in java can also be called using instance variables, this construct will lead to ambiguities: 因为java中的类方法也可以使用实例变量来调用,所以这个结构会导致含糊不清:

Main m = new Main();

m.m1();

It is unclear if the last statement should call the class method C.m1() or the instance method I.m1() . 目前还不清楚最后一个语句是应该调用类方法C.m1()还是实例方法I.m1()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当一个类实现两个具有相同方法签名但修饰符default和static不同的接口时会发生什么 - what will happen when a class implement two interface having same method signature but different modifier default and static 接口和类中的方法签名相同 - same method signature in interface and class 与通用签名接口的静态方法 - Static Method in Interface with Generic signature 覆盖父 Class 和接口中存在的方法(具有相同的签名) - Overriding a method(with the same signature) present in both Parent Class as well as the Interface 为什么不能在Java中使用相同的方法签名的静态和非静态方法? - Why can't you have a static and non-static method with the same method signature in Java? 在接口的静态方法内调用默认方法 - Invoking a default method inside a static method of interface 是否可以让方法签名成为它实现的接口的子类型? - Is it possible to have a method signature be a subtype of the interface it implements? 如何使用课堂 <Interface> Java中的方法签名 - How to use Class<Interface> in method signature in Java 通过功能接口方法签名获取 class 构造函数 - Get class constructor by functional interface method signature 子 class 中的 Java 方法能否具有与父 class 中的方法相同的签名,但不会导致覆盖? - Can a Java method in a sub class have the same signature as a method in the parent class but does not cause overriding?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM