java关于多态性的说法正确的是_java 关于多态的一点总结

一直不是很理解多态,今天看了两遍《think in java》第八章,试着总结一下。

多态的本质就是动态绑定。

将一个方法调用同一个方法主体关联起来叫做绑定。java中除了static方法和final方法(private方法属于final方法)之外,其他所有的方法都是后期绑定。

所以先不考虑static和final,看看多态是怎么样的。

记得c++中父类指针指向子类对象时默认是使用父类函数的,除非父类中函数是虚函数。

而在java不同。一个父类的引用指向子类的对象,如果子类重写了父类的方法,那么默认是调用子类的方法。

重写(override)和重载(overload)的区别

听说面试经常考这个?但是完全不一样嘛。重载要求是方法名相同,参数列表不同,而且和继承无关。但是重写的要求是子类中方法与父类中方法参数列表完全相同,返回值也要相同,或者子类返回值为父类返回值的子类型。重写可以通过@Override标注出来,防止出错,也使代码结构清晰。

用父类引用指向子类对象,会“缩小”接口。一个父类的引用,就算指向了子类的对象,那也只能使用父类有的方法,只不过有一些被重写了而已。一个应该使用父类的方法可以传参为一个子类,称作向上转型(Upcast)。很好理解,因为一个子类拥有父类所有的接口,可以满足方法所有的需求。

多态的好处:

现在来看窝就理解了两点

1.简化代码。写一个参数为父类的方法可以代替为很多子类分别写一个方法。

2.可扩展性。只要写一个父类,就可以随时扩充一个子类。而原来指向父类的方法不需要改变就可以用于新子类。这很重要。

借用别人博客的例子 同时考察了重写和重载

1 classA {2 publicString show(D obj) {3 return ("A and D");4 }5 publicString show(A obj) {6 return ("A and A");7 }8 }9 class B extendsA {10 publicString show(B obj) {11 return ("B and B");12 }13 publicString show(A obj) {14 return ("B and A");15 }16 }17 class C extendsB {}18 class D extendsB {}19

20 public classMain {21 public static voidmain(String[] args) {22 A a1 = newA();23 A a2 = newB();24 B b = newB();25 C c = newC();26 D d = newD();27 System.out.println(a1.show(b)); //1

28 System.out.println(a1.show(c)); //2

29 System.out.println(a1.show(d)); //3

30 System.out.println(a2.show(b)); //4

31 System.out.println(a2.show(c)); //5

32 System.out.println(a2.show(d)); //6

33 System.out.println(b.show(b)); //7

34 System.out.println(b.show(c)); //8

35 System.out.println(b.show(d)); //9

36 }37 }

1~3,都是A类引用指向A类对象,那么没有重写多态什么的,直接根据参数选择方法,很简单。

4~6,A类引用指向B类对象,会涉及多态。对于A类引用来说,只会有两个方法,一个是show(D),一个是show(A)。show(D)没有被重写,输出"A and D",show(A)被重写输出"B and A"。然后根据参数选择方法就好了。

7~9,B类引用指向B类对象,不涉及多态。B一共有3个方法,继承自父类的show(D)输出"A and D",继承自父类又被重写的show(A)输出"B and A",子类中添加的show(B)输出"B and B"。然后根据参数选择。

输出:

A and A

A and A

A and D

B and A

B and A

A and D

B and B

B and B

A and D

再写一个我觉得需要注意的

1 classF {2 public voidf1() {3 System.out.println("f1 in F");4 f2();5 }6 public voidf2() {7 System.out.println("f2 in F");8 }9 }10

11 class S extendsF {12 public voidf1() {13 System.out.println("f1 in S");14 f2();15 }16 public voidf2() {17 System.out.println("f2 in S");18 }19 }20

21 public classMain {22 public static voidmain(String[] args) {23 F f = newS();24 f.f1();25 }26 }

输出

f1 in S

f2 in S

1 classF {2 public voidf1() {3 System.out.println("f1 in F");4 f2();5 }6 public voidf2() {7 System.out.println("f2 in F");8 }9 }10

11 class S extendsF {12 public voidf2() {13 System.out.println("f2 in S");14 }15 }16

17 public classMain {18 public static voidmain(String[] args) {19 F f = newS();20 f.f1();21 }22 }

输出

f1 in F

f2 in S

1 classF {2 public voidf1() {3 System.out.println("f1 in F");4 }5 }6

7 class S extendsF {8 public voidf1() {9 System.out.println("f1 in S");10 f2();11 }12 public voidf2() {13 System.out.println("f2 in S");14 }15 }16

17 public classMain {18 public static voidmain(String[] args) {19 F f = newS();20 f.f1();21 }22 }

输出

f1 in S

f2 in S

1 classF {2 public voidf1() {3 System.out.println("f1 in F");4 f2();5 }6 public voidf2() {7 System.out.println("f2 in F");8 }9 }10

11 class S extendsF {12 public voidf1() {13 System.out.println("f1 in S");14 f2();15 }16 }17

18 public classMain {19 public static voidmain(String[] args) {20 F f = newS();21 f.f1();22 }23 }

输出

f1 in S

f2 in F

主要注意一下第二个吧,可以看出即使是父类的方法中调用的方法也会被重写。

然后考虑一下final

考虑一下下面的代码输出什么

1 classF {2 final voidf() {3 System.out.println("F");4 }5 }6

7 class S extendsF {8 final voidf() {9 System.out.println("S");10 }11 }12

13 public classMain3 {14 public static voidmain(String[] args) {15 F f = newS();16 f.f();17 }18 }

答案是:

嗯。。编译错误。。Cannot override the final method

所以final方法不能被重写。当你不想让一个方法被重写,可以把方法设置为final

然后看一下private方法。虽然private也是final的,但是在这里还是有一点区别,因为父类的private方法对于子类是不可见的。

1 classF {2 private voidf() {3 System.out.println("F");4 }5 }6

7 class S extendsF {8 //@Override 加上这句会出现错误 可知并不是重写

9 private voidf() {10 System.out.println("S");11 }12 }13

14 public classMain3 {15 public static voidmain(String[] args) {16 F f = newS();17 //f.f(); Error:The method f() from the type F is not visible

18 }19 }

对于private方法可以在子类添加相同方法,但并不是重写,只是一个无关的全新方法,同时这样会造成混淆,所以不要这样使用。

接下来是static

按照《thinking in java》上的说法,构造器也是static的(虽然并不理解)。构造器中最好只调用final方法。因为其他方法可能会造成重写,而我们又知道,初始化的时候是先初始化父类再初始化子类的,这样就会导致子类还未初始化完成就被调用,可能产生一些错误。

静态方法的继承

1 classStaticSuper {2 static voidf() {3 System.out.println("Super");4 }5 }6

7 class StaticSub extendsStaticSuper {8 static voidf() {9 System.out.println("Sub");10 //super.f(); error:Cannot use super in a static context

11 }12 }13

14 public classMain {15 public static voidmain(String[] args) {16 StaticSuper sup = newStaticSub();17 sup.f();18 StaticSub sub = newStaticSub();19 sub.f();20 }21 }

输出:

Super

Sub

可知对于静态方法不存在多态,子类中方法会覆盖父类相同方法。但是静态方法是否被继承?

1 classStaticSuper {2 static voidf() {3 System.out.println("Super");4 }5 }6

7 class StaticSub extendsStaticSuper {8 }9

10 public classMain {11 public static voidmain(String[] args) {12 StaticSuper sup = newStaticSub();13 sup.f();14 StaticSub sub = newStaticSub();15 sub.f();16 }17 }

输出

Super

Super

可见静态方法是会被继承的。

上面所有讨论的都是方法。对于域,是不存在多态的!

1 classSuper {2 public int field = 0;3 public intgetField() {4 returnfield;5 }6 }7

8 class Sub extendsSuper {9 public int field = 1;10 public intgetField() {11 returnfield;12 }13 public intgetSuperField() {14 return super.field;15 }16 }17

18 public classMain {19 public static voidmain(String[] args) {20 Super sup = newSub();21 System.out.println(sup.getField());22 Sub sub = newSub();23 System.out.println(sub.getField());24 System.out.println(sub.getSuperField());25 }26 }

输出

1

1

0

over~~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值