Java-隐藏覆盖和最终修饰符
我找不到像我这样的问题,所以我希望这不是一个重复的问题 同样,它是关于覆盖和隐藏的。我想——但我可能错了——我两者都懂 以下代码的行为与预期一致,这两个方法都已隐藏。method1因为它是私有方法,私有方法只能隐藏,method2因为它是静态方法,静态方法不能被覆盖,所以只能隐藏Java-隐藏覆盖和最终修饰符,java,methods,overriding,final,method-hiding,Java,Methods,Overriding,Final,Method Hiding,我找不到像我这样的问题,所以我希望这不是一个重复的问题 同样,它是关于覆盖和隐藏的。我想——但我可能错了——我两者都懂 以下代码的行为与预期一致,这两个方法都已隐藏。method1因为它是私有方法,私有方法只能隐藏,method2因为它是静态方法,静态方法不能被覆盖,所以只能隐藏 public class Child extends Parent { public void method1(){System.out.println("child");} public
public class Child extends Parent {
public void method1(){System.out.println("child");}
public static void method2(){ System.out.println("static child");}
}
class Parent{
private void method1(){ System.out.println("parent");}
public static void method2(){ System.out.println("static parent");}
public static void main(String[] args){
Parent p = new Child();
p.method1(); //prints out "parent"
p.method2(); //prints out "static parent"
}
}
如果我看了说明书,上面写着:
方法可以声明为final,以防止子类重写
或者把它藏起来
如果我将父类中的method1更改为“final”
一切正常。
编辑开始:我以为编译器会出错,说最终方法不能隐藏,但那没有发生。
:编辑结束
问题1:这是否意味着只能隐藏静态方法?在我正在读的书(OCA研究指南,珍妮·博亚尔斯基和斯科特·塞利科夫,第252页)中,他们明确地说隐藏了一种私人方法
然后我将父类中的method2更改为
public final static void method2(){ System.out.println("static parent");}
现在编译器确实在抱怨,错误是“Child不能重写method2()”,这非常令人困惑,因为我以为我试图隐藏一个方法
问题2:不应该是“Child不能隐藏method2()”吗
编辑开始:我很清楚这里不会发生重写,但正如前面提到的规范所指出的:修饰符final阻止重写或隐藏方法,这就是我将其放在标题中的原因。
:编辑结束问题1
问题1:这是否意味着只能隐藏静态方法
Parent.method1()
在中不可见,也不被Child
继承,这仅仅是因为它是私有的
。因此Child.method1()
没有重写或隐藏Parent.method1()
,它只是在Child
中创建了一个具有相同名称、参数和返回类型的新方法
见:
请注意,在这些术语的技术意义上,私有方法不能隐藏或重写。这意味着子类可以在其一个超类中声明具有与私有方法相同签名的方法,并且不要求此类方法的返回类型或抛出子句与超类中私有方法的返回类型或抛出子句具有任何关系
问题2
问题2:不应该是“Child不能隐藏method2()”吗
是的,你说得对。应该是“隐藏”。根据JLS()
如果类C声明或继承了一个静态方法m,那么m被称为在C的超类和超接口中隐藏任何方法m',其中m的签名是m'签名的子签名(§8.4.2),否则C中的代码可以访问该方法
“隐藏”是static
方法对static
方法所做的事情。“重写”是实例方法对实例方法所做的操作。这两者不能混合:一个静态
方法不能覆盖或隐藏一个实例方法,一个实例方法不能覆盖或隐藏一个静态
方法
顺便说一句,我的Eclipse编译器给出了一个类似的错误消息:“无法重写父级的最终方法”嗯,我对java非常陌生,但我会尝试回答 区别在于您使用的访问级别修饰符不同:您在父类的
method1()
上使用private,在子类的method1()
上使用public。事实上,你没有隐藏这个方法,因为它不是同一个方法。private修饰符指定该成员只能在其自己的类中访问,因此,当您在子类上声明method1()
时,您正在使用一个新方法。即使子级继承父级的所有方法(在扩展它时),私有方法也不会被继承。对于method2()
,它被声明为public
,由子类继承并可以隐藏
更多信息(摘自):
超类中的私有成员
子类不继承其父类的私有成员。但是,如果超类具有访问其私有字段的公共或受保护方法,则子类也可以使用这些方法
嵌套类可以访问其封闭类的所有私有成员,包括字段和方法。因此,子类继承的公共或受保护的嵌套类可以间接访问超类的所有私有成员
编辑:
问题2:
隐藏的是静态方法,而不是最终方法。只有静态的才能隐藏,如下所示:
class SuperClass {
static void display() {
System.out.println("Super");
}
}
class SubClass extends SuperClass {
static void display() {
System.out.println("Sub");
}
}
public class Test {
public static void main(String[] args) {
// Prints "Super" in console
SuperClass sup = new SubClass();
sup.display();
// Prints "Sub" in console
SubClass sub = new SubClass();
sub.display();
}
}
在方法声明中使用final关键字表示该方法不能被子类重写。所以,如果您更改它,您将覆盖它,因此,编译器会说:
重写的方法是静态的final
(注意final
)
编译器抱怨它,因为您不再隐藏它。当您声明它为final时,您正在覆盖它。如果您不在子类上使用static
修饰符,试图覆盖不再是static
的内容,则会出现相同的错误。仅当静态方法隐藏另一个静态方法时才使用隐藏。如果您尝试:
在这些情况下,您不再试图隐藏(因为隐藏仅用于静态),而是尝试覆盖 您的示例有点混乱,因为method2是在method1之前定义的。为了可读性,您可能需要重新构造:a)首先定义method1,然后定义Method2,b)首先定义类父类,然后定义类子类,最后定义包含主方法的某个公共类作为测试框架。现在我真正的问题是:“一切正常”是什么意思?请说明你的期望和发生的事情。我预计在结束时会出现编译器错误
class SuperClass {
static void display() {
System.out.println("Super");
}
}
class SubClass extends SuperClass {
static void display() {
System.out.println("Sub");
}
}
public class Test {
public static void main(String[] args) {
// Prints "Super" in console
SuperClass sup = new SubClass();
sup.display();
// Prints "Sub" in console
SubClass sub = new SubClass();
sub.display();
}
}