01.public class A{
02.
03. public String s = "A";
04.
05. public void setS(String s){
06. this.s = s;
07. }
08.
09. public String getS(){
10. return this.s;
11. }
12.
13.}
14.
15.public class B extends A{
16.
17. public String s = "B";
18.
19. public void setS(String s){
20. this.s = s;
21. }
22.
23. public String getS(){
24. return this.s;
25. }
26.
27. public static void main(String[] args){
28. A a = new A();
29. B b = new B();
30. a.setS("[AA]");
31. b.setS("[BB]");
32. a = b;
33. System.out.print(a.s);
34. System.out.print(b.s);
35. System.out.print(a.getS());
36. System.out.print(b.getS());
37. }
38.}//输出的结果
02.
03. public String s = "A";
04.
05. public void setS(String s){
06. this.s = s;
07. }
08.
09. public String getS(){
10. return this.s;
11. }
12.
13.}
14.
15.public class B extends A{
16.
17. public String s = "B";
18.
19. public void setS(String s){
20. this.s = s;
21. }
22.
23. public String getS(){
24. return this.s;
25. }
26.
27. public static void main(String[] args){
28. A a = new A();
29. B b = new B();
30. a.setS("[AA]");
31. b.setS("[BB]");
32. a = b;
33. System.out.print(a.s);
34. System.out.print(b.s);
35. System.out.print(a.getS());
36. System.out.print(b.getS());
37. }
38.}//输出的结果
我的理解
a = b;那么这句就作废了a.setS("[AA]");
b.setS("BB");所以b.s ="BB";
所以a.s 取出来的是自己的a.s="A"
b.s ="[BB]";
System.out.print(a.getS());这句话被子类复写了,打印[BB]
System.out.print(b.getS());这个很明显是[BB]
[BB]
[BB]
[BB]
重写多态那些事...
属性不支持多态,但可以被覆盖,A类中的s与B类中s各自属于各自的类,a的引用指向b时,由于a类型仍然为父类A,那么a.s指向为父类的this.s,输出A,为什么一开始a.setS("[AA]")不管用了?因为a重新指向了,原来的new A()和a已经没有任何关系了
例如 A a = new B();
使用多态以后 ,如果子类B中重写了父类A的某些方法 ,那么a在调用那些被重写的方法的时候,其实执行的是B类的方法 , 属性不支持重写,如果B中某个属性和A中类型相同、名字相同,当使用a.a这种方式访问的时候,访问的是A类中的a属性。但是调用a.getA()方法的时候,应为B类中重写了该方法,所以实际上执行的是B类中的getA()方法,所以返回的是[BB]
a= b 应该是a 的引用和b相同,
所以,a的访问的属性和方法,都和b一样了。
输出应该全是BB吧
8.25缺陷:域与静态方法class Super{
public int field = 0;
public int getField(){return field;}
}class Sub extends Super{
public int field = 1;
public int getField(){return field;}
public int getSuperField(){return super.field;}
}public class FieldAccess{
public static void main(String[] args){
Super sup = new Sub();//Upcast
System.out.println("sup.field=" + sup.field +
",sup.getField()=" + sup.getField());
Sub sub = new Sub();
System.out.println("sup.field = " + sub.field +
", sub.getField() = " +sub.getField()+
", sub.getSuperField()= " + sub.getSuperField());
}
}/*Output
sup.field = 0,sup.getField() = 1
sub.field = 1,sub.getField() = 1, sub.getSuperField() = 0
*///;书中解释如下:
当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的。在本例中,为Super.field和Sub.field分配了不同的存储空间。这样,Sub实际上包含两个称为field的域:它自己的和从Super处得到的。然而,在引用Sub中的field时所产生的默认域并非Super版本的field域。因此,为了得到Super.field,必须显示的指明super.field.
尽管这看起来好像会成为一个容易令人混淆的问题,但是在实践中,它实际上从来不会发生。首先,你通常会把所有的域都设置成private,因此不能直接访问它们,其副作用只能调用方法来访问。另外,你可能不会对基类中的域和导出类中的域赋予相同的名字,因此这种做法容易令人混淆。
大家谈谈是不是没有解释清楚??
这才是关键!属性不支持重写,并且a.a这种方式访问的时候,访问的是A类中的a属性。
A[BB][BB][BB]?
我的理解
a = b;那么这句就作废了a.setS("[AA]");
b.setS("BB");所以b.s ="BB";
所以a.s 取出来的是自己的a.s="A"
b.s ="[BB]";
System.out.print(a.getS());这句话被子类复写了,打印[BB]
System.out.print(b.getS());这个很明显是[BB……为什么a.setS("[AA]");这句作废了呢?它不是在a=b;之前执行的?
同问啊?解释清楚点!
b.setS("BB");只是使b.s ="BB",其父类的s还是A
a.s指的是父类的s
就这个问题 Super sup = new Super();
Sub sub = new Sub();
sup = sub;
父子类中 同时存在 A属性 和getA()方法;
当sup.A属性时,属性为静态绑定 没有多态特性,所以你用sup父引用.A属性时 虚拟机直接去父区里找A属性;
当sup.getA()方法时,方法时动态绑定 有多态特性,所以虚拟机先去子区找getA()方法 只有在子区找不到getA()方法时,才会去上一级父区里找getA()方法。
这就是属性和方法的区别 也是静态绑定 和 动态绑定的区别;
就Super类 和 Sub类的内存图
|-------------|
| Object |
|-------------|
| Super |
| int A; |
| getA(); |
|-------------|
| Sub |
| int A; |
| getA(); |
|-------------|
在new Sub()对象中:
访问 Super中的A属性 sup.A;
访问 Sub中的A属性 this.A;
访问 Super中的getA()方法 super.getA();(这时如果用sup.getA(),访问的则是Sub中的getA()方法)
访问 Sub中的getA()方法 this.getA();
A a = new A(); 有了个a 里面有个s "[AA]"
B b = new B(); 有个b 里面有个s "[BB]"
a = b; 把b的指针传给a 但是要是调用a.s的话还是自己的s
a.getS() 的话就是调用子类的了,因为构成了重写。
A a = new b();
调用的属性是基类的,调用的方法是子类的。
a = b ; 应该是a 和 b 这两个引用都会指向共同一个new 出来的对象。
画内存图应该很了
B类对象只是改变B类中的字符串s,A类s字符串没有变,但是方法覆盖一定是访问B类的getS()方法返回B类的s字符串
A
[BB]
[BB]
[BB]