Java 重写可见性较低的方法会导致编译错误
我有一个类和一个接口:Java 重写可见性较低的方法会导致编译错误,java,overriding,Java,Overriding,我有一个类和一个接口: public interface A { public void getNum(); } public class B { public void getNum() { System.out.println("4"); } } public class C extends B implements A { protected void getNum() { System.out.println("3");
public interface A {
public void getNum();
}
public class B {
public void getNum() {
System.out.println("4");
}
}
public class C extends B implements A {
protected void getNum() {
System.out.println("3");
}
}
现在我的问题是,为什么这段代码会给出编译错误,我们如何避免它。有什么方法可以在C类中重写此方法吗?修复错误并重试;)
当您实现一个接口时,您需要强制重写它以提供函数的具体实现(除非实现该接口的类是抽象的)。在您的例子中,您正在实现一个接口,该接口使您实现
getNum()
函数,并且由于重写类,您有另一个具有相同签名的函数,这是不允许的。所以你得到了编译错误
可能的解决方案:您可以使用B作为接口。为了实现这一点,您可以这样做,因为每个文件只能有一个公共类,并且文件名应该与类的名称相同
public class HelloWorld{
public static void main(String []args){
C obj=new C();
obj.getNum();
}
}
//interface
interface A {
public void getNum();
}
class B {
protected void getNum() {
System.out.println("4");
}
}
class C extends B implements A {
public void getNum() {
System.out.println("3");
}
}
输出:
3来自Java语言规范: 重写或隐藏方法的访问修饰符(§6.6)必须提供至少与重写或隐藏方法相同的访问,如下所示:
- 如果重写或隐藏的方法是public,那么重写或隐藏的方法必须是public;否则,将发生编译时错误
B
(以及接口A
)的public
方法getNum()
。这意味着您试图降低此方法的可见性,但根据规范,此方法是不正确的。要覆盖此方法,您需要在该方法的新版本中使用
public
access修饰符
为什么你不能降低能见度?看看下面的代码,它使用您的类,但放在其他包中,并问自己“这段代码应该如何运行?”
首先,在Java中重写方法时,作用域应该从低到高。子类方法的范围应该高于超类,例如 有效覆盖
class B {
protected void getNum() {
System.out.println("4");
}
class C extends B {
public void getNum() {
System.out.println("3");
}
class B {
public void getNum() {
System.out.println("4");
}
class C extends B {
protected void getNum() {
System.out.println("3");
}
无效覆盖
class B {
protected void getNum() {
System.out.println("4");
}
class C extends B {
public void getNum() {
System.out.println("3");
}
class B {
public void getNum() {
System.out.println("4");
}
class C extends B {
protected void getNum() {
System.out.println("3");
}
第二个问题是您创建了两个无效的公共类。您只能在java文件中创建一个公共类。一个java类文件只能有一个公共类或接口。 将接口和定义类的可见性更改为默认级别或在单独的文件中声明 只有公共和抽象修饰符可以应用于接口方法。实现接口的类不能更改方法的可见性(我们不能将其从public更改为protected)。的解释完全正确,即您不能降低被覆盖的
或接口函数的可见性。
让我们来考试一下
class B
{
protected void getProtected1()
{
System.out.println("4");
}
protected void getProtected2()
{
System.out.println("4");
}
public void getPublic1()
{
System.out.println("4");
}
public void getPublic2()
{
System.out.println("4");
}
}
class C extends B
{
@Override
private void getPublic1() //COMPILATION ERROR : Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
@Override
protected void getPublic2() //COMPILATION ERROR :Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
@Override
private void getProtected1() //COMPILATION ERROR : Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
@Override
public void getProtected2() // NO ERROR IT MEANS YOU ARE ALLOWED TO INCREASE THE VISIBILITY
{
System.out.println("3");
}
}
从上面的示例可以清楚地看出,在任何情况下都不允许降低函数的可见性。
在您的问题中您正在尝试实现接口
功能,我们知道Java中的接口
有如下规则:
- 方法:只允许
公开
和摘要
- 字段:(变量)仅允许
公共
,静态
和最终
根据经验,您永远不能降低重写的
或实现的方法或变量的可见性,对于接口
,它始终是公共的
(如果涉及可见性),因此在实现的类中,这些类应该始终是公共的。如上所述,每个文件只能使用一个公共类。因此,要将它们全部公开,必须创建三个单独的.java文件。我将在下面编写代码,并详细说明如何重写该方法,以便在每种情况下使用正确的版本
可能总是有同名的方法,但为了重写,它们必须有不同的参数列表。这是一个编译器错误,您有三个具有相同参数列表的方法,即none。您可以使用正确的参数列表创建并调用该方法,以获得所需的结果
A.java:
package stackOverflow.tests; // Sample package for visibility
public Interface A {
public void getNum(int a); // Method takes a single integer argument
}
B.java:
package stackOverflow.tests;
public class B {
protected void getNum(int a, int b) { // Method takes two integer arguments, differing in the argument list but equal in name
System.out.println("4");
}
}
C.java:
package stackOverflow.tests;
import stackOverflow.tests.A; // Importing both classes to use their methods
import stackOverflow.tests.B;
public class C extends B implements A {
public void getNum(int a, String x) { // Takes an integer and a string argument
System.out.println("3");
}
public void getNum(int a) {
//Do nothing, as in A.java, this code is necessary to be able to override the method.
}
public static void main(String[] arguments) { // Sample main method for implementation
C c = new C(); // Instantiating class C
int test = 0; // Initializing two integer variables and one String variable
int test2 = 0;
String test3 = "";
c.getNum(test); // takes one integer, using getNum() from A.java
c.getNum(test, test2); // takes two integers, using getNum() from B.java
c.getNum(test, test3); // takes an integer and a String, using getNum() from C.java
}
}
输出:
4
3
如上面代码所示,参数列表定义了使用的方法版本。作为一个小提示,定义getNum(inta)
与getNum(intb)
没有什么不同,因此这将导致它无法编译。泄露秘密。编译错误是什么?为了更好的世界缩进你的代码。为什么不重命名B.getNum()?在JavaC1.7.0_45上对我来说很好。@200_成功这个问题是。现在编辑完成了,编译错误又回来了。现在C类通过继承有了B类方法。现在我只想实现A类的方法。可能的解决方案是什么。@实际上它可以毫无问题地编译,只要您将所有公共类和接口放在单独的.java
文件中,因为每个.java
文件只能有一个公共类,并且该类的名称必须与您在文件中使用的名称相同,如MyClass.java
可以有公共类MyClass
@Pshermo,他可以将所有类放在单个文件。@michali true,但在这种情况下,其中只有一个可以是public
@Pshemo,它可以始终是嵌套类:@michali我怀疑如果是这种情况,OP会提到:)所有的文件都在不同的文件中。