Java 基础— 引用变量编译时类型和运行时类型的区别 及属性和静态非静态方法调用规则
程序员文章站
2024-03-23 14:24:04
...
前言:
编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定
。如果编译时类型和运行时类型不一致,会出现所谓的多态。因为子类其实是一种特殊的父类,因此java允许把一个子类对象直接赋值给一个父类引用变量,无须任何类型转换,或者被称为向上转型,由系统自动完成。引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法
,因此,编写Java代码时,引用变量只能调用声明该变量所用类里包含的方法(方法表)。与方法不同的是,对象的属性则不具备多态性
。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性。
--------引自《疯狂Java讲义》
1. 成员变量 & 静态成员函数:
- 编译时,参考引用型变量所属的类中是否有调用的成员变量/静态函数,有,编译通过,无,编译失败
- 运行时,参考引用型变量所属的类中是否有调用的成员变量/静态函数,并运行
- 简而言之,编译运行都参考等号
左边
引用型变量所属的类
2. 非静态成员函数:
- 编译时,参考引用型变量所属的类中是否有调用的非静态成员函数,有,编译通过,无,编译失败
- 运行时,参考的是对象所属的类中是否有调用的函数
- 简而言之,编译 – 左边 – 引用型变量所属类型,运行 – 右边 – 对象所属类型
示例说明
`Demo.java`
// 父类
class Fu{
int num = 3;
public void show(){
System.out.println("Fu show");
}
public static void method(){
System.out.println("Fu method");
}
public void getNum(){
System.out.println(this.num);
}
}
// 子类
class Zi extends Fu{
int num = 1;
public void show(){
System.out.println("Zi show");
}
public static void method(){
System.out.println("Zi method");
}
}
// 主程序所在的类
class Demo{
public static void main(String[] args){
Fu f = new Zi();
System.out.println(f.num); // 3 (父类中的num值)
f.show(); // Zi show (非静态 -- 子)
f.method(); // Fu method (静态 -- 父)
f.getNum(); // 3 (父类中的num值)
}
}
// 1.变量:
Fu f = new Zi(); // 参考父类
// 对象所调用的变量,父类若没有,即使子类有,编译失败;父类中有,即使子类有同名同类型变量(面试会出现,实际不应该有,继承父类即可),运行父类
Zi z = new Zi(); // 参考子类
// 对象所调用的变量,子类若没有,转向父类中寻找;子类中有,运行子类
// 2.静态成员函数:
f.mehtod(); // 实际调用静态方法,类名调用即可
// 静态方法无需创建对象便可使用 (多态是对对象,所以静态方法无多态可言?)
Fu.method();
// 所调用的静态方法,父类中若没有,即使子类有同声明函数,编译失败;父类中有,即使子类有同声明函数,运行父类
Zi.method();
// 所调用的静态方法,子类中若没有,转向父类中寻找;子类中有,运行子类
// 3.非静态成员函数
f.show();
// 所调用的非静态方法,父类中若没有,即使子类有,编译失败;子父类都有,运行子类
z.show();
// 所调用的非静态方法,子类中若没有,转向父类中查找;子类中有,运行子类
- 非静态方法必须由对象来完成调用,对象属于子类;
- 静态方法无需创建对象,对应类名调用
-
Fu f = new Zi();
引用型变量f
属于父类,指向子类对象 (父类引用指向子类对象)
注意
:
- 如您发现本文档中有错误的地方,
- 或者您发现本文档中引用了他人的资料而未进行说明时,请联系我进行更正。
- 转载或使用本文档时,请作说明。
- 非常感谢
:)