目錄
1. 什么是封裝?
2. 訪問修飾符
3. 封裝的好處
4. 封裝的步驟
5. 包
5.1 什么是包
5.2 導入包中的類
5.3 自定義包
5.4 常用的包
6. static關鍵字
6.1 static修飾成員變量
6.2 static修飾成員方法
6.3 Static修飾成員變量初始化
7. 代碼塊
7.1 普通代碼塊
7.2 構造代碼塊
7.3 靜態代碼塊
7.4 各種初始化
8. 對象的打印
1. 什么是封裝?
封裝就是對類里面的成員變量和成員方法進行隱藏,只能在所在類的范圍內使用,只留下一些可以被外部訪問的方法,供外部調用,隱藏方法實現的內部細節。
這就好比一臺電視機,給你提供了一個遙控器供你使用,進行一系列操作,但是操作的內部細節你看不到,只是通過遙控器來實現功能。
2. 訪問修飾符
Java當中是通過類和訪問權限來實現封裝的,類可以實現數據和封裝的數據存儲在一起,而訪問修飾符則可以設置數據的訪問權限。
訪問限定符有四個:private , default , protected , public 。它們的訪問權限也是不一樣的。如圖所示:
private修飾的屬性和方法只能在類內部使用,不能在類外部直接使用。
3. 封裝的好處
1.可以隱藏類內部的實現細節。
2.可以保證安全和合理,比如說要對屬性設置值,可以在封裝的類里面先判斷設置的值是否合理,再考慮是否賦值。
4. 封裝的步驟
1.對屬性和方法進行私有化(只能在類里面使用,不能直接修改值)
2. 設置public的set方法實現對私有的屬性的判斷和賦值。
3. 設置public的get方法對權限進行判斷,進而得到私有屬性的值。
舉個Student類的例子:
class Student{private String name;private int age;private String stuNum;public void setName(String name) {this.name = name;}public String getName() {return name;}
}public class Test {public static void main(String[] args) {Student student = new Student();student.setName("張三");System.out.println(student.getName());}
}
上面就是設置的兩個公共方法一個設置成員變量的值,一個返回成員變量的值。
但是每個成員變量都要寫過于麻煩,因此idea提供一種快捷方法,可以直接生成這兩個方法:
1.鼠標在類內部右擊找到下面的選項:
2. 找到下面選項:?
3. 把需要生成的成員變量選上,ok。?
?這樣就實現了間接訪問成員變量。
但是為什么把屬性設置成了私有還可以被外部間接訪問呢?
????????因為,封裝的屬性和方法是為類內部的其他方法提供的,而設置的一些公共類的方法就可以被外部所訪問,而這個方法有可以使用封裝的屬性和方法,這樣既隱藏了封裝的方法的內部細節,又可以通過公共方法給外部間接使用。
5. 包
5.1 什么是包
????????包本質上是對類的一種管理形式,包里面包含了很多的類,也就相當于包是一個文件夾,里面存放了很多的.Java文件,一個.Java文件對應一個類。
5.2 導入包中的類
這里我們可以用到import關鍵字進行導入包,也成為打包。例如:
import java.util.Arrays;
java.util就是包的名字,而Arrays就是類名。
當然我們也可以不導入包直接在代碼中使用,如下:
int[] a = new int[]{6,4,2,1};java.util.Arrays.sort(a);System.out.println(java.util.Arrays.toString(a));
但是這樣書寫太麻煩了,但是當兩個包里面有相同名字的類都被使用的時候就需要這樣去寫。
當然還有一種寫法是: *叫做通配符
import java.util.*;
不同的包里面可以有相同的類名,這兩個類只是名字相同,但是作用不相同。?
????????這種方法可以導入包里面的全部類,但是不建議這樣書寫。因為有可能在兩個包里面會有相同名字的類,這樣書寫就會導致沖突,編譯器會報錯。
在java.util包里面有一個Date的類,在java.sql包里面也有一個Date的類,如果書寫成如下格式就會報錯:
因為這樣的話,在代碼中使用時,編譯器無法識別是哪一個包下面的類,所以遇到這種情況,只能用import導入一個類,另一個類則需要在使用的時候進行導入。如圖:
import java.util.Date;Date date = new Date();
java.sql.Date date1 = new java.sql.Date(10);
5.3 自定義包
創建一個包:
包的命必須是字母,數字,點號,下劃線,數字不能開頭,不能包含關鍵字。
一般公司命名是以 com.公司名.項目名.模塊名 來命名的。
回車后就創建好了一個包:
?com是一級目錄,abc是二級目錄,www是三級目錄。Test1是類。
Test1類里面代碼如下:
package com.abc.www;public class Test1 {public void test1() {System.out.println("haha");}
}
package是編譯器自己生成的,為了聲明該類在那個包里面。
下面我自己編寫了一段代碼。
如果要在其他類中調用自定義包里面的方法,就是如下圖:
import com.abc.www.Test1;public class Test {public static void main(String[] args) {Test1 test1 = new Test1();test1.test1();}
}
這樣就可以調用了,com.abc.www是包名,Test1是類名,test1是類里面的方法。
5.4 常用的包
java.lang? ? lang是基本包,默認引入的,不需要再導入。
java.util? ? ? 系統提供的工具包,包含工具類。
java.net? ? ? 網絡開發用的。
java.awt? ?做Java的頁面開發的。
6. static關鍵字
static是用來修飾成員的,被static修飾的成員叫做靜態成員,也叫做類成員,表示該成員不屬于任何一個對象的,而是所有對象共同包含成員。我用下面的代碼幫助大家理解:
class Student{public String name;public int age;public String stuNum;public static String classNum;public Student(String name, int age, String stuNum) {this.name = name;this.age = age;this.stuNum = stuNum;}
}
public class Test {public static void main(String[] args) {Student student1 = new Student("張三",18,"202311");Student student2 = new Student("李四",19,"202312");}
}
此時學生1和學生2這兩個對象都在同一個班級,那么班級屬性是兩個對象都一樣的,就可以被static修飾。
6.1 static修飾成員變量
當static修飾完成員變量后,該成員變量就屬于類的變量,而不是方法的變量,此時該靜態變量就不會在根據類的定義在堆區申請的對象的內存空間中了,而是在方法區中了。如下圖所示關系:
此時我們如何訪問靜態變量呢?
有兩種方式:
Student student1 = new Student("張三",18,"202311");
//通過對象的引用來訪問
student1.classNum = "1班";
//通過類名訪問
Student.classNum = "1班";
第一種是通過對象的引用來訪問,但是不建議使用,因為靜態變量不在對象申請的內存中,在方法區中,屬于類的變量。
第二種是通過類名來訪問。
注意:
- 靜態變量的訪問不依賴于對象,不需要實例化對象,就可以直接訪問。
- 類變量存儲在方法區中。
- 類變量的生命周期是整個類的生命周期。
- 靜態變量是所有對象共享的,不存在于某個對象的空間里。
6.2 static修飾成員方法
static修飾成員方法后,成員方法變成靜態成員方法,靜態成員變量的訪問不依賴于對象,屬于類方法,存在于方法區,有兩種訪問方式:
class Student {public String name = "張三";public int age = 18;public String sex = "男";public static void print() {System.out.println("hehe");}
}
public class Test1 {public static void main(String[] args) {//方法一Student student = new Student();student.print();//方法二Student.print();}
}
方法一:是通過對象來訪問,這種方法雖然不會報錯,但是不建議使用,因為靜態方法屬于類方法,不依賴于對象。
方法二:直接通過類名訪問,這種方法建議使用。
注意:
- 靜態方法里面不能使用this關鍵字,因為this關鍵字依賴于對象,而靜態方法的訪問不依賴于對象。
- 靜態方法不能直接訪問非靜態方法和非靜態變量,但可以通過對象的實例化間接訪問。
- 非靜態方法可以直接訪問靜態方法和靜態變量,非靜態方法依賴于對象,靜態方法和靜態變量不依賴于對象。
- 不同類間訪問靜態方法或靜態變量,通過類名.方法名或變量名訪問。
- 不同類間訪問非靜態方法或非靜態變量,對象實例化后,通過對象來訪問。
- static不能修飾局部變量。
6.3 Static修飾成員變量初始化
靜態成員方法初始化方法有四種:
- 通過就地初始化,也就是直接初始化值。
- 通過set方法初始化。
- 通過構造方法初始化。
- 通過靜態代碼塊初始化
7. 代碼塊
代碼塊是指被{}包含的內容,一般情況下是用來對成員變量進行初始化的。分為三種:
7.1 普通代碼塊
這是定義在方法內的代碼塊:
public static void main(String[] args) {//普通代碼塊{int a = 10;System.out.println(a);}}
7.2 構造代碼塊
定義在類里面的代碼塊,也叫做實例代碼塊。用來初始化非靜態成員變量的,在實例化對象的時候執行:
class Student {public String name = "張三";public int age = 18;public static String sex = "男";//實例代碼塊{name = "李四";age = 20;}
}
7.3 靜態代碼塊
定義在類里面的代碼塊,用來初始化靜態成員變量的,在類加載的時候執行:
class Student {public String name = "張三";public int age = 18;public static String sex = "男";//靜態代碼塊{sex = "女";}
}
靜態代碼塊只能初始化靜態成員變量。因為非靜態對象初始化依賴于對象。?
7.4 各種初始化
我們已經知道了 用構造方法來初始化成員變量,還有就地初始化成員變量,還有代碼塊初始化成員變量,代碼塊又分為靜態代碼塊和實例代碼塊。
那它們的執行先后順序又是怎樣的呢?
多個靜態代碼塊或者多個實例代碼塊同時初始化,則是按照代碼的先后順序初始化。
靜態代碼塊是在類加載時執行的,而構造方法和實例初始化則是在實例化對象時執行的,所以靜態代碼塊先執行,如果有靜態變量就地初始化,會按照先后順序進行執行,而實例初始化比構造方法先執行。
一般成員變量的定義和初始化先寫,在寫其他的代碼塊或者方法。
執行順序為:就地初始化->靜態代碼塊->實例代碼塊->構造方法。
????????如果實例化多個對象時,由于類只會在第一次實例化對象時加載一次,也就是說靜態代碼塊只執行一次,第二次實例化對象時,不執行靜態代碼塊,只執行實例代碼塊和構造方法。
8. 對象的打印
如果想打印對象的屬性也就是成員變量有什么快捷方式嗎?
這里idea提供了一種快捷方式,生成toString方法來進行打印:
class Student {public String name = "張三";public int age = 18;public String sex = "男";//打印成員變量的方法:@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +'}';}
}public class Test1 {public static void main(String[] args) {Student student = new Student();System.out.println(student);}
}
打印結果如下:
這樣就可以實現快速打印對象的屬性。
如果不寫toString方法,默認打印的是地址。當然這種快捷方式不能生成靜態成員變量。?