關於java繼承在內存中的實現的解析?
關於java繼承在內存中的實現的解析
工具/原料
java語言
方法/步驟
我們都知道java語言有4個特性:繼承、封裝、多態、抽象。
但是java繼承在底層是如何實現的我們知道的甚少,我就在此解析下java語言繼承在底層是如何實現的。
先看一段代碼:
public class Person {
int id = 12; String name = "SuperMan"; static { System.out.println("Person class"); }
public Person() { System.out.println("Person's constructor method"); }
public void whoru() { System.out.println(this.name); }
public void method(){ System.out.println("hi"); } }
public class Cheater extends Person { String name = "LittleMan"; static { System.out.println("Cheater class"); }
public Cheater() { System.out.println("Cheater's constructor method"); }
public void whoru() { System.out.println(this.name); } }
public class Test { public static void main(String[] args) { Cheater c = new Cheater(); // Person class // Cheater class // Person's constructor method // Cheater's constructor method c.whoru();// LittleMan c.method();// hi System.out.println("c'id:" + c.id + ";c.name:" + c.name);// c'id:12;c.name:LittleMan } }
首先我們知道java中的繼承指的是父類與子類之間的關係,即:由於子類繼承了父類,所以子類可以使用父類所共享的屬性和方法。
在上面的代碼中,我們發現父類的屬性和方法都沒有用private來修飾,表明其屬性和方法都是共享的。
內存分析圖如下:
先解析下: c.whoru();// LittleMan 為何會打印出:LittleMan 呢? 當我們用Cheater來申明的變量c,再有變量c調用方法whoru()時,系統會去查找又Cheater.class在jvm解析過後存放在方法區的代碼域裡的Cheater這塊內存中,發現能夠在這裡找到whoru()這個方法,故不會再去其父類Person這塊內存中查找whoru()這方法了,所以會打印出 LittleMan 的。
在解析下: c.method();// hi
其原因和上面的一樣,先會去方法區的代碼域找Cheater這塊內存中是否存在method()這個方法,但是沒有找到。於是會繼續由其父類Person這塊內存中是否有method()這個方法,找到了,所以就執行method()方法打印出 hi。
這個就是子類繼承父類之後可以調用到父類共享方法的原因。
在說說子類是如何調用到了父類的屬性的吧!
先說 c.id 打印出了 12 :
變量c調用屬性id,會從其在內存的堆中自身的cheater實例中開始查找,可是沒有找到,於是會找其父類中的屬性是否有個名稱為 id 的,於是找到了父類的 id 的屬性值,所以打印出了 12 。
而 c.name 打印出 LittleMan:
是因為在查找的過程中,在找自身的cheater實例中找到了屬性名為 name 的屬性值,所以就不會繼續查找其父的屬性信息了。
這就是子類為什麼可以調用父類的共享屬性的原因了。
綜上所述:我們發現了為什麼在堆內存中生成子類的實例,為什麼會先從其“祖宗類”來開始生成的原因了,即為了實現繼承的關係,為了讓子類可以調用到父類的共享屬性和方法,所以才會在生成子類的之前要先把其“祖宗類”先生成;說得更明確些:子類之所以能使用到父類的共享的方法和屬性,不是由於子類自身會帶著“祖宗類”的共享的方法和屬性,而是在查找子類的方法屬性的時候,沒有找到其自身的方法和屬性,於是就要去其“祖宗類”中查找了,就是這個原因,使我們感覺到子類擁有了其“祖宗類”的共享的所有的方法和屬性。