class A1
{
String s = "class A";
void show()
{
System.out.println(s);
}
}
class B extends A1
{
String s = "class B";
void show()
{
System.out.println(s);
}
}
public class TypeConvert
{
public static void main(String[] args)
{
B b1;
B b2 = new B();
A1 a1,a2;
a1 = (A1)b2;
a2 = b2;
System.out.println(a1.s);
a1.show();
System.out.println(a2.s);
a2.show();
b1 =(B) a1;
System.out.println(b1.s);
b1.show();
System.out.println(b2.s);
b2.show();
}
}
就是不明白他们的转换
为什么b2转换成a1后还能输出a1.show();还会输出classB呢?
求详解
{
String s = "class A";
void show()
{
System.out.println(s);
}
}
class B extends A1
{
String s = "class B";
void show()
{
System.out.println(s);
}
}
public class TypeConvert
{
public static void main(String[] args)
{
B b1;
B b2 = new B();
A1 a1,a2;
a1 = (A1)b2;
a2 = b2;
System.out.println(a1.s);
a1.show();
System.out.println(a2.s);
a2.show();
b1 =(B) a1;
System.out.println(b1.s);
b1.show();
System.out.println(b2.s);
b2.show();
}
}
就是不明白他们的转换
为什么b2转换成a1后还能输出a1.show();还会输出classB呢?
求详解
动态绑定
引用类型
a1.s的值为什么是classB而不是classA呢
public class TypeConvert extends java.lang.Object{
public TypeConvert();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: returnpublic static void main(java.lang.String[]);
Code:
0: new #2; //class B
3: dup
4: invokespecial #3; //Method B."<init>":()V
7: astore_2
8: aload_2
9: astore_3
10: aload_2
11: astore 4
13: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_3
17: getfield #5; //Field A1.s:Ljava/lang/String;
20: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: aload_3
24: invokevirtual #7; //Method A1.show:()V
27: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
30: aload 4
32: getfield #5; //Field A1.s:Ljava/lang/String;
35: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: aload 4
40: invokevirtual #7; //Method A1.show:()V
43: aload_3
44: checkcast #2; //class B
47: astore_1
48: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
51: aload_1
52: getfield #8; //Field B.s:Ljava/lang/String;
55: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
58: aload_1
59: invokevirtual #9; //Method B.show:()V
62: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
65: aload_2
66: getfield #8; //Field B.s:Ljava/lang/String;
69: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
72: aload_2
73: invokevirtual #9; //Method B.show:()V
76: return}从这段代码里看,强制转换似乎没有发生,应该是编译期就处理了。
a1 = (A1)b2,这句话的意思是“父类引用指向子类对象”,其中子类对象的对象在堆中分配内存,堆中是子类的对象,这个对象有个指针指向方法区中装载的子类(B),然后在子类的静态常量池查找S,得到classB;
而实例方法的时候是根据方法表来查找的,每个对象有自己的方法表,其中有自己的方法和集成自父类的方法,这个方法表是根据你声明的对象类型来关联的,由于是父类(A)的引用,所以会查找A的方法表,如果查找不到,继续向上查找其父类(这里应该是object)的方法。
a1.s的值为什么是classB而不是classA呢?
对于这个问题 我是这么理解的。java类属性是没有覆盖多态这些概念的。
如果是A的引用它的属性值就是先到父类找。找到了用父类的没找到就到子类找。
而方法就不一样。方法有覆盖多态这一概念
如果A的引用指向B它会先到子类找是否有相应方法有就调用子类的没有就到父类中找。。
System.out.println(a1.s);
输出的就是classA
你看错了