Java中類(lèi)與對(duì)象的相關(guān)知識(shí)點(diǎn)總結(jié)
一、面向過(guò)程與面向?qū)ο蟮睦斫?/h2>
C語(yǔ)言是面向過(guò)程的,關(guān)注的是過(guò)程,分析出求解問(wèn)題的步驟,通過(guò)函數(shù)調(diào)用逐步解決問(wèn)題。
JAVA是基于面向?qū)ο蟮?,關(guān)注的是對(duì)象,將一件事情拆分成不同的對(duì)象,靠對(duì)象之間的交互完成。
面向過(guò)程注重的是過(guò)程,指的是在整個(gè)過(guò)程中所涉及的行為。
面向?qū)ο笞⒅氐氖菍?duì)象,也就是參與過(guò)程所涉及到的主體。是通過(guò)邏輯將一個(gè)個(gè)功能實(shí)現(xiàn)連接起來(lái)。
面向過(guò)程: 1.把冰箱打開(kāi) 2. 把東西放入 3. 冰箱關(guān)起來(lái) 面向?qū)ο螅?打開(kāi)冰箱,儲(chǔ)存,關(guān)閉都是對(duì)冰箱的操作,是冰箱被動(dòng)的行為。冰箱就是一個(gè)對(duì)象,所以只要操作冰箱所具備的功能,都要定義在冰箱中(即類(lèi))。
二、類(lèi)與對(duì)象的理解與認(rèn)識(shí)
類(lèi)就是一類(lèi)對(duì)象的統(tǒng)稱(chēng)。對(duì)象就是這一類(lèi)具體化的一個(gè)實(shí)例。類(lèi)可以比喻為一個(gè)一個(gè)的模板,里面可能會(huì)含有許多屬性或者功能。而按照模板實(shí)例化產(chǎn)生的叫對(duì)象。一個(gè)模板能夠?qū)嵗鄠€(gè)對(duì)象。
聲明一個(gè)類(lèi)就是創(chuàng)建一個(gè)新的數(shù)據(jù)類(lèi)型,而類(lèi)在 Java 中屬于引用類(lèi)型, Java 使用關(guān)鍵字 class 來(lái)聲明類(lèi)。下面是聲明類(lèi)的定義:
// 創(chuàng)建類(lèi)
class <class_name>{
field;//成員屬性
method;//成員方法
}
// 實(shí)例化對(duì)象
<class_name> <對(duì)象名> = new <class_name>();
class為定義類(lèi)的關(guān)鍵字,ClassName為類(lèi)的名字,{}中為類(lèi)的主體。
類(lèi)中的元素稱(chēng)為:成員屬性。類(lèi)中的函數(shù)稱(chēng)為:成員方法。
示例:這里就聲明了一個(gè)類(lèi)
class Person {
public int age;//成員屬性 實(shí)例變量
public String name;
public String sex;
public void eat() {//成員方法
System.out.println("吃飯!");
}
public void sleep() {
System.out.println("睡覺(jué)!");
}
}
class Person {
public int age;//成員屬性 實(shí)例變量
public String name;
public String sex;
public void eat() {//成員方法
System.out.println("吃飯!");
}
public void sleep() {
System.out.println("睡覺(jué)!");
}
}
public class Main{
public static void main(String[] args) {
Person person = new Person();//通過(guò)new實(shí)例化對(duì)象
person.eat();//成員方法調(diào)用需要通過(guò)對(duì)象的引用調(diào)用
person.sleep();
//產(chǎn)生對(duì)象 實(shí)例化對(duì)象
Person person2 = new Person();
Person person3 = new Person();
}
}
輸出結(jié)果為:
吃飯!
睡覺(jué)!
注意事項(xiàng):
- new 關(guān)鍵字用于創(chuàng)建一個(gè)對(duì)象的實(shí)例。
- 使用 . 來(lái)訪問(wèn)對(duì)象中的屬性和方法。
- 同一個(gè)類(lèi)可以創(chuàng)建多個(gè)實(shí)例。
三、類(lèi)的成員
類(lèi)的成員可以包含以下:字段、方法、代碼塊、內(nèi)部類(lèi)和接口等。此處重點(diǎn)介紹前面三個(gè)。
1.字段/屬性/成員變量
在類(lèi)中、而方法外部定義的變量稱(chēng)為 “字段” 或 “屬性” 或 “成員變量”(三種稱(chēng)呼都可以, 一般不會(huì)嚴(yán)格區(qū)分)
class Person {
public String name; // 字段
public int age; }
class Test {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
System.out.println(person.age);
}
}
// 執(zhí)行結(jié)果
null
0
注意事項(xiàng):
- 使用 . 訪問(wèn)對(duì)象的字段。
- “訪問(wèn)” 既包含讀, 也包含寫(xiě).
- 對(duì)于一個(gè)對(duì)象的字段如果沒(méi)有顯式設(shè)置初始值, 那么會(huì)被設(shè)置一個(gè)默認(rèn)的初值。
默認(rèn)值規(guī)則
對(duì)于各種數(shù)字類(lèi)型, 默認(rèn)值為 0.
對(duì)于 boolean 類(lèi)型, 默認(rèn)值為 false.
對(duì)于引用類(lèi)型(String, Array, 以及自定制類(lèi)), 默認(rèn)值為 null
2.對(duì)null的基本認(rèn)識(shí)
null 在 Java 中為 “空引用”, 表示不引用任何對(duì)象. 類(lèi)似于 C 語(yǔ)言中的空指針. 如果對(duì) null 進(jìn)行 . 操作就會(huì)引發(fā)異常。
class Person {
public String name;
public int age; }
class Test {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name.length()); // 獲取字符串長(zhǎng)度
}
}
// 執(zhí)行結(jié)果
Exception in thread "main" java.lang.NullPointerException //空指針異常
at Test.main(Test.java:9)
字段就地初始化:
雖然此時(shí)我們都不想屬性都為默認(rèn)值而需要就地初始化,但是后面我們會(huì)講到盡量不要用字段的就地初始化,否則程序會(huì)顯得非常死板。
class Person {
public String name = "張三";
public int age = 18;
}
class Test {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
System.out.println(person.age);
}
}
// 執(zhí)行結(jié)果
張三
18
引用中需要注意的地方:
1.下面這段代碼指的是person2這個(gè)引用指向person引用指向的對(duì)象。
public static void main(String[] args) {
Person person = new Person();
Person person2 = person;
}
2.一個(gè)引用無(wú)法指向多個(gè)對(duì)象,即使多次指向?qū)ο蠛螅詈笾赶虻闹荒苁亲詈笠淮沃赶虻膶?duì)象。
3.我們知道了局部變量是在棧上開(kāi)辟內(nèi)存的,而它存儲(chǔ)的是地址,也稱(chēng)為引用。那么引用一定是在棧上嗎?? 答案是否定的,看下面的代碼:
class Person {
public String name ;
public int age ;
}
public class TestDemo {
Person person = new Person();
public static void main(String[] args) {
TestDemo testDemo = new TestDemo();
}
}
內(nèi)存布局:

3.方法 (method)
用于描述一個(gè)對(duì)象的具體行為叫做方法。
class Person {
public int age = 18;
public String name = "張三";
public void show() { //show方法
System.out.println("我叫" + name + ", 今年" + age + "歲");
}
}
class Test {
public static void main(String[] args) {
Person person = new Person();
person.show();
}
}
// 執(zhí)行結(jié)果
我叫張三, 今年18歲
這樣的 show 方法是和 person 實(shí)例相關(guān)聯(lián)的,如果創(chuàng)建了其他實(shí)例,并且講類(lèi)當(dāng)中的屬性重新賦值,那么 show 的行為就會(huì)發(fā)生變化。
Person person2 = new Person(); person2.name = "李四"; person2.age = 20; person2.show(); // 執(zhí)行結(jié)果 我叫李四, 今年20歲
4.static 關(guān)鍵字
static關(guān)鍵字的作用:
- 修飾屬性 (內(nèi)存開(kāi)辟在方法區(qū)中)
- 修飾方法 (只有調(diào)用方法時(shí)才在棧中開(kāi)辟內(nèi)存)
- 代碼塊(本課件中會(huì)介紹)
- 修飾類(lèi)(后面講內(nèi)部類(lèi)會(huì)講到)
1)修飾屬性:Java靜態(tài)屬性和類(lèi)相關(guān), 和具體的實(shí)例無(wú)關(guān)。換句話說(shuō), 同一個(gè)類(lèi)的不同實(shí)例共用同一個(gè)靜態(tài)屬性。
class TestDemo{
public int a;
public static int count; }
public class Main{
public static void main(String[] args) {
TestDemo t1 = new TestDemo();
t1.a++;
TestDemo.count++;
System.out.println(t1.a);
System.out.println(TestDemo.count);
System.out.println("============");
TestDemo t2 = new TestDemo();
t2.a++;
TestDemo.count++;
System.out.println(t2.a);
System.out.println(TestDemo.count);
}
}
輸出結(jié)果:
1
1
============
1
2
若需要調(diào)用類(lèi)當(dāng)中的有static的屬性,則只需要類(lèi)名.屬性 即可調(diào)用,而不能對(duì)象名.屬性 來(lái)調(diào)用,否則編譯器會(huì)報(bào)警告。
被static修飾的成員變量的內(nèi)存在方法區(qū)中開(kāi)辟,因?yàn)樗粚儆趯?duì)象因此不在堆上開(kāi)辟內(nèi)存;而在方法區(qū)中開(kāi)辟內(nèi)存開(kāi)辟且僅開(kāi)辟一次。
下圖體現(xiàn)出對(duì)象、類(lèi)、屬性(實(shí)例成員變量、靜態(tài)成員變量)之間的關(guān)系。

2) 修飾方法
如果在任何方法上應(yīng)用 static 關(guān)鍵字,此方法稱(chēng)為靜態(tài)方法。
- 靜態(tài)方法屬于類(lèi),而不屬于類(lèi)的對(duì)象。
- 可以直接調(diào)用靜態(tài)方法,而無(wú)需創(chuàng)建類(lèi)的實(shí)例。
- 靜態(tài)方法可以訪問(wèn)靜態(tài)數(shù)據(jù)成員,并可以更改靜態(tài)數(shù)據(jù)成員的值。
class TestDemo{
public int a;
public static int count;
public static void change() {
count = 100;
//a = 10; error 不可以訪問(wèn)非靜態(tài)數(shù)據(jù)成員
}
}
public class Main{
public static void main(String[] args) {
TestDemo.change();//無(wú)需創(chuàng)建實(shí)例對(duì)象 就可以調(diào)用
System.out.println(TestDemo.count);
}
}
輸出結(jié)果:
100
注意事項(xiàng):靜態(tài)方法和實(shí)例無(wú)關(guān), 而是和類(lèi)相關(guān). 因此這導(dǎo)致了兩個(gè)情況:
- 靜態(tài)方法不能直接使用非靜態(tài)數(shù)據(jù)成員或調(diào)用非靜態(tài)方法(非靜態(tài)數(shù)據(jù)成員和方法都是和實(shí)例相關(guān)的).
- this和super兩個(gè)關(guān)鍵字不能在靜態(tài)上下文中使用(this 是當(dāng)前實(shí)例的引用, super是當(dāng)前實(shí)例父類(lèi)實(shí)例的引用, 也是和當(dāng)前實(shí)例相關(guān))
- 因?yàn)閙ain方法為static方法,因此只能實(shí)例化其他類(lèi)后才能調(diào)用其他類(lèi)中的實(shí)例成員變量或?qū)嵗蓡T方法,當(dāng)然main方法也可以直接用類(lèi)名去調(diào)用其他類(lèi)中的靜態(tài)成員變量或靜態(tài)方法。
- 靜態(tài)變量是屬于類(lèi)的,因此在方法中不能定義被static修飾的靜態(tài)方法(包括普通方法和靜態(tài)方法),但是可以初始化或者使用。
- 普通方法中可以調(diào)用靜態(tài)方法,而靜態(tài)方法中不能調(diào)用普通方法,卻又可以調(diào)用其它的靜態(tài)方法。
觀察以下代碼及理解其內(nèi)存布局:
class Person {
public int age;//實(shí)例變量 存放在對(duì)象內(nèi)
public String name;//實(shí)例變量
public String sex;//實(shí)例變量
public static int count;//類(lèi)變量也叫靜態(tài)變量,編譯時(shí)已經(jīng)產(chǎn)生,屬于類(lèi)本身,且只有一份。存放在方法區(qū)
public final int SIZE = 10;//被final修飾的叫常量,也屬于對(duì)象。 被final修飾,后續(xù)不可更改
public static final int COUNT = 99;//靜態(tài)的常量,屬于類(lèi)本身,只有一份 被final修飾,后續(xù)不可更
改
//實(shí)例成員函數(shù)
public void eat() {
int a = 10;//局部變量
System.out.println("eat()!");
}
//實(shí)例成員函數(shù)
public void sleep() {
System.out.println("sleep()!");
}
//靜態(tài)成員函數(shù)
public static void staticTest(){
//不能訪問(wèn)非靜態(tài)成員
//sex = "man"; error
System.out.println("StaticTest()");
}
}
public class Main{
public static void main(String[] args) {
//產(chǎn)生對(duì)象 實(shí)例化對(duì)象
Person person = new Person();//person為對(duì)象的引用
System.out.println(person.age);//默認(rèn)值為0
System.out.println(person.name);//默認(rèn)值為null
//System.out.println(person.count);//會(huì)有警告!
//正確訪問(wèn)方式:
System.out.println(Person.count);
System.out.println(Person.COUNT);
Person.staticTest();
//總結(jié):所有被static所修飾的方法或者屬性,全部不依賴(lài)于對(duì)象。
person.eat();
person.sleep();
}
}
輸出結(jié)果為:
0
null
0
99
StaticTest()
eat()!
sleep()!
數(shù)據(jù)屬性的內(nèi)存布局:

四、封裝
什么是封裝??簡(jiǎn)單地來(lái)說(shuō),在我們寫(xiě)代碼的時(shí)候經(jīng)常會(huì)涉及兩種角色: 類(lèi)的實(shí)現(xiàn)者和類(lèi)的調(diào)用者,而封裝能夠使得類(lèi)的調(diào)用者不必關(guān)系類(lèi)的實(shí)現(xiàn)者是如何實(shí)現(xiàn)類(lèi)的,只要知道類(lèi)中有什么方法直接調(diào)用即可。降低了類(lèi)使用者的學(xué)習(xí)和使用成本, 從而降低了復(fù)雜程度。
1. private實(shí)現(xiàn)封裝
private/ public 這兩個(gè)關(guān)鍵字是訪問(wèn)修飾限定符。
被 public 修飾的成員變量或者成員方法, 可以直接被類(lèi)的調(diào)用者使用被 private 修飾的成員變量或者成員方法, 不能被類(lèi)的調(diào)用者使用
直接使用public:
class Person {
public String name = "張三";
public int age = 18; }
class Test {
public static void main(String[] args) {
Person person = new Person();
System.out.println("我叫" + person.name + ", 今年" + person.age + "歲");
}
}
// 執(zhí)行結(jié)果
我叫張三, 今年18歲
這樣的代碼導(dǎo)致類(lèi)的使用者(main方法的代碼)必須要了解 Person 類(lèi)內(nèi)部的實(shí)現(xiàn), 才能夠使用這個(gè)類(lèi),學(xué)習(xí)成本較高。
一旦類(lèi)的實(shí)現(xiàn)者修改了代碼(例如把 name 改成 myName), 那么類(lèi)的使用者就需要大規(guī)模的修改自己的代碼, 維護(hù)成本較高。
使用private:
class Person {
private String name = "張三";
private int age = 18;
public void show() {
System.out.println("我叫" + name + ", 今年" + age + "歲");
}
}
class Test {
public static void main(String[] args) {
Person person = new Person();
person.show();
}
}
// 執(zhí)行結(jié)果
我叫張三, 今年18歲
此時(shí)字段已經(jīng)使用 private 來(lái)修飾,類(lèi)的調(diào)用者(main方法中)不能直接使用. 而需要借助 show 方法. 此時(shí)類(lèi)的使用者就不必了解 Person 類(lèi)的實(shí)現(xiàn)細(xì)節(jié)。
同時(shí)如果類(lèi)的實(shí)現(xiàn)者修改了字段的名字, 類(lèi)的調(diào)用者不需要做出任何修改(類(lèi)的調(diào)用者根本訪問(wèn)不到 name, age這樣的字段)
private 不光能修飾字段, 也能修飾方法
通常情況下我們會(huì)把字段設(shè)為 private 屬性, 但是方法是否需要設(shè)為 public, 就需要視具體情形而定. 一般我們希望一個(gè)類(lèi)只提供 “必要的” public 方法, 而不應(yīng)該是把所有的方法都設(shè)為 public。
2.getter和setter方法
被private修飾的字段不等于無(wú)法在類(lèi)外使用該字段。那么如何在類(lèi)外中獲取被private修飾的字段呢?此處jdk為我們提供了getter和setter方法 。
代碼示例:
class Person {
private String name;//實(shí)例成員變量
private int age;
public void setName(String name){
//name = name;//不能這樣寫(xiě),否則name仍為0,局部變量?jī)?yōu)先
this.name = name;//this引用,表示調(diào)用該方法的對(duì)象的name
}
public String getName(){
return name;
}
public void show(){
System.out.println("name: "+name+" age: "+age);
}
}
public static void main(String[] args) {
Person person = new Person();
person.setName("caocao");
String name = person.getName();
System.out.println(name);
person.show();
}
// 運(yùn)行結(jié)果
caocao
name: caocao age: 0
注意事項(xiàng):
- getName 即為 getter 方法, 表示獲取這個(gè)成員的值
- setName 即為 setter 方法, 表示設(shè)置這個(gè)成員的值
- 當(dāng)set方法的形參名字和類(lèi)中的成員屬性的名字一樣的時(shí)候,如果不使用this, 相當(dāng)于自賦值. this 表示當(dāng)前實(shí)例的引用
- 不是所有的字段都一定要提供 setter / getter 方法, 而是要根據(jù)實(shí)際情況決定提供哪種方法
- 在 IDEA 中可以使用 alt + insert (或者 alt + F12) 快速生成 setter / getter 方法. 在 VSCode 中可以使用鼠標(biāo)右鍵菜單 -> 源代碼操作 中自動(dòng)生成 setter / getter 方法

五、構(gòu)造方法
1.構(gòu)造方法的基本語(yǔ)法及使用
構(gòu)造方法是一種特殊方法, 使用關(guān)鍵字new實(shí)例化新對(duì)象時(shí)會(huì)被自動(dòng)調(diào)用, 用于完成初始化操作。
new 執(zhí)行過(guò)程:
- 為對(duì)象分配內(nèi)存空間
- 調(diào)用對(duì)象的構(gòu)造方法
語(yǔ)法規(guī)則:
- 方法名稱(chēng)必須與類(lèi)名稱(chēng)相同。
- 構(gòu)造方法沒(méi)有返回值類(lèi)型聲明。
- 每一個(gè)類(lèi)中一定至少存在一個(gè)構(gòu)造方法(如果沒(méi)有明確定義,則系統(tǒng)自動(dòng)生成一個(gè)無(wú)參構(gòu)造方法)
注意事項(xiàng):
- 如果類(lèi)中沒(méi)有提供任何的構(gòu)造函數(shù),那么編譯器會(huì)默認(rèn)生成一個(gè)不帶有參數(shù)的構(gòu)造函數(shù)
- 若類(lèi)中定義了構(gòu)造方法,則默認(rèn)的無(wú)參構(gòu)造將不再生成,如果再需要調(diào)用無(wú)參的構(gòu)造方法則需要手動(dòng)寫(xiě)一個(gè)。
- 構(gòu)造方法支持重載,規(guī)則和普通方法的重載一致。(對(duì)返回值不作要求,方法名相同,參數(shù)不同可包括參數(shù)個(gè)數(shù)不同或參數(shù)類(lèi)型不同)
代碼示例:
class Person {
private String name;//實(shí)例成員變量
private int age;
private String sex;
//默認(rèn)構(gòu)造函數(shù) 構(gòu)造對(duì)象
public Person() {
this.name = "caocao";
this.age = 10;
this.sex = "男";
}
//帶有3個(gè)參數(shù)的構(gòu)造函數(shù)
public Person(String name,int age,String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main{
public static void main(String[] args) {
Person p1 = new Person();//調(diào)用不帶參數(shù)的構(gòu)造函數(shù) 如果程序沒(méi)有提供會(huì)調(diào)用不帶參數(shù)的構(gòu)造函數(shù)
p1.show();
Person p2 = new Person("zhangfei",80,"男");//調(diào)用帶有3個(gè)參數(shù)的構(gòu)造函數(shù)
p2.show();
}
}
// 執(zhí)行結(jié)果
name: caocao age: 10 sex: 男
name: zhangfei age: 80 sex: 男
2.this關(guān)鍵字
this表示當(dāng)前對(duì)象引用(注意不是當(dāng)前對(duì)象),可以借助 this 來(lái)訪問(wèn)對(duì)象的字段和方法。this表示當(dāng)前對(duì)象引用是因?yàn)樵趧?chuàng)建對(duì)象的過(guò)程中會(huì)調(diào)用合適的構(gòu)造方法,而構(gòu)造方法內(nèi)部能夠用this關(guān)鍵字,而對(duì)象在創(chuàng)建的過(guò)程當(dāng)中(對(duì)象還未被創(chuàng)建出來(lái))就使用了this關(guān)鍵字,證明this指向的是當(dāng)前對(duì)象的引用。
class Person {
private String name;//實(shí)例成員變量
private int age;
private String sex;
//默認(rèn)構(gòu)造函數(shù) 構(gòu)造對(duì)象
public Person() {
//this調(diào)用構(gòu)造函數(shù)
this("bit", 12, "man");//必須放在第一行進(jìn)行顯示
}
//這兩個(gè)構(gòu)造函數(shù)之間的關(guān)系為重載。
public Person(String name,int age,String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void show() {
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main{
public static void main(String[] args) {
Person person = new Person();//調(diào)用不帶參數(shù)的構(gòu)造函數(shù)
person.show();
}
}
// 執(zhí)行結(jié)果
name: bit age: 12 sex: man
this既可以指的是當(dāng)前對(duì)象的引用中的屬性,也可以在構(gòu)造方法內(nèi)部使用(若是調(diào)用其它構(gòu)造方法則只能在構(gòu)造方法內(nèi)部使用)。
代碼示例:
class Person {
private String name ;
private int age ;
public Person() {
this("zjr",18);
}
public Person(String name ,int age) {
System.out.println("name:"+name+" age:"+age);
}
}
public class TestDemo {
public static void main(String[] args) {
Person person =new Person();
}
}
運(yùn)行結(jié)果:

結(jié)論:
如果用this關(guān)鍵字調(diào)用其它構(gòu)造方法的放在第二行則會(huì)報(bào)錯(cuò);并且調(diào)用構(gòu)造方法只能調(diào)用一次。要習(xí)慣于使用this關(guān)鍵字,this關(guān)鍵字能夠有效地避免在對(duì)象的屬性賦值時(shí)兩邊變量名相同會(huì)出錯(cuò)。
六、Java中的代碼塊
字段的初始化方式有:
- 就地初始化
- 使用構(gòu)造方法初始化
- 使用代碼塊初始化
前兩種初始化方式都已介紹過(guò),那么如何單純用代碼塊來(lái)初始化屬性??
1.認(rèn)識(shí)代碼塊
使用 {} 定義的一段代碼.
根據(jù)代碼塊定義的位置以及關(guān)鍵字,又可分為以下四種:
- 普通代碼塊(只做了解)
- 構(gòu)造塊
- 靜態(tài)塊
- 同步代碼塊(后續(xù)講解多線程部分再談)
2.普通代碼塊
普通代碼塊:定義在方法中的代碼塊。
public class Main{
public static void main(String[] args) {
{ //直接使用{}定義,普通方法塊
int x = 10 ;
System.out.println("x1 = " +x);
}
int x = 100 ;
System.out.println("x2 = " +x);
}
}
// 執(zhí)行結(jié)果
x1 = 10
x2 = 100
3.構(gòu)造代碼塊
構(gòu)造塊:定義在類(lèi)中的代碼塊(不加修飾符)。也叫:實(shí)例代碼塊。構(gòu)造代碼塊一般用于初始化實(shí)例成員變量。
代碼示例:
class Person{
private String name;//實(shí)例成員變量
private int age;
private String sex;
public Person() {
System.out.println("I am Person init()!");
}
//實(shí)例代碼塊
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
p1.show();
}
}
// 運(yùn)行結(jié)果
I am instance init()!
I am Person init()!
name: bit age: 12 sex: man
注意事項(xiàng): 實(shí)例代碼塊優(yōu)先于構(gòu)造函數(shù)執(zhí)行。
4.靜態(tài)代碼塊
使用static定義的代碼塊。一般用于初始化靜態(tài)成員屬性。
class Person{
private String name;//實(shí)例成員變量
private int age;
private String sex;
private static int count = 0;//靜態(tài)成員變量 由類(lèi)共享數(shù)據(jù) 方法區(qū)
public Person(){
System.out.println("I am Person init()!");
}
//實(shí)例代碼塊
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
//靜態(tài)代碼塊
static {
count = 10;//只能訪問(wèn)靜態(tài)數(shù)據(jù)成員
System.out.println("I am static init()!");
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();//靜態(tài)代碼塊是否還會(huì)被執(zhí)行?
}
}
注意:
- 靜態(tài)代碼塊不管生成多少個(gè)對(duì)象,其只會(huì)執(zhí)行一次,且是最先執(zhí)行的。
- 靜態(tài)代碼塊執(zhí)行完畢后, 實(shí)例代碼塊(構(gòu)造塊)執(zhí)行,再然后是構(gòu)造函數(shù)執(zhí)行。
- 只有靜態(tài)代碼塊不需要實(shí)例化對(duì)象就能夠執(zhí)行。只要調(diào)用了類(lèi)中的某個(gè)變量或方法(靜態(tài))就能夠被執(zhí)行。靜態(tài)代碼塊的執(zhí)行是在類(lèi)的加載過(guò)程執(zhí)行的,因此只執(zhí)行一次。
- 靜態(tài)代碼塊的使用基變量本上跟static方法差不多,也不能出現(xiàn)this與定義被static修飾的變量,不依賴(lài)于對(duì)象。
- 靜態(tài)代碼塊中可以使用靜態(tài)變量,但是對(duì)于被靜態(tài)修飾的代碼塊與變量執(zhí)行的先后順序又不一樣,它是根據(jù)代碼的執(zhí)行先后順序決定的(前提是在初始化時(shí)已經(jīng)賦予初值,否則仍然遵循靜態(tài)代碼塊先執(zhí)行的順序)。例如:
class Person {
public String name ;
public int age ;
public static int count = 10 ;
static {
count=99;
System.out.println("靜態(tài)");
}
{
System.out.println("實(shí)例");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
System.out.println(Person.count);
}
}
運(yùn)行結(jié)果:

交換執(zhí)行先后順序:
class Person {
public String name ;
public int age ;
static {
count=99;
System.out.println("靜態(tài)");
}
public static int count = 10 ;
{
System.out.println("實(shí)例");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
System.out.println(Person.count);
}
}

因此如果靜態(tài)變量沒(méi)賦初值,則結(jié)果是靜態(tài)代碼塊內(nèi)賦的值;如果靜態(tài)變量賦了初值,則按照?qǐng)?zhí)行順序決定改變量最后的值,除了變量賦值語(yǔ)句執(zhí)行順序不同以外,靜態(tài)代碼塊內(nèi)的語(yǔ)句都是先執(zhí)行的。
代碼塊中的重點(diǎn)是主要了解實(shí)例代碼塊、靜態(tài)代碼塊、構(gòu)造方法的運(yùn)行順序??偨Y(jié):先運(yùn)行的是靜態(tài)代碼塊,再運(yùn)行實(shí)例代碼塊(構(gòu)造代碼塊),最后運(yùn)行構(gòu)造方法。靜態(tài)代碼塊內(nèi)的只運(yùn)行一次。
七、toString方法
1.重寫(xiě)println的toString方法
我們剛剛注意到,我們?cè)诎褜?duì)象的屬性進(jìn)行打印的時(shí)候,我們是自己實(shí)現(xiàn)了show函數(shù)。但在Java中它提供了一個(gè)給我們打印屬性的方法。叫toString方法。
代碼示例:
class Person {
private String name;
private int age;
public Person(String name,int age) {
this.age = age;
this.name = name;
}
public void show() {
System.out.println("name:"+name+" " + "age:"+age);
}
//重寫(xiě)Object的toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person("caocao",19);
person.show();
System.out.println(person);
}
}
// 執(zhí)行結(jié)果
name:caocao age:19
Person{name='caocao', age=19}
注意事項(xiàng):
- toString 方法會(huì)在 println 的時(shí)候被自動(dòng)調(diào)用
- 將對(duì)象轉(zhuǎn)成字符串這樣的操作我們稱(chēng)為序列化
- toString 是 Object 類(lèi)提供的方法, 我們自己創(chuàng)建的 Person 類(lèi)默認(rèn)繼承自 Object 類(lèi), 可以重寫(xiě) toString 方法實(shí)現(xiàn)我們自己版本的轉(zhuǎn)換字符串方法. (關(guān)于繼承和重寫(xiě)這樣的概念, 我們后面會(huì)重點(diǎn)介紹).
- @Override 在 Java 中稱(chēng)為 “注解”, 此處的 @Override 表示下面實(shí)現(xiàn)的 toString 方法是重寫(xiě)了父類(lèi)的方法,關(guān)于注解后面的課程會(huì)詳細(xì)介紹.
- IDEA快速生成Object的toString方法快捷鍵:alt+f12(insert)

若我們要觀察println中的toString方法,則我們可以按住ctrl鍵,將鼠標(biāo)點(diǎn)到println中的位置。點(diǎn)入println中會(huì)看到如圖所示:

再按ctrl鍵將鼠標(biāo)放在紅框處點(diǎn)入,看到的如圖所示:

最后將進(jìn)入紅框內(nèi)的方法當(dāng)中,如圖所示:

因此我們能夠證實(shí)println中的toString方法是按照哈希值來(lái)進(jìn)行處理后打印的。因此如果我們重寫(xiě)了它的toString方法來(lái)打印我們類(lèi)中的屬性,則直接System.out.println(person);即可(代碼如上所示),若沒(méi)有重寫(xiě)println中的toString方法,則再用System.out.println(person);時(shí)打印的結(jié)果為:類(lèi)名+@+經(jīng)過(guò)哈希值處理的地址。

2.匿名對(duì)象
匿名只是表示沒(méi)有名字的對(duì)象
- 沒(méi)有引用的對(duì)象稱(chēng)為匿名對(duì)象
- 匿名對(duì)象只能在創(chuàng)建對(duì)象時(shí)使用
- 如果一個(gè)對(duì)象只是用一次, 后面不需要用了, 可以考慮使用匿名對(duì)象
class Person {
private String name;
private int age;
public Person(String name,int age) {
this.age = age;
this.name = name;
}
public void show() {
System.out.println("name:"+name+" " + "age:"+age);
}
}
public class Main {
public static void main(String[] args) {
new Person("caocao",19).show();//通過(guò)匿名對(duì)象調(diào)用方法
}
}
// 執(zhí)行結(jié)果
name:caocao age:19
重點(diǎn):注意匿名對(duì)象是如何調(diào)用類(lèi)中的方法的。
八、交換兩個(gè)數(shù)的值(實(shí)參交換)
代碼:
class Test {
private int num ;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
public class TestDemo2 {
public static void Swap(Test test1,Test test2) {
int tmp = test1.getNum();
test1.setNum(test2.getNum()) ;
test2.setNum(tmp);
}
public static void main(String[] args) {
Test test1 = new Test();
Test test2 = new Test();
test1.setNum(10);
test2.setNum(20);
System.out.println(test1.getNum());
System.out.println(test2.getNum());
Swap(test1,test2);
System.out.println(test1.getNum());
System.out.println(test2.getNum());
}
}
運(yùn)行結(jié)果:

總結(jié)
到此這篇關(guān)于Java中類(lèi)與對(duì)象知識(shí)點(diǎn)的文章就介紹到這了,更多相關(guān)Java類(lèi)與對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java連接Redis報(bào)錯(cuò):NoSuchElementException: Unable to&nb
這篇文章主要介紹了Java連接Redis報(bào)錯(cuò):NoSuchElementException: Unable to validate object的解決辦法,文中通過(guò)圖文講解的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2024-12-12
Mybatis查詢語(yǔ)句返回對(duì)象和泛型集合的操作
這篇文章主要介紹了Mybatis查詢語(yǔ)句返回對(duì)象和泛型集合的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
springboot?web項(xiàng)目中?Set-Cookie?失敗原因及解決辦法
這篇文章主要介紹了springboot?web項(xiàng)目中?Set-Cookie?失敗原因及解決辦法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-10-10
Javaweb EL自定義函數(shù)開(kāi)發(fā)及代碼實(shí)例
這篇文章主要介紹了Javaweb EL自定義函數(shù)開(kāi)發(fā)及代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06

