< 示例1>
1
class Base {2
int x = 2 ;3
int method() {4
return x;5
} 6
} 7
8
class SubClass extends Base {9
int x = 3 ;10
int method() {11
return x;12
} 13
} 14
15
public class Main { 16
public static void main(String[] args) {17
Base b = new SubClass ();18
System.out.println(b.x);19
System.out.println(b.method());20
} 21
}
2 , 3
<练习>
1
class s1 { 2
public String s = " s1 " ; 3
public String get() { 4
return s; 5
} 6
} 7
class s2 extends s1 { 8
public String s = " s2 " ; 9
public String get() { 10
return s; 11
} 12
} 13
public class s { 14
public static void main(String[] args) { 15
s1 a = new s2(); 16
System.out.println(a.s); 17
System.out.println(a.get()); 18
} 19
} 这个地方就是多态的一个陷阱;
多态是对方法而言的,不是对变量;
s1 a = new s2();这里生成的对象是s1类的实例,但是是由s2类构造的;
java中对变量的选择是静态的,对方法的选择是动态的,是在运行时决定的。(static除外)
运行时实际上调用的是实例的方法,即s1的方法;但对于继承(多态的一种方式),方法的定位是在动态执行时选择的,选择实际构造者,因此就出现了本题的现象了。
另外:多态是对方法而言的,不是对变量;这样说有些不严密,方法应该有个修饰,就是除了final修饰的方法外,java中对函数的调用都是后期绑定,所谓的后期绑定就是动态选择
摘自 崔毅解答csdn疑问时给出的分析
注意以下的方法都被修饰了final
< 示例2>以下哪里会出错?
1
class Base {2
private final void f() {3
System.out.println( " Base.f() " );4
} 5
} 6
7
class Derived extends Base {8
public final void f() {9
System.out.println( " Derived.f() " );10
} 11
} 12
13
public class Main { 14
public static void main(String[] args) {15
Derived op1 = new Derived();16
Base op2 = op1;17
op1.f();18
op2.f();19
} 20
} 21
op2.f(); 处出错!
<示例3>
1
class Parent { 2
private void method1() { 3
System.out.println( " Parent's method1() " ); 4
} 5
public void method2() { 6
System.out.println( " Parent's method2() " ); 7
method1(); 8
} 9
} 10
class Child extends Parent { 11
public void method1() { 12
System.out.println( " Child's method1() " ); 13
} 14
public static void main(String args[]) { 15
Parent p = new Child(); 16
p.method2(); 17
} 18
} 1
答案是:prints: parent’s method2() parent’s method1() 2
如果把父类中method1改成public,那么答案是3
prints: parent’s method2() child’s method1()
分析
多态:
Java 中的函数,除了声明外 final 的外,都是后期绑定。
所谓绑定是建立“函数调用”和“函数本体”的关联。、
所谓的后期绑定是指执行时根据对象类别而进行
多态仅仅对函数而言,不对变量而言;
变量的访问依赖于编译期引用指向的类型;
方法的访问依赖于执行期对象的类型;
向上转型后,调用某个函数,若 derived class overriding 了该函数,则会调用该 derived class 中的函数,否则会调用 base class 中的函数。
向上转型后,只能调用 base class 中被 derived class overriding 的函数,不能调用 derived class 中 extend 函数。
即向上转型后,只能调用 base class 中的方法,不能调用 derived class 中的扩展方法
1
public class CalC {2
void amethod() {3
System.out.println( " CalC.amethod " );4
} 5
CalC() {6
amethod();7
System.out.println( " Hu? " );8
} 9
public static void main(String[] args) {10
CalC cc = new CalChild();11
cc.amethod();12
} 13
} 14
class CalChild extends CalC {15
void amethod() {16
System.out.println( " CalChild.amethod " );17
} 18
} 1
output:2
CalChild.amethod3
Hu ? 4
CalChild.amethod5
为什么CalC Constructor调用的不是自己的amethod()呢 1
方法在内存中只有一个备份,所以的对象都共享这个备份,为了区分开到底是哪个对象在调用这个方法,关键的地方就是this的使用。this把调用方法的上下文对应到当前对象上。2
3
第二,调用java中的所有成员变量或者成员函数都隐含了this。4
5
所以这个地方就很明了了:构造子类,this指针代表的当前对象是子类实例,子类实例为啥不调用自己overriding的方法呢?!6
--------取于 崔毅 之《java编程指南》《java编程思想》学习笔记l
以下是强化和复习:
1 多态只针对非final方法;
不针对变量、final方法
2方法[非final]是运行时对应对象
变量、fianl是编译期间对应对象
3多态只能调用父类中有的方法(向上扩展后)
不能调用父类中没有的方法;
不能调用子类中扩展父类[not overridding]方法
4多态定义:指的是使用同一个实现接口,以实现不同的对象实例
多态好处:多态让程序依赖接口或者抽象类,而不是具体类
p.s
1
class Base {
2
int x = 2 ;
3
String s="s1";
4
int method() {
5
return x;
6
}
7
public String method2(){
8
return s;
9
}
10
}
11
class SubClass extends Base {
12
int x = 3 ;
13
String s="s2";
14
int method() {
15
return x;
16
}
17
public String method2(){
18
return s;
19
}
20
}
21
public class t4 {
22![]()
23
public static void main(String[] args) {
24
Base b = new SubClass ();
25
System.out.println(b.x);
26
System.out.println(b.method());
27
System.out.println("-----用new SubClass会如何?------");
28
System.out.println(new SubClass().x); //相当于 SubClass a=new SubClass(); 然后a.x
29
System.out.println(new SubClass().method());//相当于a.method();
30
System.out.println(new SubClass().s);
31
System.out.println(new SubClass().method2());
32
System.out.println("-----直接new SubClass的test结束------");
33
System.out.println(b.s);
34
System.out.println(b.method2());
35
36![]()
37
}
38![]()
39
}
40
1
2
2
3
3
-----用new SubClass会如何?------
4
3
5
3
6
s2
7
s2
8
-----直接new SubClass的test结束------
9
s1
10
s2
11
这说明直接写new son();//相当于 son son=new son();
class Base {2
int x = 2 ;3
String s="s1";4
int method() {5
return x;6
}7
public String method2(){8
return s;9
} 10
}11
class SubClass extends Base {12
int x = 3 ;13
String s="s2";14
int method() {15
return x;16
}17
public String method2(){18
return s;19
} 20
} 21
public class t4 {22

23
public static void main(String[] args) {24
Base b = new SubClass ();25
System.out.println(b.x);26
System.out.println(b.method());27
System.out.println("-----用new SubClass会如何?------");28
System.out.println(new SubClass().x); //相当于 SubClass a=new SubClass(); 然后a.x29
System.out.println(new SubClass().method());//相当于a.method();30
System.out.println(new SubClass().s);31
System.out.println(new SubClass().method2());32
System.out.println("-----直接new SubClass的test结束------");33
System.out.println(b.s);34
System.out.println(b.method2());35
36

37
}38

39
}40

22
33
-----用new SubClass会如何?------4
35
36
s27
s28
-----直接new SubClass的test结束------9
s110
s211



浙公网安备 33010602011771号