24_封裝

第二十四章 封裝

作者:張子默

一、封裝概述

1、概述

面向對象編程語言是對客觀世界的模擬,客觀世界裏成員變量都是隱藏在對象內部的,外界無法直接操作和修改。封裝可以被認爲是一個屏障,防止該類的代碼和數據被其他類隨意訪問。要訪問該類的數據,必須通過指定的方式。適當的封裝可以讓代碼更容易理解與維護,也加強了代碼的安全性。

2、原則

屬性隱藏起來,若需要訪問某個屬性,提供公共方法對其訪問。

3、實例

/*
面向對象三大特徵:封裝、繼承、多態

封裝在Java當中的表現
	1、方法就是一種封裝
	2、關鍵字private也是一種封裝
	
封裝就是將一些細節信息隱藏起來,對於外界不可見
*/
public class Demo01Methed {
	public static void main(String[] args) {
		int[] array = {5, 15, 25, 20 ,100};
		
		int result = getMax(array);
		System.out.println("最大值:" + result);
	}
	
	//給我一個數組,我還給你一個最大值
	public static int getMax(int[] array) {
		int max = array[0];
		for(int i=1; i<array.length; i++) {
			if(array[i]>max) {
				max = array[i];
			}
		}
		
		return max;
	}

}

二、封裝的步驟

  • 使用private關鍵字來修飾成員變量。

  • 對需要訪問的成員變量,提供對應的一對getXxx方法、SetXxx方法。

1、實例

/*
問題描述:定義Person的年齡時,無法阻止不合理的數值被設置進來。

解決方案:用private關鍵字將需要保護的成員變量進行修飾。

一旦使用了private進行修飾,那麼本類當中仍然可以隨意。但是!超出了本類範圍之外就不能再直接訪問了。

間接訪問private成員變量,就是定義一對兒Getter/Setter方法

命名規則:必須叫setXXX或者是getXxx

對於Getter來說,不能有參數,返回值類型和成員變量對應
對於Setter來說,不能有返回值,參數類型和成員變量對應
*/
public class Person {
	
	String name; //姓名
	private int age; //年齡
	
	public void show() {
		System.out.println("我叫:" + name + ",年齡:" + age);
	}
	
	//這個成員方法,專門用於向age設置數據
	public void setAge(int num) {
		if(num<100 && num>=9) {
			age = num;
		}else {
			System.out.println("數據不合理!");
		}
	}
	
	//這個成員方法,專門獲取age數據
	public int getAge() {
		return age;
	}

}

public class Demo02Person {
	
	public static void main(String[] args) {
		Person person = new Person();
		person.show();
		
		person.name = "趙麗穎";
		//person.age = 18; //直接訪問private內容,錯誤寫法!
		person.setAge(-20);
		person.show();
	}

}

三、封裝的操作——private關鍵字

1、private的含義

  • private是一個權限修飾符,代表最小權限。

  • 可以修飾成員變量和成員方法。

  • 被private修飾後的成員變量和成員方法,只能在本類中才能訪問。

2、private的使用格式

private 數據類型 變量名;
  • 使用private修飾成員變量,代碼如下:

    public class Student {
    		private String name;
    		private int age;
    }
    
    
  • 提供getXxx方法/setXxx方法,可以訪問成員變量,代碼如下:

    public class Student {
    			private String name;
    			private int age;
    			public void setName(String n) {
    				name = n;
    			}
    			public String getName() {
    				return name;
    			}
    			public void setAge(int a) {
    				age = a;
    			}
    			public int getAge() {
    				return age;
    			}
    		}
    

3、實例

/*
對於基本類型當中的boolean值,Getter方法一定要寫成isXxx的形式,而setXxx規則不變。
*/
public class Student {
	
	private String name; //姓名
	private int age; //年齡
	private boolean male; //是不是爺們兒
	
	public void setMale(boolean b) {
		male = b;
	}
	
	public boolean isMale() {
		return male;
	}
	
	public void setName(String str) {
		name = str;
	}
	
	public String getName() {
		return name;
	}
	
	public void setAge(int num) {
		age = num;
	}
	
	public int getAge() {
		return age;
	}

}

public class Demo03Student {
	
	public static void main(String[] args) {
		Student stu = new Student();
		
		stu.setName("鹿晗");
		stu.setAge(20);
		stu.setMale(true);
		
		System.out.println("姓名:" + stu.getName());
		System.out.println("年齡:" + stu.getAge());
		System.out.println("是不是爺們兒:" + stu.isMale());
	}

}

四、封裝優化——this關鍵字

我們發現setXxx方法中的形參名字並不符合見名知意的規定,那麼如果修改與成員變量名一致,是否就見名知意了呢?代碼如下:

public class Student {
	private String name;
	private int age;
	public void setName(String name) {
		name = name;
	}
	public void setAge(int age) {
		age = age;
	}
}

經過修改和測試,我們發現了新的問題,成員變量賦值失敗了。也就是說,在修改了setXxx()的形參變量名後,方法並沒有給成員變量賦值!這是由於形參名與成員變量名重名,導致成員變量名被隱藏,方法無法訪問到成員變量從而賦值失敗。所以,我們只能使用this關鍵字來解決這個重名問題。

1、this的含義

this代表所在類的當前對象的引用(地址值),即對象自己的引用。

記住:方法被那個對象調用,方法中的this就代表那個對象。即誰在調用,this就代表誰。

2、this使用格式

this.成員變量名;
  • 使用this修飾方法中的變量,解決成員變量被隱藏的問題,代碼如下:

    public class Student {
    	private String name;
    	private int age;
    	public void setName(String name) {
    		//name = name;
    		this.name = name;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setAge(int age) {
    		//age = age;
    		this.age = age;
    	}
    	public int getAge() {
    		return age;
    	}
    }
    

小貼士:方法中只有一個變量名時,默認也是使用this修飾,可以省略不寫。

3、實例

/*
當方法的局部變量和類的成員變量重名的時候,根據"就近原則"優先使用局部變量。

如果需要訪問本類中的成員變量,需要使用格式:this.變量名

"通過誰調用的方法,誰就是this"
*/
public class Person1 {
	
	String name; //我自己的名字
	
	//參數who是對方的名字
	//成員變量name是自己的名字
	public void sayHello(String name) {
		System.out.println(name + "你好!我是" + this.name);
		System.out.println(this);
	}

}

public class Demo04Person1 {
	
	public static void main(String[] args) {
		Person1 person = new Person1();
		//設置我自己的名字
		person.name = "王健林";
		person.sayHello("王思聰");
		System.out.println(person); //地址值
	}

}

五、封裝優化——構造方法

當一個對象被創建的時候,構造方法用來初始化該對象,給對象的成員變量賦初始值。

小貼士:無論是否自定義構造方法,所有的類都有構造方法,因爲Java自動提供了一個無參數構造方法,一旦自己定義了構造方法,Java自動提供的默認無參數構造方法就會失效。

1、構造方法的定義格式

修飾符 構造方法名(參數列表) {
	//方法體
}

構造方法的寫法上,方法名與它所在的類名相同。它沒有返回值,所以不需要返回值類型,甚至不需要void。使用構造方法後,代碼如下:

public class Student {
	private String name;
	private int age;
	// 無參數構造方法
	public Student() {}
	// 有參數構造方法
	public Student(String name,int age) {
		this.name = name;
		this.age = age;
	}
}

2、注意事項

  • 如果你不提供構造方法,系統會給出無參數構造方法。

  • 如果你提供了構造方法,系統將不再提供無參數的構造方法。

  • 構造方法是可以重載的,既可以定義參數,也可以不定義參數。

3、實例

/*
構造方法是專門用來創建對象的方法,當我們通過關鍵字new來創建對象時,其實就是在調用構造方法。

格式:
	public 類名稱(參數類型 參數名稱) {
		方法體
	}
	
注意事項:
	1、構造方法的名稱必須和所在的類名稱完全一樣,就連大小寫也要一樣
	2、構造方法不要寫返回值類型,連void都不寫
	3、構造方法不能return一個具體的返回值
	4、如果沒有編寫任何構造方法,那麼編譯器將會默認贈送一個構造方法,沒有參數、方法體什麼事情都不做。
		public Student1() {}
	5、一旦編寫了至少一個構造方法,那麼編譯器將不再贈送。
	6、構造方法也是可以重載的
	
重載:方法名稱相同,參數列表不同
*/
public class Student1 {
	
	//成員變量
	private String name;
	private int age;

	//無參數的構造方法
	public Student1() {
		System.out.println("無參構造方法執行啦!");
	}
	
	//全參數的構造方法
	public Student1(String name, int age) {
		this.name = name;
		this.age = age;
		System.out.println("全參構造方法執行啦!");
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public int getAge() {
		return age;
	}

}

public class Demo05Student1 {
	
	public static void main(String[] args) {
		Student1 stu = new Student1(); //無參構造
		System.out.println("==============");
		
		Student1 stu1 = new Student1("趙麗穎", 20); //全參構造
		System.out.println("姓名:" + stu1.getName() + ",年齡:" + stu1.getAge());
		//如果需要改變對象當中的成員變量數據內容,仍然還需要使用setXxx方法
		stu1.setAge(21); //改變年齡
		System.out.println("姓名:" + stu1.getName() + ",年齡:" + stu1.getAge());
		
	}

}

六、標準代碼——JavaBean

JavaBean是Java語言編寫類的一種規範。符合JavaBean的類,要求類必須是具體的和公共的,並且具有無參數的構造方法,提供用來操作成員變量的setget方法。

public class ClassName{
	//成員變量
	//構造方法
	//無參構造方法【必須】
	//有參構造方法【建議】
	//成員方法
	//getXxx()
	//setXxx()
}

編寫符合JavaBean規範的類,以學生類爲例,標準代碼如下:

public class Student {
	//成員變量
	private String name;
	private int age;
	//構造方法
	public Student() {}
	public Student(String name,int age) {
		this.name = name;
		this.age = age;
	}
	//成員方法
	publicvoid setName(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	publicvoid setAge(int age) {
		this.age = age;
	}
	publicint getAge() {
		return age;
	}
}

測試類,代碼如下:

public class TestStudent {
	public static void main(String[] args) {
		//無參構造使用
		Student s= new Student();
		s.setName("柳巖");
		s.setAge(18);
		System.out.println(s.getName()+"‐‐‐"+s.getAge());
		//帶參構造使用
		Student s2= new Student("趙麗穎",18);
		System.out.println(s2.getName()+"‐‐‐"+s2.getAge());
	}
}

1、實例

/*
一個標準的類通常要擁有下面四個組成部分:
	1、所有的成員變量都要使用private關鍵字修飾
	2、爲每一個成員變量編寫一對兒Getter/Setter方法
	3、編寫一個無參數的構造方法
	4、編寫一個全參數的構造方法
	
這樣標準的類也叫作Java Bean
*/
public class Student2 {
	
	private String name; //姓名
	private int age; //年齡
	
	public Student2() {
		
	}
	
	public Student2(String name, int age) {
		this.name = name;
		this.age = age;
	}



	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		this.age = age;
	}

}

public class Demo06Student2 {
	
	public static void main(String[] args) {
		Student2 stu = new Student2();
		stu.setName("迪麗熱巴");
		stu.setAge(20);
		System.out.println("姓名:" + stu.getName() + ",年齡:" + stu.getAge());
		System.out.println("===================");
		
		Student2 stu1 = new Student2("古力娜扎", 21);
		System.out.println("姓名:" + stu1.getName() + ",年齡:" + stu1.getAge());
		stu1.setAge(22);
		System.out.println("姓名:" + stu1.getName() + ",年齡:" + stu1.getAge());
	}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章