近期复习java时,发觉了自己很多没掌握的知识点,现在每天总结一点点,一点点的积累,一点点的进步。
今天的解决问题——java中覆盖和隐藏的问题(方法和变量)
参考网址:http://school.cnd8.com/java/jiaocheng/10836.htm
http://heisetoufa.javaeye.com/blog/227345
1.先来总结java中方法的覆盖和隐藏
一个大的原则:静态方法不能被覆盖。实例方法被覆盖,静态方法被隐藏。被覆盖的方法只有覆盖它们的类才能访问它们,而访问被隐藏的方法是提供该方法的全局名。
例子:
01: class Super
02: {
03: static String greeting()
04: {
05: return "Goodnight";
06: }
07:
08: String name()
09: {
10: return "Richard";
11: }
12: }
01: class Sub extends Super
02: {
03: static String greeting()
04: {
05: return "Hello";
06: }
07:
08: String name()
09: {
10: return "Dick";
11: }
12: }
01: class Test
02: {
03: public static void main(String[] args)
04: {
05: Super s = new Sub();
06: System.out.println(s.greeting() + ", " + s.name());
07: }
08: }
程序运行结果:Goodnight,Dick
分析:在main函数中,创建了一个子类sub对象实例,通过赋值号我们可以看成其被强制转换成父类super类型。由于greeting是静态方法,它仅仅是被子类sub隐藏,所以通过强制转换成父类super的对象实例s调用时,实际上调用的是父类的greeting方法;而name方法为实例方法,其被子类sub覆盖,所以s.name()是调用的子类name方法。
在继承时需要注意的几点原则:
1)试图用子类的静态方法隐藏父类中同样标识的实例方法不合法,编译器会报错;
2)试图用子类的实例方法覆盖父类中同样标识的静态方法也不合法,编译器会报错;
3)静态方法和最终方法不能被覆盖;
4)实例方法能够被覆盖;
5)抽象方法必须在具体类中被覆盖。
2.再来总结下变量的覆盖和隐藏
原网址的变量分的很详细,不仔细看还被绕的有点糊涂。总结了下,不管是静态变量还是非静态变量,只要是成员变量,它们被覆盖和被隐藏的原则一样。原则:成员变量能够被子类同名的成员变量隐藏,而局部变量和形参不会被隐藏。
例子:
class Base {
int x = 1;
static int y=2;
int z=3;
int method() {
return x;
}
}
class Subclass extends Base {
int x = 4;
int y=5;
static int z=6;
int method() {
return x;
}
}
public class Test {
public static void main(String[] args) {
Subclass s=new Subclass();
System.out.println(s.x + " " + s.y +" "+ s.z);
System.out.println(s.method());
Base b = (Subclass)s;
System.out.println(b.x + " " + b.y +" "+ b.z);
System.out.println(b.method());
}
}
结果:4 5 6
4
1 2 3
4
分析:在main方法中,开始创建了一个subclass对象实例,对于第一个输出很好理解;后将对象实例s强制转换成父类Base类型,由于父类的成员变量只是被隐藏,所以通过强制转换成父类类型的对象实例调用时,调用的是父类中的变量,而method方法是被子类同名方法所覆盖,所以调用时依然调用的子类method方法。
3.最后变量和方法的隐藏及其覆盖的不同
一个类的实例无法通过使用全局名或者强制自己转换成父类型,来访问父类中被隐藏的方法,但是可以通过强制转换为父类型之后,访问父类型中被隐藏的变量。静态方法不能覆盖父类的实例方法,而静态变量却可以隐藏父类的一个同名实例变量。实例方法不能覆盖父类的同名静态方法,而变量却可以隐藏父类的同名成员变量。
4.我最终发现和解决的问题
public class ClassA{
public void methodOne(int i){}
public void methodTwo(int i){}
public static void methodThree(int i){}
public static void methodFour(int i){}
}
public class ClassB{
public static void methodOne(int i){}
public void methodTwo(int i){}
public void methodThree(int i){}
public static void methodFour(int i){}
}
a.哪些方法覆盖了超类中的方法? methodTwo
b.哪些方法隐藏了超类中的方法? methodFour
其他两个方法编译会报错,因为不能用子类的静态方法隐藏父类中同名的实例方法,不能用子类的实例方法覆盖父类中同名的静态方法。