Java 编译看左边 运行看右边的理解
在理解Java动态的时候,有这么一句话 :编译看左边 , 运行看右边;那么又如何来理解呢?
首先,先简单的了解java 中的多态是什么,简单来说,java动态可以粗略的理解为 父类的引用指向子类的对象,这里以Java 中的继承来进行举例。
public class Test{
public static void main(String[] args) {
Person person = new Student(); // 这就是多态的体现
}
}
// 父类
class Person{
}
// 继承 Person 的子类
class Student extends Person{
}
那么如何理解编译看左边 ,运行看右边呢,先看下面的这个例子
public class Test{
public static void main(String[] args) {
Person person = new Student(); // 这就是多态的体现
int age = person.age; // 48
String name = person.name; // Person
Student student = new Student();
int age = person.age; // 48
String name = person.name; // Person
}
}
// 父类
class Person{
int age = 48;
String name = "Person";
}
// 继承 Person 的子类
class Student extends Person{
}
此时会发现 两个 子类中虽然没人了 age 和name 两个属性,但是子类 居然能拿到这两个属性 ,并且还有值,其实这是因为子类继承了父类,难道继承就能拿到父类的东西了吗,java中的继续 大家都知道 子类继承父类,-就能继承父类的成员属性和方法。这里你暂且可以这样理解;继续看下面的例子
public class Test{
public static void main(String[] args) {
Person person = new Student(); // 这就是多态的体现
int age = person.age; // 48
String name = person.name; // Person
Student student = new Student();
int age = person.age; // 18
String name = person.name; // student
}
}
// 父类
class Person{
int age = 48;
String name = "Person";
}
// 继承 Person 的子类
class Student extends Person{
int age = 18;
String name = "student";
}
发现 结果有不一样了。子类获取的是子类的,父类获取的是父类的。父类的应用不是指向子类的对象吗,不是说编译看左边,运行看左边吗? 为什么 父类获取的又是父类的不是子类的呢,继续看下面例子
public class Test{
public static void main(String[] args) {
Person person = new Student(); // 这就是多态的体现
int age = person.age; // 48
String name = person.name; // Person
perosn.meth01(); // student....meth01
perosn.meth02(); // Person.....meth02
perosn.meth03(); // 报错
perosn.meth04(); // 报错
}
}
// 父类
class Person{
int age = 48;
String name = "Person";
public void meth01(){
System.out.println("Person....meth01");
}
public static void meth02(){
System.out.println("Person.....meth02");
}
}
// 继承 Person 的子类
class Student extends Person{
int age = 18;
String name = "student";
public void meth01(){
System.out.println("student....meth01");
}
public static void meth02(){
System.out.println("student....meth02");
}
public void meth03(){
System.out.println("meth03");
}
}
public static void meth04(){
System.out.println("meth04");
}
}
运行发现 person对象调用meth01() 时 输出子子类的内容,调用meth02() 时 输出父类的内容,调用meth03()时 报错, 也许有人会想到 子类继承父类 重写了父类的方法,所以父类的meth01() 被覆盖了。确实如此,如果子类继承父类 ,那么子类就会继承父类的属性和方法。但是,请记住,子类并不是会继承父类的所有方法和属性,子类只会继续父类的非私有的属性和实例方法,当然,如果父类的属性时私有的,那么除了父类本身以外的类都无发去访问 父类私有的的,哪怕是 父类的实例也不行(当然反射除外),只有父类中的类才能够访问(俗称的内部类),当然你有可能说不是有公共的getter和setter f方法吗,如果提供了公共的getter和setter方法,那么,还与子类有啥关系,不是其子类也可以访问…;
结束,回到 主题,如何理解 多态中的编译看左边运行看右边呢?
首先,子类继承父类,父类中非私有的属性会被子类所继承,但是 子类不会覆盖父类的属性,如果子类没有将父类的属性所覆盖,那么子类会使用父类的属性,如果覆盖了父类的属性,那么就不会使用父类的属性,此时父类的引用获取的依然是父类的属性,子类的也依然是子类的。
其次,父类的中的实例方法也会被子类所继承,如果子类重写了父类的实例方法,那么父类的的实例方法会被子覆盖,此时,父类的引用去调用父类的实例方法,实际运行的是子类重写的实例方法,但是,父类拿不到子类的特有的方法,不管是实例方法,实时静态方法。
再其次,父类的静态方法,子类是无法继承的,因为 父类的静态方法会在子类加载之前 已经加载到内存中
最后,总结。子类继承父类,只会继承父类的非使用的属性和实例方法,
在最后 结合图看看吧