1. 程式人生 > >JavaSE 最easy出錯的幾個簡單的問題

JavaSE 最easy出錯的幾個簡單的問題

成員 tde bsp ase log package 標識 多次 年齡

案例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;
	}
		
}
Person s=new Person();做了哪些事情

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出錯的幾個簡單的問題