網(wǎng)站建設(shè)歸工商局管還是工信局管查關(guān)鍵詞排名軟件
【Java】對象與類
文章目錄
- 【Java】對象與類
- 1、學(xué)習(xí)背景
- 2、定義&使用
- 2.1 創(chuàng)建類
- 2.2 創(chuàng)建對象
- 3、static關(guān)鍵字
- 3.1 修飾變量
- 3.2 修飾方法
- 3.3 修飾代碼塊
- 3.4 修飾內(nèi)部類
- 4、this關(guān)鍵字
- 5、封裝特性
- 5.1 訪問修飾符
- 5.2 包的概念
- 6、構(gòu)造方法
- 7、代碼塊
- 7.1 普通代碼塊
- 7.2 成員代碼塊
- 7.3 靜態(tài)代碼塊
- 7.4 同步代碼塊
1、學(xué)習(xí)背景
在學(xué)習(xí)C++后繼續(xù)學(xué)習(xí)Java,Java給我的第一感覺和C++很像,它們都是面對對象編程(OOP)語言,在很多知識上都有相似之處,這也給學(xué)習(xí)帶來了方便
就從類與對象入手,先分析Java與C++在這上邊的區(qū)別
-
語法差異:
- 類定義: 在C++中,類的定義可以分為頭文件(.h)和實現(xiàn)文件(.cpp)。在Java中,一個類通常定義在一個獨立的源文件中。
- 構(gòu)造函數(shù): 在C++中,構(gòu)造函數(shù)和析構(gòu)函數(shù)的命名與類名相同,沒有返回類型。在Java中,構(gòu)造函數(shù)的命名與類名相同,但沒有析構(gòu)函數(shù)的概念。
- 繼承: 在C++中,使用
public
、protected
和private
關(guān)鍵字來控制繼承中的成員訪問權(quán)限。在Java中,使用public
、protected
、private
和默認(rèn)(包內(nèi)可見)四種訪問修飾符。
-
內(nèi)存管理:
- 內(nèi)存分配: C++中使用
new
和delete
來手動管理對象的內(nèi)存分配和釋放。Java中的對象內(nèi)存管理由垃圾回收器自動處理。 - 析構(gòu)函數(shù)和垃圾回收: C++的析構(gòu)函數(shù)用于對象被銷毀時執(zhí)行清理操作。Java中沒有析構(gòu)函數(shù),垃圾回收器負(fù)責(zé)釋放不再使用的對象。
- 內(nèi)存分配: C++中使用
-
引用類型:
- 在C++中,可以使用引用類型來創(chuàng)建別名,但在Java中,沒有直接的引用類型,只有對象引用。
-
繼承與多態(tài):
- C++中支持多重繼承,一個類可以從多個父類派生。Java中只支持單一繼承,但可以通過接口實現(xiàn)類似多重繼承的效果。
- C++中使用虛函數(shù)和關(guān)鍵字
virtual
來實現(xiàn)運行時多態(tài)性。Java中所有非靜態(tài)方法默認(rèn)都是虛方法,可以被子類重寫。
-
訪問控制:
- C++中通過
public
、protected
和private
來控制類成員的訪問權(quán)限。Java也使用類似的修飾符,包括public
、protected
、private
和默認(rèn)(包內(nèi)可見)。
- C++中通過
盡管存在一些差異,但類與對象的概念在C++和Java中基本上是類似的。這兩種語言都支持封裝、繼承、多態(tài)等面向?qū)ο蟮幕靖拍?#xff0c;但具體實現(xiàn)和一些細(xì)節(jié)方面會有一些差異。
2、定義&使用
2.1 創(chuàng)建類
在Java中,創(chuàng)建一個類需要使用特定的語法結(jié)構(gòu)。下面是創(chuàng)建類的基本語法:
// 類的定義
public class ClassName {// 成員變量(屬性)dataType variableName1;dataType variableName2;// ...// 構(gòu)造方法public ClassName() {// 構(gòu)造方法的代碼}// 成員方法(函數(shù))returnType methodName1(parameterType parameterName1, parameterType parameterName2, ...) {// 方法的代碼}returnType methodName2(parameterType parameterName1, parameterType parameterName2, ...) {// 方法的代碼}// ...
}
在上面的代碼中,需要做以下幾件事情:
-
類名(ClassName): 用于標(biāo)識類的名稱,通常采用駝峰命名法(首字母小寫)。
-
成員變量(屬性): 在類中定義成員變量,用于存儲對象的數(shù)據(jù)。需要指定數(shù)據(jù)類型和變量名。
-
構(gòu)造方法: 構(gòu)造方法用于創(chuàng)建對象時初始化成員變量,沒有返回類型,并且與類名相同。可以有多個構(gòu)造方法,以支持不同的初始化方式。
-
成員方法(函數(shù)): 在類中定義成員方法,用于執(zhí)行各種操作。需要指定返回類型、方法名、參數(shù)列表和方法體。
請注意以下幾點:
- 成員變量和方法可以有不同的訪問修飾符,如
public
、private
、protected
或默認(rèn)(包內(nèi)可見)。 - 構(gòu)造方法在創(chuàng)建對象時被調(diào)用,用于初始化對象的屬性。
- 成員方法可以執(zhí)行各種操作,使用返回類型指定方法的返回值類型。
以下是一個簡單的例子:
public class Person {// 成員變量private String name;private int age;// 構(gòu)造方法public Person(String n, int a) {name = n;age = a;}// 成員方法public void introduce() {System.out.println("My name is " + name + " and I am " + age + " years old.");}// 主方法(用于測試)public static void main(String[] args) {Person person1 = new Person("Alice", 25);person1.introduce();Person person2 = new Person("Bob", 30);person2.introduce();}
}
在這個例子中,Person
類有兩個成員變量 name
和 age
,一個構(gòu)造方法用于初始化這些變量,以及一個 introduce
方法用于介紹人物信息。在 main
方法中,我們創(chuàng)建了兩個 Person
對象并調(diào)用了他們的 introduce
方法。
2.2 創(chuàng)建對象
創(chuàng)建了一個類并定義了其屬性和方法后,可以使用 new
關(guān)鍵字來實例化(創(chuàng)建)該類的對象。
在上面的例子中,我們已經(jīng)創(chuàng)建了 Person
類,現(xiàn)在讓我們繼續(xù)使用該類來創(chuàng)建對象并調(diào)用方法。
public class Person
{// ...(之前的類定義)// 主方法(用于測試)public static void main(String[] args){Person person1 = new Person("alice",25);Person person2 = new Person("dick",13);person1.introduce();person2.introduce();}
}
在上面的代碼中,我們在 main
方法中創(chuàng)建了兩個 Person
對象 person1
和 person2
。然后,我們分別調(diào)用了這兩個對象的 introduce
方法,以顯示它們的信息。
這就是在Java中創(chuàng)建對象的基本過程。通過實例化類,可以創(chuàng)建具有類定義屬性和方法的實際對象,并通過調(diào)用對象的方法來執(zhí)行特定的操作。在實際開發(fā)中,類和對象的概念是面向?qū)ο缶幊讨蟹浅V匾幕A(chǔ)。
與C++不同點出現(xiàn)了,Java多數(shù)情況下將main
方法放在類中
main
方法在Java中的特殊作用是作為程序的入口點。當(dāng)運行一個Java程序時,JVM會從main
方法開始執(zhí)行。這種設(shè)計方式使得執(zhí)行流程具有明確的起點,確保了程序的可預(yù)測性和可控性。將
main
方法放在類內(nèi)部有幾個重要的原因:
統(tǒng)一入口: 將
main
方法置于類內(nèi)部使得每個Java類都可以作為一個獨立的程序執(zhí)行。這樣,你可以在一個項目中創(chuàng)建多個獨立的Java程序,每個程序都有自己的入口點。訪問權(quán)限: Java中的訪問修飾符(如
public
、private
等)也適用于方法。將main
方法放在類內(nèi)部意味著你可以根據(jù)需要選擇設(shè)置其訪問權(quán)限,以便控制它是否可以被其他類訪問。類的上下文:
main
方法可以直接訪問類中定義的成員變量和方法。這對于在程序啟動時進行一些初始化操作或測試非常有用。簡化執(zhí)行: Java應(yīng)用程序的執(zhí)行流程始終從
main
方法開始,這種統(tǒng)一入口的設(shè)計使得程序的執(zhí)行過程變得清晰可見,易于理解和調(diào)試。基于以上原因,Java程序的
main
方法通常被放置在類的內(nèi)部作為程序的入口。當(dāng)在命令行或集成開發(fā)環(huán)境(IDE)中運行Java程序時,JVM會查找并執(zhí)行具有正確簽名(public static void main(String[] args)
)的main
方法。
3、static關(guān)鍵字
3.1 修飾變量
在Java中,使用 static
關(guān)鍵字來修飾變量會使這個變量成為一個靜態(tài)變量(也叫類變量)。靜態(tài)變量屬于類而不是對象,它在類加載時被初始化,并且在整個類的生命周期內(nèi)都只有一份副本,被所有實例共享。以下是關(guān)于使用 static
修飾變量的一些重要點:
-
靜態(tài)變量聲明: 靜態(tài)變量通常在類的頂層聲明,即在類的成員變量部分,但在方法和構(gòu)造方法之外。它們必須使用
static
關(guān)鍵字修飾。 -
初始化: 靜態(tài)變量在類加載時會被初始化,只會執(zhí)行一次。你可以在聲明時直接賦值,也可以在靜態(tài)代碼塊中進行初始化。
-
共享性: 所有類的實例共享同一個靜態(tài)變量,它不屬于特定的實例,而是屬于整個類。
-
通過類名訪問: 靜態(tài)變量可以使用類名直接訪問,不需要創(chuàng)建對象。例如,
ClassName.staticVariable
。 -
在靜態(tài)方法中使用: 靜態(tài)變量可以在靜態(tài)方法中直接使用,因為靜態(tài)方法屬于類而不是對象。
-
線程共享: 由于靜態(tài)變量屬于類,多個線程共享同一個靜態(tài)變量。需要注意線程安全問題。
下面是一個使用靜態(tài)變量的例子:
public class Example {// 靜態(tài)變量static int count = 0;// 構(gòu)造方法public Example() {count++;}// 靜態(tài)方法使用靜態(tài)變量public static void printCount() {System.out.println("Count: " + count);}public static void main(String[] args) {Example obj1 = new Example();Example obj2 = new Example();Example.printCount(); // 輸出:Count: 2}
}
在這個例子中,count
是一個靜態(tài)變量,用于計算 Example
類的實例數(shù)量。通過每次創(chuàng)建對象時遞增 count
,最終可以得到對象的總數(shù)。靜態(tài)方法 printCount
可以直接訪問靜態(tài)變量 count
,因為它們都屬于類本身。
3.2 修飾方法
方法與函數(shù)
方法(Method)和函數(shù)(Function)在編程中基本上是相同的概念,尤其在討論通用性時。它們都表示一段可重復(fù)使用的代碼塊,用于執(zhí)行特定的操作或完成特定的任務(wù)。然而,它們的使用和命名可能因編程語言而異。
在面向?qū)ο缶幊?#xff08;OOP)中,尤其是在Java等一些編程語言中,我們更常用術(shù)語“方法”來表示屬于類或?qū)ο蟮男袨?。方法是對象的行?#xff0c;它們通常用于在對象上執(zhí)行操作、訪問數(shù)據(jù)或執(zhí)行一些功能。
在一些非面向?qū)ο蟮木幊陶Z言(如C語言),我們更常用術(shù)語“函數(shù)”來表示可重用的代碼塊,它們可以獨立于對象存在。這些函數(shù)可以接受參數(shù),執(zhí)行一些操作,并返回一個值。在這種情況下,函數(shù)不一定與對象相關(guān)聯(lián),它們可以是獨立的代碼模塊。
雖然在一些語言中術(shù)語可能會有所不同,但在大多數(shù)情況下,方法和函數(shù)都指代相似的概念:可重用的代碼塊,用于執(zhí)行特定的操作或完成任務(wù)。無論使用哪個術(shù)語,它們都是編程中非常重要的概念,用于模塊化和組織代碼。
在Java中,使用 static
關(guān)鍵字修飾方法會使這個方法成為一個靜態(tài)方法。靜態(tài)方法不屬于特定的實例,而是屬于整個類,因此它可以在不創(chuàng)建類的實例的情況下直接通過類名調(diào)用。以下是關(guān)于使用 static
修飾方法的一些重要點:
-
靜態(tài)方法聲明: 靜態(tài)方法必須在類的頂層聲明,即在類的成員方法部分,但在構(gòu)造方法之外。它們必須使用
static
關(guān)鍵字修飾。 -
調(diào)用方式: 靜態(tài)方法可以通過類名直接調(diào)用,不需要創(chuàng)建對象。例如,
ClassName.staticMethod()
。 -
不能訪問實例變量: 靜態(tài)方法不能直接訪問實例變量和非靜態(tài)方法,因為它們不屬于具體的實例。只能訪問靜態(tài)變量和靜態(tài)方法。
-
不能被重寫: 靜態(tài)方法不能被子類重寫(覆蓋),因為它們屬于類而不是實例,不具有多態(tài)性。
-
可以訪問靜態(tài)成員: 靜態(tài)方法可以訪問類中的其他靜態(tài)成員,包括靜態(tài)變量和其他靜態(tài)方法。
下面是一個使用靜態(tài)方法的例子:
public class Example {// 靜態(tài)變量static int count = 0;// 靜態(tài)方法public static void incrementCount() {count++;}// 非靜態(tài)方法public void printCount() {System.out.println("Count: " + count);}public static void main(String[] args) {Example.incrementCount();Example.incrementCount();Example.printCount(); // 錯誤,靜態(tài)方法無法訪問實例方法}
}
在這個例子中,incrementCount
是一個靜態(tài)方法,用于遞增靜態(tài)變量 count
。由于它是靜態(tài)的,可以通過類名直接調(diào)用。printCount
是一個非靜態(tài)方法,無法在靜態(tài)方法中直接訪問,所以在 main
方法中調(diào)用它會導(dǎo)致錯誤。
靜態(tài)的main方法
在Java中,
main
方法必須是靜態(tài)的,否則程序無法運行。這是因為在Java程序啟動時,首先會加載類并調(diào)用靜態(tài)的main
方法作為程序的入口點。要使Java程序能夠作為可執(zhí)行程序運行,
main
方法必須滿足以下條件:
main
方法必須是public
訪問修飾符,這樣JVM才能訪問它。main
方法的返回類型必須是void
,即不返回任何值。main
方法的名稱必須是main
。main
方法的參數(shù)必須是一個String
數(shù)組(String[] args
),用于接收命令行參數(shù)。另外,由于程序啟動時沒有創(chuàng)建對象,所以
main
方法必須是靜態(tài)的,以便可以通過類名直接調(diào)用,而不需要創(chuàng)建類的實例。以下是一個標(biāo)準(zhǔn)的
main
方法的示例:public class MainExample {public static void main(String[] args) {System.out.println("Hello, Java!");} }
在這個例子中,
main
方法是一個靜態(tài)方法,因此可以通過類名MainExample
直接調(diào)用。運行這個程序時,JVM會從main
方法開始執(zhí)行,輸出 “Hello, Java!”。
3.3 修飾代碼塊
在Java中,static
關(guān)鍵字不僅可以用于修飾靜態(tài)變量和靜態(tài)方法,還可以用于修飾靜態(tài)代碼塊。靜態(tài)代碼塊是一個特殊的代碼塊,在類加載時執(zhí)行,用于進行一些類級別的初始化操作。以下是關(guān)于靜態(tài)代碼塊的一些重要點:
-
靜態(tài)代碼塊聲明: 靜態(tài)代碼塊是在類的成員部分,但在方法和構(gòu)造方法之外聲明的。它使用
static
關(guān)鍵字修飾。 -
執(zhí)行時機: 靜態(tài)代碼塊在類加載時執(zhí)行,只會執(zhí)行一次,且在類的構(gòu)造方法之前執(zhí)行。
-
初始化操作: 靜態(tài)代碼塊通常用于執(zhí)行一些類級別的初始化操作,如初始化靜態(tài)變量、加載資源等。
-
無法訪問實例成員: 靜態(tài)代碼塊不能直接訪問實例變量和實例方法,因為它在類加載時執(zhí)行,沒有創(chuàng)建對象。
-
可以訪問靜態(tài)成員: 靜態(tài)代碼塊可以訪問類中的其他靜態(tài)成員,包括靜態(tài)變量和靜態(tài)方法。
下面是一個使用靜態(tài)代碼塊的例子:
public class StaticBlockExample {// 靜態(tài)變量static int count;// 靜態(tài)代碼塊static {count = 10;System.out.println("Static block initialized.");}public static void main(String[] args) {System.out.println("Count: " + count); // 輸出:Count: 10}
}
在這個例子中,靜態(tài)代碼塊用于初始化靜態(tài)變量 count
,并輸出一條初始化信息。當(dāng)類加載時,靜態(tài)代碼塊會執(zhí)行一次,然后在 main
方法中輸出 count
的值。需要注意的是,靜態(tài)代碼塊在類加載時自動執(zhí)行,不需要顯式調(diào)用。
靜態(tài)代碼塊意義
靜態(tài)代碼塊在Java中具有重要的意義,它主要用于在類加載時進行一些初始化操作,實現(xiàn)了以下幾個方面的功能:
-
靜態(tài)成員初始化: 靜態(tài)代碼塊是在類加載時執(zhí)行的,因此可以用于初始化靜態(tài)變量。這對于需要進行一些計算、設(shè)置默認(rèn)值或者加載靜態(tài)資源的靜態(tài)變量是非常有用的。
-
資源加載: 如果一個類需要加載一些外部資源,如配置文件、數(shù)據(jù)庫連接等,靜態(tài)代碼塊可以用來加載這些資源。這樣可以確保在類第一次被使用時就完成資源的加載。
-
單次初始化: 靜態(tài)代碼塊在類加載時只會執(zhí)行一次,這意味著其中的初始化操作也只會執(zhí)行一次。這對于需要確保某些初始化操作只執(zhí)行一次的情況非常有用。
-
提高效率: 如果某些計算或操作在每個實例中都是相同的,將其放在靜態(tài)代碼塊中可以減少重復(fù)計算,從而提高效率。
-
復(fù)雜初始化: 靜態(tài)代碼塊可以用于執(zhí)行一些較為復(fù)雜的初始化操作,這些操作可能無法在變量聲明時完成。
下面是一個使用靜態(tài)代碼塊初始化數(shù)據(jù)庫連接的示例:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DatabaseConnection {static Connection connection;static {try {// 初始化數(shù)據(jù)庫連接connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");System.out.println("Database connection initialized.");} catch (SQLException e) {System.err.println("Database connection failed: " + e.getMessage());}}public static Connection getConnection() {return connection;}public static void main(String[] args) {Connection conn = DatabaseConnection.getConnection();// 使用數(shù)據(jù)庫連接執(zhí)行操作}
}
在這個例子中,靜態(tài)代碼塊被用來初始化數(shù)據(jù)庫連接,確保在類加載時連接已經(jīng)建立,從而可以在其他地方使用這個連接。這種方式能夠避免在每次需要連接數(shù)據(jù)庫時都進行重復(fù)的初始化操作。
3.4 修飾內(nèi)部類
在Java中,static
關(guān)鍵字可以用于修飾內(nèi)部類,創(chuàng)建靜態(tài)內(nèi)部類。靜態(tài)內(nèi)部類與非靜態(tài)內(nèi)部類之間有一些重要的區(qū)別,主要體現(xiàn)在內(nèi)部類的訪問方式、生命周期和作用域等方面。
以下是關(guān)于使用 static
修飾內(nèi)部類的一些重要點:
-
訪問方式: 靜態(tài)內(nèi)部類可以直接通過外部類訪問,無需創(chuàng)建外部類的實例。非靜態(tài)內(nèi)部類需要通過外部類的實例來訪問。
-
生命周期: 靜態(tài)內(nèi)部類的生命周期與外部類無關(guān),它的創(chuàng)建不依賴于外部類的實例。非靜態(tài)內(nèi)部類的生命周期與外部類實例的生命周期緊密關(guān)聯(lián)。
-
作用域: 靜態(tài)內(nèi)部類可以在外部類的靜態(tài)方法中直接使用,因為它們不依賴于外部類的實例。非靜態(tài)內(nèi)部類不能直接在外部類的靜態(tài)方法中使用,因為它們需要通過外部類的實例來訪問。
-
對外部類成員的訪問: 靜態(tài)內(nèi)部類可以訪問外部類的靜態(tài)成員,但不能直接訪問外部類的非靜態(tài)成員。非靜態(tài)內(nèi)部類可以訪問外部類的所有成員,包括靜態(tài)和非靜態(tài)。
以下是一個使用靜態(tài)內(nèi)部類的示例:
public class OuterClass {private static int outerStaticField = 10;private int outerInstanceField = 20;// 靜態(tài)內(nèi)部類public static class StaticInnerClass {public void printOuterFields() {System.out.println("Outer static field: " + outerStaticField);// 無法訪問 outerInstanceField}}public static void main(String[] args) {StaticInnerClass inner = new StaticInnerClass();inner.printOuterFields();}
}
在這個例子中,StaticInnerClass
是一個靜態(tài)內(nèi)部類。在 main
方法中,我們創(chuàng)建了 StaticInnerClass
的實例,并通過它訪問了外部類的靜態(tài)成員 outerStaticField
。需要注意的是,靜態(tài)內(nèi)部類不能直接訪問外部類的非靜態(tài)成員 outerInstanceField
。
總之,靜態(tài)內(nèi)部類是與外部類分開的獨立實體,無需外部類實例即可訪問,因此在某些場景下可以提供更好的靈活性和封裝性。
4、this關(guān)鍵字
在Java中,this
關(guān)鍵字用于引用當(dāng)前對象,即正在執(zhí)行代碼的實例對象。它在訪問類的成員變量、方法和構(gòu)造方法時非常有用,以便明確指示正在操作的對象。以下是 this
關(guān)鍵字的幾個主要作用:
-
引用當(dāng)前對象: 在類的方法中,使用
this
關(guān)鍵字引用當(dāng)前對象,以便訪問對象的成員變量和方法。 -
區(qū)分參數(shù)和成員變量: 如果方法的參數(shù)名與對象的成員變量名相同,使用
this
關(guān)鍵字可以明確指示要訪問的是成員變量而不是參數(shù)。 -
在構(gòu)造方法中調(diào)用其他構(gòu)造方法: 當(dāng)一個類有多個構(gòu)造方法時,可以使用
this
關(guān)鍵字調(diào)用其他構(gòu)造方法,以避免代碼重復(fù)。 -
返回當(dāng)前對象: 在方法中返回當(dāng)前對象本身,以支持鏈?zhǔn)秸{(diào)用的編程風(fēng)格。
以下是這些用法的示例:
public class Person {private String name;public Person(String name) {this.name = name; // 使用 this 關(guān)鍵字區(qū)分參數(shù)和成員變量}public void setName(String name) {this.name = name; // 使用 this 關(guān)鍵字引用當(dāng)前對象的成員變量}public void printName() {System.out.println("Name: " + this.name);}public Person anotherPerson() {return this; // 返回當(dāng)前對象本身}public static void main(String[] args) {Person person1 = new Person("Alice");Person person2 = new Person("Bob");person1.printName();person2.printName();person1.anotherPerson().printName(); // 鏈?zhǔn)秸{(diào)用}
}
在這個例子中,this
關(guān)鍵字用于引用當(dāng)前對象,以區(qū)分參數(shù)和成員變量、調(diào)用方法以及返回當(dāng)前對象本身。這有助于確保代碼的清晰性和準(zhǔn)確性。
5、封裝特性
封裝(Encapsulation)是面向?qū)ο缶幊?#xff08;OOP)中的一種重要特性,它指的是將數(shù)據(jù)(成員變量)和操作數(shù)據(jù)的方法(成員方法)封裝在一個類中,并通過訪問修飾符來控制對這些數(shù)據(jù)和方法的訪問。封裝旨在實現(xiàn)數(shù)據(jù)隱藏、保護數(shù)據(jù)完整性,以及提供更好的抽象和封裝性。
5.1 訪問修飾符
Java的封裝特性通過訪問修飾符實現(xiàn),主要有三種訪問修飾符:private
、protected
和 public
。以下是封裝特性的一些重要優(yōu)點和原則:
-
數(shù)據(jù)隱藏: 封裝允許將數(shù)據(jù)隱藏在類的內(nèi)部,只暴露必要的接口供外部使用。這樣可以避免直接訪問數(shù)據(jù),減少了錯誤和數(shù)據(jù)損壞的可能性。
-
數(shù)據(jù)完整性: 通過封裝,可以限制對數(shù)據(jù)的訪問方式,確保只有經(jīng)過驗證的方法可以修改數(shù)據(jù)。這有助于保持?jǐn)?shù)據(jù)的正確性和一致性。
-
抽象: 封裝使得類的外部使用者只需關(guān)心類的公共接口,而不需要了解內(nèi)部實現(xiàn)細(xì)節(jié)。這促進了抽象和模塊化編程。
-
靈活性: 封裝允許在不影響外部代碼的情況下修改類的內(nèi)部實現(xiàn)。只要類的接口保持不變,類的實現(xiàn)可以進行改進。
-
維護性: 封裝提高了代碼的可維護性,因為修改類的內(nèi)部實現(xiàn)不會影響使用該類的其他代碼。
以下是一個使用封裝的示例:
public class BankAccount {private String accountNumber;private double balance;public BankAccount(String accountNumber, double initialBalance) {this.accountNumber = accountNumber;this.balance = initialBalance;}public double getBalance() {return balance;}public void deposit(double amount) {if (amount > 0) {balance += amount;}}public void withdraw(double amount) {if (amount > 0 && amount <= balance) {balance -= amount;}}public static void main(String[] args) {BankAccount account = new BankAccount("123456", 1000.0);System.out.println("Initial balance: " + account.getBalance());account.deposit(500.0);System.out.println("After deposit: " + account.getBalance());account.withdraw(200.0);System.out.println("After withdrawal: " + account.getBalance());}
}
在這個例子中,BankAccount
類將成員變量 accountNumber
和 balance
封裝在內(nèi)部,并通過 public
方法來提供訪問。外部代碼只能通過這些方法來修改和訪問數(shù)據(jù),而無法直接訪問內(nèi)部數(shù)據(jù)。這樣可以確保數(shù)據(jù)的安全性和正確性。
5.2 包的概念
在Java中,“包”(Package)是一種用于組織和管理類和接口的方式。包是一種邏輯上的組織結(jié)構(gòu),可以將相關(guān)的類和接口組織在一起,從而實現(xiàn)更好的模塊化、代碼復(fù)用和命名空間管理。每個類都必須屬于一個包,除非它位于默認(rèn)包中。
以下是關(guān)于Java包的一些重要概念:
-
命名空間管理: 包在Java中用于創(chuàng)建命名空間,防止類名沖突。如果不使用包,可能會在不同的庫或項目中出現(xiàn)相同的類名,導(dǎo)致命名沖突。
-
包的層次結(jié)構(gòu): 包可以嵌套形成層次結(jié)構(gòu)。例如,
java.util
包是java
包的子包,java.util.ArrayList
類位于java.util
包中。 -
包的聲明: 在類文件的開頭,使用
package
關(guān)鍵字聲明類所屬的包。例如,package com.example;
聲明了類屬于com.example
包。 -
包的導(dǎo)入: 使用
import
關(guān)鍵字可以引入其他包中的類,以便在當(dāng)前類中使用。例如,import java.util.ArrayList;
導(dǎo)入了java.util
包中的ArrayList
類。 -
默認(rèn)包: 如果不在類文件中使用
package
聲明,則類被認(rèn)為屬于默認(rèn)包。默認(rèn)包是沒有命名空間的,因此不建議在實際項目中使用。 -
約定: 包名通常使用小寫字母,采用逆域名(反轉(zhuǎn)的域名)的命名方式,以確保唯一性和清晰性。例如,
com.example.myproject
。
以下是一個簡單的包使用示例:
假設(shè)有兩個類:Person
和 Address
??梢詫⑺鼈兘M織到一個叫做 com.example.myproject
的包中。
在 Person.java
文件中:
package com.example.myproject;public class Person {// 類的定義
}
在 Address.java
文件中:
package com.example.myproject;public class Address {// 類的定義
}
這樣,Person
和 Address
類就位于同一個包中,可以通過導(dǎo)入包的方式在其他類中使用它們。
和C/C++中的頭文件有些相似。
6、構(gòu)造方法
在Java中,構(gòu)造方法(Constructor)是一種特殊類型的方法,用于創(chuàng)建和初始化對象。構(gòu)造方法在對象被創(chuàng)建時自動調(diào)用,用于設(shè)置對象的初始狀態(tài),分配內(nèi)存和執(zhí)行必要的初始化操作。以下是構(gòu)造方法的一些重要特點:
-
方法名與類名相同: 構(gòu)造方法的方法名必須與類名完全相同,包括大小寫。它沒有返回類型,也不需要聲明返回值。
-
沒有返回值: 構(gòu)造方法不需要返回值類型,因為它們的主要目的是初始化對象,而不是返回值。
-
自動調(diào)用: 構(gòu)造方法在使用
new
關(guān)鍵字創(chuàng)建對象時自動調(diào)用。每次創(chuàng)建對象時,都會調(diào)用構(gòu)造方法一次。 -
重載: 類可以有多個構(gòu)造方法,以滿足不同的初始化需求。這稱為構(gòu)造方法的重載。
-
默認(rèn)構(gòu)造方法: 如果類沒有顯式定義構(gòu)造方法,編譯器會自動提供一個無參數(shù)的默認(rèn)構(gòu)造方法。如果類定義了任何構(gòu)造方法,編譯器將不再提供默認(rèn)構(gòu)造方法。
以下是一個示例,展示如何定義和使用構(gòu)造方法:
public class Person {private String name;private int age;// 構(gòu)造方法1:帶參數(shù)的構(gòu)造方法public Person(String name, int age) {this.name = name;this.age = age;}// 構(gòu)造方法2:無參數(shù)的構(gòu)造方法public Person() {this.name = "Unknown";this.age = 0;}// 成員方法public void introduce() {System.out.println("Name: " + name);System.out.println("Age: " + age);}public static void main(String[] args) {Person person1 = new Person("Alice", 25);Person person2 = new Person();person1.introduce();person2.introduce();}
}
在這個例子中,Person
類定義了兩個構(gòu)造方法:一個帶參數(shù)的構(gòu)造方法用于設(shè)置對象的初始狀態(tài),另一個無參數(shù)的構(gòu)造方法用于提供默認(rèn)值。通過 new
關(guān)鍵字創(chuàng)建對象時,會根據(jù)提供的參數(shù)選擇合適的構(gòu)造方法進行初始化。
7、代碼塊
7.1 普通代碼塊
在Java中,普通代碼塊(也稱為局部代碼塊)是一種用于限定變量作用域和執(zhí)行特定代碼的代碼塊。普通代碼塊不同于方法和構(gòu)造方法,它位于方法內(nèi)部,可以在其中定義臨時變量,這些變量只在代碼塊內(nèi)部可見。
以下是關(guān)于普通代碼塊的一些重要特點:
-
作用域限定: 在普通代碼塊中定義的變量只在代碼塊內(nèi)部可見。這有助于避免命名沖突和混淆。
-
臨時變量: 普通代碼塊通常用于定義臨時變量,這些變量在代碼塊執(zhí)行完畢后會被銷毀,不會影響到方法外部的代碼。
-
變量生命周期: 普通代碼塊內(nèi)部定義的變量的生命周期僅限于代碼塊的執(zhí)行期間。一旦代碼塊執(zhí)行完畢,變量將被銷毀。
-
代碼塊嵌套: 可以在方法中嵌套多個普通代碼塊。內(nèi)部代碼塊中的變量對外部代碼塊不可見,但外部代碼塊中的變量對內(nèi)部代碼塊可見。
以下是一個使用普通代碼塊的示例:
public class LocalBlockExample {public static void main(String[] args) {int x = 10; // 外部變量System.out.println("Outside x: " + x);{int y = 20; // 內(nèi)部代碼塊變量System.out.println("Inside y: " + y);System.out.println("Inside x: " + x); // 可以訪問外部變量}// y 在這里不可見{int z = 30; // 另一個內(nèi)部代碼塊變量System.out.println("Inside z: " + z);}// z 在這里不可見}
}
在這個例子中,我們在 main
方法中使用了兩個普通代碼塊。內(nèi)部代碼塊中的變量只在代碼塊內(nèi)部可見,不會影響到外部的變量。這有助于限定變量的作用域,提高代碼的可讀性和維護性。
7.2 成員代碼塊
成員代碼塊(Instance Initializer Block)是在Java類中的一個代碼塊,用于在創(chuàng)建對象實例時執(zhí)行初始化操作。它類似于構(gòu)造方法,但與構(gòu)造方法不同的是,成員代碼塊在每次創(chuàng)建對象時都會執(zhí)行,而不是在特定的構(gòu)造方法中執(zhí)行。
以下是關(guān)于成員代碼塊的一些重要特點:
-
執(zhí)行順序: 成員代碼塊在每次創(chuàng)建對象時都會在構(gòu)造方法之前執(zhí)行。如果一個類有多個構(gòu)造方法,它們都會共享同一個成員代碼塊。
-
共享初始化邏輯: 成員代碼塊允許在多個構(gòu)造方法之間共享相同的初始化邏輯,從而避免代碼重復(fù)。
-
可用性: 成員代碼塊可以在類的任何地方定義,不受方法的限制。它會在構(gòu)造方法前執(zhí)行,無論構(gòu)造方法如何調(diào)用。
以下是一個使用成員代碼塊的示例:
public class InstanceInitializerExample {private int x;private int y;// 成員代碼塊{x = 10;y = 20;System.out.println("Instance initializer block executed.");}// 構(gòu)造方法1public InstanceInitializerExample() {System.out.println("Constructor 1 called.");}// 構(gòu)造方法2public InstanceInitializerExample(int x, int y) {this.x = x;this.y = y;System.out.println("Constructor 2 called.");}public void printValues() {System.out.println("x: " + x + ", y: " + y);}public static void main(String[] args) {InstanceInitializerExample obj1 = new InstanceInitializerExample();obj1.printValues();InstanceInitializerExample obj2 = new InstanceInitializerExample(30, 40);obj2.printValues();}
}
在這個例子中,InstanceInitializerExample
類使用成員代碼塊來初始化 x
和 y
成員變量。每次創(chuàng)建對象時,成員代碼塊都會在構(gòu)造方法之前執(zhí)行。這有助于確保對象的初始化邏輯在不同的構(gòu)造方法中得到共享。
7.3 靜態(tài)代碼塊
上邊 3.3 static修飾代碼塊處已經(jīng)講過,就不再贅述
7.4 同步代碼塊
在以后Java多線程的學(xué)習(xí)中會介紹