覆盖和隐藏

所谓父类静态方法在子类重新定义会被隐藏,指的实际上应该是静态方法,在子类中既不能被重写,也不能被重载。 

所谓静态方法被隐藏应该类似于重写的作用,因为重写也是类似于隐藏了父类的那个方法。 

实际上静态方法一般不存在被隐藏的问题,因为如果两个类有继承关系,并且两个类都有各自的一个静态方法(名称相同,参数,返回都相同),那么如果这时候从外部调用这两个类的静态方法,因为需要加上类名,所以不会重复,比如
class A{static void meth1(){}}   class B extends A{static void meth1(){}}
class C
{
public static void main(String[] args)
{
A.meth1();
B.meth1();//从外部调用静态方法不存在隐藏。
}
}
如果从内部调用,那么就存在隐藏了,实际上就是和重写差不多吧。
class A{static void meth1(){}}
class B extends A
{
static void meth1(){}
public static void main(String[] args)
{
meth1();    //这里调用的是哪一个呢?  调用的是自身的,父类的被隐藏了。
}
}
下面来说下重写和重载 

所谓重写和重载的最大的区别是:方法参数是否能改变。 

例如重写: 
class A 
{ 
void Meth1(int i){} 
} 
class B extends A 
{ 
void Meth1(int i){} 
} 
这就是重写,方法所接收的参数并没有改变。而当我创建一个对象去调用这个方法时,根据对象的不同,调用的方法将不同。例: 
class C 
{ 
public static void main(String[] args) 
{ 
B x11=new B(); //创建一个b的对象 
x11.Meth1(); //这时候调用的实际上就是B类的meth1,父类的meth1被 
//隐藏了。 
A x12=new A(); 
x12.Meth1(); //这时候调用的methe1就是A的methe1了 
} 
} 

而改变方法参数的就是重载。例 
class A 
{ 
void Meth1(int i){} 
} 
class B 
{ 
void Meth1(float j){} 
} 
这时候就是重载,可以看到,方法所需要的参数改变了。而这个时候,创建对象,调用者两个方法,一是看对象是哪个类的对象,二是看调用时候传递的参数是什么来决定具体的调用哪个方法。 
class C 
{ 
public static void main(String[] args) 
{ 
A x11=new A(); 
x11.Meth1(); //A的对象当然只能调用A里面的meth1了 
B x12=new B(); 
B.Meth1(1); //传递的是int,就调用int的那个 
B.Meth1(1.1); // 传递的是float,就调用float的那个 
} 
}






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
其他两个方法编译会报错,因为不能用子类的静态方法隐藏父类中同名的实例方法,不能用子类的实例方法覆盖父类中同名的静态方法。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值