我试图理解如果抽象类和接口中都存在方法会发生什么。下面,我发布了一个场景,让您清楚地了解我所指的是什么。
interface act
{
void read();
}
abstract class enact
{
void read() {
System.out.println("hello");
}
}
public class second extends enact implements act
{
public void read() {
// does method read() correspond to Interface or abstract class?
}
}
令人惊讶的是,编写此代码时没有编译错误。任何建议都会非常有用。
答案 0 :(得分:1)
我只是想知道方法read()是否与接口或抽象类
有关
或两者都没有。它取决于您实际使用它的上下文中的表观类型。例如。你是否
enact example = new second();
或
act example = new second();
两者都允许您编译代码:
example.read();
因为read()方法在两种明显的类型中定义,act和enact。但在这两种情况下,它都是“第二”类中定义的read()定义才真正重要。这就是被执行的东西。
答案 1 :(得分:1)
我不确定您期望出现什么样的问题,因此我将尝试证明此方案没有问题。
您正在通过以下引用调用方法:
"env": {
"PORT": 5050,
"ROOT_URL": "http://youripaddress"
},
这将执行来自Second sc = new Second();//you should name your classes with upper-case
sc.read();
类的代码,因为这是 Second
引用中存储的对象 的类型(这是多态性的工作原理 - 或者准确地说dynamic binding)。
您还可以创建sc
类的实例并将其传递给Second
类型的引用(Java中的所有类型都应以大写字母开头,包括接口和枚举),如
Act
由于Act act = sc;// or Act act = new Second();
act.read();
方法是多态的(只有final,private或static方法不是),因此在运行时JVM会查找要在类中执行的代码,哪个实例存储在read()
接口中,所以因为它是来自该类的art
类代码Second
的实例将被执行(如果你不会在继承自read()
抽象类的类代码中重写它将被执行)。
答案 2 :(得分:1)
我的理解如下。让我们从考虑更简单的设置开始。 Class Second是抽象的,并实现了两个接口,Act和React。两个接口都声明了一个非默认的void read()方法。在这种情况下,Second继承了同一方法的多个声明,没有实现,编译器很满意(JLS 8.4.8.4)。
interface Act {
void read();
}
interface React {
void read();
}
public abstract class Second implements Act, React {
}
如果一个或两个接口方法都是默认方法,我们会得到编译器错误(JLS 8.4.8.4,9.4.1.3),除非Second从超类(JLS 8.4.8.4)继承抽象read()方法,如以下场景,其中Second实际上最终继承了三个read()方法。
interface Act {
default void read() {}
}
interface React {
void read();
}
abstract class First {
abstract void read();
}
public abstract class Second extends First implements Act, React {
}
如果没有这样的超类,Second必须给出read()的实现,从而阻止冲突方法的继承(JLS 9.4.1.3)。当然,如果所有接口方法都是抽象的,并且我们不希望将类本身声明为抽象,则Second必须这样做。
如果Second确实给出了read()的具体实现,如下例所示,这个方法并没有"关联"接口方法中的一个或另一个:它简单地覆盖并阻止具有相同签名的任何和所有超接口方法的继承 - 更准确地说,使用签名,其中第二个中的read()的签名是其子签名。 - 好像只有一种这样的方法(JLS 8.4.8.1)。 (在某些极端情况下,方法可能无法同时满足它所要覆盖的方法的所有合同.James Gosling在他的第4.3.2节中提供了一个很好的例子 - 和同事们 - ' - - Java编程语言。)
interface Act {
void read();
}
interface React {
void read();
}
public class Second implements Act, React {
@Override
public void read() {}
}
你的情况类似。
interface Act {
void read();
}
abstract class Enact {
void read() {}
}
public class Second extends Enact implements Act {
@Override
public void read() {}
}
唯一真正的区别是,Enact中的read()是一个具体的方法(事实上,Enact是抽象的无关紧要),但事情并没有太大变化:Second中的声明会覆盖read()in执行中的Act和read()(JLS 8.4.8.1)。同时,它是Act接口的有效实现,所以这里确实没有问题。
请注意,即使Second没有覆盖read(),此代码也会编译:第二个将从Enact继承read(),并且继承的方法将被视为Act的同等有效实现(JLS 8.4.8,8.4。 8.1,9.4.1.3)。