首先简要说明下程序运行时,内存的结构。堆区栈区,常量区,静态方法区和非静态方法区。 1.栈:存放基本类型的变量数据和对象的引用(也就是在new对象时左边那一块),但是对象本身不放在栈中,而是存在堆(new出来的对象)。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。 2.堆:存放new出来的对象。堆中的对象由垃圾回收器负责回收,因此大小和生命周期不需要确定。 3.常量区:存放字符串常量和基本类型常量。
代码示例:
class Fu{ void method1() { System.out.PRintln("fu method_1"); } void method2() { System.out.println("fu method_2"); } static void method3() { System.out.println("fu method_3"); }}class Zi extends Fu{ void method1() { System.out.println("zi method_1"); } void method4() { System.out.println("zi method_4"); } static void method3() { System.out.println("fu method_3"); }}class DemoDuotai{ public static void main(String args[]) { Fu aa=new Zi();//创建一个父类引用,指向子类。 aa.method1();//发生动态绑定,打印子的 aa.method3();//打印父的 }}内存图简要示例
举个例子来说明编译时(javac)和运行时(java)的区别,代码如下:
class Demo{ private int num; Demo(int num) { this.num=num; } public boolean equals(Object d) { Demo a=(Demo)d; return this.num==a.num; }}class Person{}public class object_equals{ public static void main(String[] args) { Demo a=new Demo(3); Demo b=new Demo(4); Person c=new Person(); System.out.println(a.equals(c)); }}结果:编译通过,运行挂掉
分析:equals方法是超类Object中的方法,我们把他复写,调用equals时,参数 Object d=new Person()这里发生了向上转型,接着Demo a=(Demo)d 编译的时候是不会出错的,因为此处的d引用变量是绑定的Object这个类;而运行时,发生动态绑定也就绑定到了Person类上,把Person类的对象转化成Demo类的对象,出现类型转换错误。
改正:加上以下判断即可.
if(!d instanceof Demo) return ;新闻热点
疑难解答