1. Java篇
import java.util.ArrayList;
import java.util.Stack;
class Super
{
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super
{
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
String name2() { return "Dick2"; }
}
public class Test3
{
public static void main(String[] args)
{
Super s = new Sub();
//s.name2();
System.out.println(s.greeting() + ", " + s.name());
}
}
Test3会输出什么呢? s在Java VM空间是Super还是Sub? s.name2会不会有编译错误?
执行D:/workspace/2009Java/test/bin>D:/Java/jdk/bin/javap -c Test3 >Test3.bytecode, 来看看java的opcode.
Compiled from "Test3.java"
public class Test3 extends java.lang.Object{
public Test3();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #16; //class Sub
3: dup
4: invokespecial #18; //Method Sub."<init>":()V
7: astore_1
8: getstatic #19; //Field java/lang/System.out:Ljava/io/PrintStream;
11: new #25; //class StringBuilder
14: dup
15: invokestatic #27; //Method Super.greeting:()Ljava/lang/String;
18: invokestatic #33; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
21: invokespecial #39; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
24: ldc #42; //String ,
26: invokevirtual #44; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
29: aload_1
30: invokevirtual #48; //Method Super.name:()Ljava/lang/String;
33: invokevirtual #44; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: invokevirtual #51; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
39: invokevirtual #54; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
42: return
}
| invokevirtual | Invoke instance method, dispatch based on run-time type |
| invokestatic |
Invoke a class (static) method
|
2. Run-time type is Sub, Class type is Super. 所以会有以上的输出. 至于s.name2的错误,编译器检查的结果.
2. C++篇
import java.util.ArrayList;
import java.util.Stack;
class Super
{
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super
{
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
String name2() { return "Dick2"; }
}
public class Test3
{
public static void main(String[] args)
{
Super s = new Sub();
//s.name2();
System.out.println(s.greeting() + ", " + s.name());
}
}
这样的输出又是什么呢?
Coming from a C# background you never need to worry about issues like as you always pass objects by reference and there is no such thing as copy constructors, assignment operator overloads and the obvious one is that all objects are on the heap meaning that assigning a to b means b and a point to the same thing.
In c++ you have the choice to create an object on the free store or create it on the stack. When objects are store on the stack and a is assigned to b then the copy constructor or the asignment overload will run and copy the object to the other object doing a memberwise / shallow copy.
This becomes a problem when you have a function that takes a base class object without reference semantics. You think that it supports polymorphism but it does not. when you invoke the virtual method it always calls the super classes methods. Why? This is because it was copied to a super class object and all reference to the sub class was lost.
本文通过一个Java示例探讨了多态性的工作原理及其在编译过程中的表现,解释了子类对象赋值给父类引用时的行为特征,并通过Java字节码指令解析了运行时类型确定的方法调用。

被折叠的 条评论
为什么被折叠?



