本例根据一个实例来说明类方法和实例方法调用的区别,以及不同修饰符下的属性调用的区别,并对这种区别作出解释。
父类定义:
子类定义:
输出结果:
[quote]
父类的名字,静态常量
40
父类生日,变量
父类的类方法,Hello Parent~
子类的实例方法,Bye Child
[/quote]
主函数中声明了对Parent的引用obj1,这个引用指向Son的对象,即实际对象是利用new Son()所创建的实例。
上例中,obj1对调用了Parent类的静态方法sayHello(),而调用了Son类的实例方法sayHello()。对类方法和实例方法调用的区别,《深入Java虚拟机》中有这样一段话可以解释:
[quote]当JVM调用一个类方法时,它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法。相反,当JVM调用一个实例方法是,它会基于实际对象的类(只能在运行时得知)来选择所调用的方法。[/quote]
对象引用obj1的类型Parent自加载进入JVM之后便在内存的方法区维护了静态方法,而Son类的实例方法sayBye()是在被实际对象调用的时候才动态连接的。
基于上面分析可以推测,因为类在方法区中还维护了字段信息、类(静态)变量、常量池,JVM调用一个字段时,它将基于对象引用的类型来选择所调用的字段,故obj1调用的字段皆来自于父类Parent。
[color=gray]注:[/color]常量池:常量池就是该类型所用常量的一个有序集合,包括直接常量(string、integer和floating point常量)和对其他类型、字段和方法的符号引用。池中的数据项就像数组一样是通过索引访问的,因为常量池存储了相应类型所用到的所有类型、字段和方法的符号引用,所以他在java程序的动态连接性中起到核心作用。
父类定义:
public class Parent{
public static String name = "父类的名字,静态常量";
public final int age = 40;
public String birth = "父类生日,变量";
public static void sayHello(){
System.out.println("父类的类方法,Hello Parent~");
}
public void sayBye(){
System.out.println("父类的实例方法,Bye Parent~");
}
}
子类定义:
public class Son extends Parent{
public static String name = "子类名字,静态变量";
public final int age = 20;
public String birth = "子类生日,变量";
public static void sayHello(){
System.out.println("子类的类方法,Hello Child!");
}
public void sayBye(){
System.out.println("子类的实例方法,Bye Child!");
}
public static void main(String[] args){
//1
Parent obj1 = new Son();
System.out.println(obj1.name);
System.out.println(obj1.age);
System.out.println(obj1.birth);
obj1.sayHello();
obj1.sayBye();
}
}
输出结果:
[quote]
父类的名字,静态常量
40
父类生日,变量
父类的类方法,Hello Parent~
子类的实例方法,Bye Child
[/quote]
主函数中声明了对Parent的引用obj1,这个引用指向Son的对象,即实际对象是利用new Son()所创建的实例。
上例中,obj1对调用了Parent类的静态方法sayHello(),而调用了Son类的实例方法sayHello()。对类方法和实例方法调用的区别,《深入Java虚拟机》中有这样一段话可以解释:
[quote]当JVM调用一个类方法时,它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法。相反,当JVM调用一个实例方法是,它会基于实际对象的类(只能在运行时得知)来选择所调用的方法。[/quote]
对象引用obj1的类型Parent自加载进入JVM之后便在内存的方法区维护了静态方法,而Son类的实例方法sayBye()是在被实际对象调用的时候才动态连接的。
基于上面分析可以推测,因为类在方法区中还维护了字段信息、类(静态)变量、常量池,JVM调用一个字段时,它将基于对象引用的类型来选择所调用的字段,故obj1调用的字段皆来自于父类Parent。
[color=gray]注:[/color]常量池:常量池就是该类型所用常量的一个有序集合,包括直接常量(string、integer和floating point常量)和对其他类型、字段和方法的符号引用。池中的数据项就像数组一样是通过索引访问的,因为常量池存储了相应类型所用到的所有类型、字段和方法的符号引用,所以他在java程序的动态连接性中起到核心作用。