JavaSE 最easy出錯的幾個簡單的問題
案例1.
package cn.itcast.oop; public class ThisDemo { public static void main(String[] args) { Student s=new Student(); s.setName("李衛康"); s.setAge(22); String name=s.getName(); int age=s.getAge(); System.out.println("學生的姓名是:"+name+" 學生的年齡是:"+age); } } class Student{ private String name; private int age; public String getName() { return name;//這裏默認省略了this,實際上是this.name } public void setName(String name) { name = name; } public int getAge() { return age; } public void setAge(int age) { age = age; } }
這段代碼非常簡單,可是非常easy出錯!出錯的關鍵點就在於this.
執行結果:
為什麽會這樣呢?為什麽打印結果不是-->學生的姓名是:李衛康 學生的年齡是:22
案例2.
package cn.itcast.oop; public class StudentDemo { public static void main(String[] args) { Person s=new Person(); } } class Person{ private String name="林青霞"; private int age=27; public Person(){ name="劉毅"; age=30; } }
A:把Student.class文件載入到內存
B:在棧內存中給s變量開辟一個空間
C:在堆內存中為人類對象申請一個空間
D:給成員便令進行默認初始化.null 0
E:給成員變量進行顯示 初始化。林青霞,27
F:通過構造方法給成員變量進行初始化 劉毅。30
G:數據初始化完成,然後把堆內存的地址值賦值給棧內存的s變量
3.繼承概述
A:java僅僅支持類的單繼承不支持類的多繼承
B:子類僅僅能繼承父類全部非私有的成員(成員方法和成員變量)
C:子類不能繼承父類的構造方法,可是能夠通過super(立即講)keyword去訪問父類構造方法。
D:子類中的成員變量和父類中的成員變量名稱一樣,
在子類方法中訪問一個變量的查找順序:
a:在子類方法的局部範圍找,有就使用
b:在子類的成員範圍找,有就使用
c:在父類的成員範圍找,有就使用
d:假設還找不到。就報錯。
E:this代表本類相應的引用。super代表父類存儲空間的標識(能夠理解為父類引用,能夠操作父類的成員)
F:繼承中構造方法的關系
子類中全部的構造方法默認都會訪問父類中空參數的構造方法:由於子類會繼承父類中的數據,可能還會使用父類的數據。所以,子類初始化之前,一定要先完畢父類數據的初始化。
註意:子類每個構造方法的第一條語句默認都是:super();
G:假設父類沒有無參構造方法,那麽子類的構造方法會出現什麽現象呢?報錯。
怎樣解決呢?
1):在父類中加一個無參構造方法
2):通過使用superkeyword去顯示的調用父類的帶參構造方法
3):子類通過this去調用本類的其它構造方法,子類中一定要有一個去訪問了父類的構造方法,否則父類數據就沒有初始化。
註意事項:
this(...)或者super(...)必須出如今第一條語句上。
假設不是放在第一條語句上,就可能對父類的數據進行了多次初始化,所以必須放在第一條語句上。
H:繼承中成員方法的關系:1):子類中的方法和父類中的方法聲明不一樣,這個太簡單。2):子類中的方法和父類中的方法聲明一樣,這個該怎麽玩呢?
通過子類對象調用方法:
a:先找子類中。看有沒有這種方法,有就使用
b:再看父類中,有沒有這種方法。有就使用
c:假設沒有就報錯。
I:方法重寫的註意事項
1):父類中私有方法不能被重寫-->由於父類私有方法子類根本就無法繼承
2):子類重寫父類方法時。訪問權限不能更低-->最好就一致
3):父類靜態方法,子類也必須通過靜態方法進行重寫
事實上這個算不上方法重寫。可是現象確實如此,至於為什麽算不上方法重寫,多態中我會講
子類重寫父類方法的時候,最好聲明一模一樣。
例題:
class Fu { static { System.out.println("靜態代碼塊Fu"); } { System.out.println("構造代碼塊Fu"); } public Fu() { System.out.println("構造方法Fu"); } } class Zi extends Fu { static { System.out.println("靜態代碼塊Zi"); } { System.out.println("構造代碼塊Zi"); } public Zi() { System.out.println("構造方法Zi"); } } class ExtendsTest2 { public static void main(String[] args) { Zi z = new Zi(); Zi z2 = new Zi(); } }運行結果:
看程序寫結果:
A:一個類的靜態代碼塊,構造代碼塊,構造方法的運行流程
靜態代碼塊 > 構造代碼塊 > 構造方法
B:靜態的內容是隨著類的載入而載入
靜態代碼塊的內容會優先運行
C:子類初始化之前先會進行父類的初始化
結果是:
靜態代碼塊Fu
靜態代碼塊Zi
構造代碼塊Fu
構造方法Fu
構造代碼塊Zi
構造方法Zi
經典面試題:
class X { X() { System.out.print("X"); } Y b = new Y(); } class Y { Y() { System.out.print("Y"); } } public class Z extends X { Z() { //super System.out.print("Z"); } Y y = new Y(); public static void main(String[] args) { new Z(); } }記住一句話:先初始化父類數據,再初始化子類數據
因此運行流程為:依據初始化的順序:先默認初始化,顯示初始化,構造初始化
1.先初始化父類class X:運行成員變量顯示初始化Y y=new Y();因此調用Y的構造函數打印Y
2.父類的構造方法初始化,運行構造方法中的代碼打印X
3.子類進行初始化Class Z:運行成員變量初始化Y y=new Y()因此調用Y的構造方法打印Y
4.子類的構造方法初始化:運行構造方法中的代碼打印Z
結果為:YXYZ
debug模式:
案例:
package cn.itcast.extend; public class Demo { public static void main(String[] args) { Zi z=new Zi(); z.show(); } } class Fu{ int num=10; public void show(){ System.out.println(num); } } class Zi extends Fu{ int num=20; public void show(){ System.out.println(num); } }結果是毋容置疑的:20
去掉子類的show方法
package cn.itcast.extend; public class Demo { public static void main(String[] args) { Zi z=new Zi(); z.show(); } } class Fu{ int num=10; public void show(){ System.out.println(num); } } class Zi extends Fu{ int num=20; }
答案是:10
為什麽呢:由於子類中找方法show()沒有找到就去父類中找.
JavaSE 最easy出錯的幾個簡單的問題