1. 封裝思想
封裝是面向?qū)ο笕筇卣髦唬浜x有兩個(gè)(掌握思想):
把對象的字段和方法存放在一個(gè)獨(dú)立的模塊中(類)
信息隱藏,盡可能隱藏對象的數(shù)據(jù)和功能的實(shí)現(xiàn)細(xì)節(jié)
封裝的好處:
1语盈、保證數(shù)據(jù)的安全性砖织,防止調(diào)用者隨意修改數(shù)據(jù)
2狂鞋、提高組件的重用性躏结,把公用功能放到一個(gè)類中,誰需要該功能夸研,直接調(diào)用即可
沒有封裝帶來的困惑:
學(xué)生類:
public class Student{
String name;
int age;
void say() {
System.out.println("我是" + name + ",今年" + age + "歲");
}
}
測試類:
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
s.name = "小明";
s.age = -12;
s.say();//我是小明,今年-12歲
}
}
此時(shí)從代碼語法上來看邦蜜,是沒有任何問題的,但是從邏輯上來分析人的年齡怎么能是負(fù)數(shù)呢亥至?造成該問題的根本原因就是:可以隨意訪問對象中的字段悼沈。
那么問題來了,怎么才能限制不能隨意訪問字段數(shù)據(jù)呢姐扮?
此時(shí)絮供,就該歡迎訪問修飾符登場了!
1.1. 訪問修飾符(必須記撞杳簟)
車庫有一個(gè)車位壤靶,旁邊寫著”公共車位”,那么該車位就是公共的惊搏,誰都可以訪問它贮乳。如果我在車位旁邊寫上“私家車位”忧换,那么該車位就只能是我自己來訪問。外界(除我之外)都訪問不了向拆,像“公共”亚茬、“私有”這種限制外界訪問的標(biāo)記符號,就稱之為訪問修飾符浓恳。
訪問修飾符才写,決定了有沒有權(quán)限訪問某個(gè)資源。
封裝其實(shí)就是要讓有些類看不到另外一些類中定義的字段和方法奖蔓。Java提供了不同的訪問權(quán)限修飾符來限定類中的成員讓誰可以訪問到。
private:表示當(dāng)前類私有的讹堤,類訪問權(quán)限吆鹤,只能在本類中操作,離開本類之后就不能直接訪問
不寫(缺手奘亍):表示當(dāng)前包私有疑务,包訪問權(quán)限,定義和調(diào)用只能在同一個(gè)包中梗醇,才能訪問
protected:表示子類訪問權(quán)限知允,同包中的可以訪問,即使不同包但是有繼承關(guān)系也可以訪問
public:表示公共的叙谨,可以在當(dāng)前項(xiàng)目中任何地方訪問
private修飾符演示:
缺省和public修飾符演示:
暫時(shí)記孜赂搿:把所有的字段使用private修飾,所有方法使用public修飾手负。
1.2. 封裝使用(了解)
使用private修飾了Student類中的字段涤垫,此時(shí)在測試類中訪問報(bào)錯(cuò)。
public class Student {
private String name;
private int age;
}
測試類:
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
s.name = "小明";//此行報(bào)錯(cuò)竟终,訪問權(quán)限不足
s.age = -12;//此行報(bào)錯(cuò)蝠猬,訪問權(quán)限不足
}
}
此時(shí)使用private修飾字段后,在測試類中不能再操作這些字段了统捶,此時(shí)怎么辦榆芦?我們可以使用JavaBean的規(guī)范來解決,其實(shí)也非常簡單喘鸟。
1.2.1. JavaBean規(guī)范(重點(diǎn)掌握)
JavaBean是一種某些符合條件的特殊類匆绣,但是必須遵循一定的規(guī)范:
類必須使用public修飾
必須保證有公共無參數(shù)構(gòu)造器,即使手動(dòng)提供了帶參數(shù)的構(gòu)造器什黑,也得手動(dòng)提供無參數(shù)構(gòu)造器
字段使用private修飾犬绒,每個(gè)字段提供一對getter和setter方法
需求:針對名為name的字段名來舉例
getter方法:僅僅用于返回某一個(gè)字段的值
public String getName(){
return name; //返回name字段存儲(chǔ)的值
}
如果操作的字段是boolean類型的,此時(shí)是is方法兑凿,把 getName 變成 isName凯力。
setter方法:僅僅用來給某一個(gè)字段設(shè)置值
public void setName(String n){
name = n; //把傳過來的參數(shù)n的值,存儲(chǔ)到name字段中
}
注意:每一個(gè)字段都得使用private修飾茵瘾,并提供一對getter/setter方法。
Eclipse工具可以自動(dòng)生成標(biāo)準(zhǔn)的getter/setter咐鹤,前期必須手寫拗秘。
代碼如下:
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String n) {
name = n;
}
public int getAge() {
return age;
}
public void setAge(int a) {
if(a < 0) {
System.out.println("非法的年齡");
return;
}
age = a;
}
}
測試類:
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
// 調(diào)用setter方法設(shè)置字段數(shù)據(jù)
s.setName("小明");
s.setAge(12);
// 調(diào)用getter方法獲取字段數(shù)據(jù)
String n = s.getName();
int a = s.getAge();
System.out.println(n + "," + a);
}
}
1.2.2. this關(guān)鍵字(掌握)
之前說過,變量名稱或方法參數(shù)名稱祈惶,要見名知意雕旨,下列兩個(gè)set方法的參數(shù)名,就顯得太LOW了捧请。
public class Student {
private String name;
private int age;
public void setName(**String n**) {
name = name;
}
public void setAge(**int a**) {
age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
不就是設(shè)置名字和年齡嗎凡涩,如果此時(shí)把參數(shù)名分別改為name和age。
public class Student {
private String name;
private int age;
public void setName(String **name**) {
name = name;
}
public void setAge(int **age**) {
age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
此時(shí)會(huì)發(fā)現(xiàn)參數(shù)根本就設(shè)置不進(jìn)去疹蛉,name和age打印出來都是各自的初始值活箕,運(yùn)行測試類的結(jié)果如下:
null,0
先回憶方法的參數(shù)屬于局部變量這個(gè)結(jié)論,導(dǎo)致參數(shù)設(shè)置不進(jìn)去的原因是:
局部變量和成員變量同名可款,此時(shí)在方法中調(diào)用變量時(shí)根據(jù)就近原則育韩,優(yōu)先使用局部變量,示意圖如下闺鲸。
可以看出setName方法中兩次使用的name筋讨,都是直接尋找距離自己最近的形參name,就相當(dāng)于把參數(shù)name的值設(shè)置給參數(shù)name摸恍,根本就沒有把參數(shù)值設(shè)置給成員變量悉罕。
該問題,更專業(yè)的叫法是局部變量和成員變量存在二義性立镶,也就是變量名有歧義蛮粮。為了解決該問題——有請this關(guān)鍵字。
使用this.變量名的語法谜慌,此時(shí)訪問的就是成員變量然想,this的其他操作,后面再講欣范。
具體代碼如下:
public class Student {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
1.2.3. 使用構(gòu)造器還是setter方法(了解)
構(gòu)造器和setter方法都可以給對象設(shè)置數(shù)據(jù):
構(gòu)造器变泄,在創(chuàng)建對象的時(shí)候設(shè)置初始數(shù)據(jù),只能初始化一次恼琼。
setter方法妨蛹,創(chuàng)建對象后再設(shè)置初始數(shù)據(jù),可以設(shè)置多次晴竞。
若要獲得最好的學(xué)習(xí)效果蛙卤,需要配合對應(yīng)教學(xué)視頻一起學(xué)習(xí)。需要完整教學(xué)視頻,請參看https://ke.qq.com/course/272077颤难。