文章目錄
- 一、面向程序與面向物件的理解
- 二、類與物件的理解與認識
- 三、類的成員
- 1.欄位/屬性/成員變數
- 2.對null的基本認識
- 3.方法 (method)
- 4.static 關鍵字
- 四、封裝
- 1. private實作封裝
- 2.getter和setter方法
- 五、構造方法
- 1.構造方法的基本語法及使用
- 2.this關鍵字
- 六、Java中的代碼塊
- 1.認識代碼塊
- 2.普通代碼塊
- 3.構造代碼塊
- 4.靜態代碼塊
- 七、toString方法
- 1.重寫println的toString方法
- 2.匿名物件
- 八、交換兩個數的值(實參交換)
一、面向程序與面向物件的理解
C語言是面向程序的,關注的是程序,分析出求解問題的步驟,通過函式呼叫逐步解決問題,
JAVA是基于面向物件的,關注的是物件,將一件事情拆分成不同的物件,靠物件之間的互動完成,
面向程序注重的是程序,指的是在整個程序中所涉及的行為,
面向物件注重的是物件,也就是參與程序所涉及到的主體,是通過邏輯將一個個功能實作連接起來,
面向程序: 1.把冰箱打開 2. 把東西放入 3. 冰箱關起來 面向物件: 打開冰箱,儲存,關閉都是對冰箱的操作,是冰箱被動的行為,冰箱就是一個物件,所以只要操作冰箱所具備的功能,都要定義在冰箱中(即類),
二、類與物件的理解與認識
類就是一類物件的統稱,物件就是這一類具體化的一個實體,類可以比喻為一個一個的模板,里面可能會含有許多屬性或者功能,而按照模板實體化產生的叫物件,一個模板能夠實體化多個物件,
宣告一個類就是創建一個新的資料型別,而類在 Java 中屬于參考型別, Java 使用關鍵字 class 來宣告類,下面是宣告類的定義:
// 創建類
class <class_name>{
field;//成員屬性
method;//成員方法
}
// 實體化物件
<class_name> <物件名> = new <class_name>();
class為定義類的關鍵字,ClassName為類的名字,{}中為類的主體,
類中的元素稱為:成員屬性,類中的函式稱為:成員方法,
示例:這里就宣告了一個類
class Person {
public int age;//成員屬性 實體變數
public String name;
public String sex;
public void eat() {//成員方法
System.out.println("吃飯!");
}
public void sleep() {
System.out.println("睡覺!");
}
}
class Person {
public int age;//成員屬性 實體變數
public String name;
public String sex;
public void eat() {//成員方法
System.out.println("吃飯!");
}
public void sleep() {
System.out.println("睡覺!");
}
}
public class Main{
public static void main(String[] args) {
Person person = new Person();//通過new實體化物件
person.eat();//成員方法呼叫需要通過物件的參考呼叫
person.sleep();
//產生物件 實體化物件
Person person2 = new Person();
Person person3 = new Person();
}
}
輸出結果為:
吃飯!
睡覺!
注意事項:
- new 關鍵字用于創建一個物件的實體,
- 使用 . 來訪問物件中的屬性和方法,
- 同一個類可以創建多個實體,
三、類的成員
類的成員可以包含以下:欄位、方法、代碼塊、內部類和介面等,此處重點介紹前面三個,
1.欄位/屬性/成員變數
在類中、而方法外部定義的變數稱為 “欄位” 或 “屬性” 或 “成員變數”(三種稱呼都可以, 一般不會嚴格區分)
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);
}
}
// 執行結果
null
0
注意事項:
- 使用 . 訪問物件的欄位,
- “訪問” 既包含讀, 也包含寫.
- 對于一個物件的欄位如果沒有顯式設定初始值, 那么會被設定一個默認的初值,
默認值規則
對于各種數字型別, 默認值為 0.
對于 boolean 型別, 默認值為 false.
對于參考型別(String, Array, 以及自定制類), 默認值為 null
2.對null的基本認識
null 在 Java 中為 “空參考”, 表示不參考任何物件. 類似于 C 語言中的空指標. 如果對 null 進行 . 操作就會引發例外,
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()); // 獲取字串長度
}
}
// 執行結果
Exception in thread "main" java.lang.NullPointerException //空指標例外
at Test.main(Test.java:9)
欄位就地初始化:
雖然此時我們都不想屬性都為默認值而需要就地初始化,但是后面我們會講到盡量不要用欄位的就地初始化,否則程式會顯得非常死板,
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);
}
}
// 執行結果
張三
18
3.方法 (method)
用于描述一個物件的具體行為叫做方法,
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();
}
}
// 執行結果
我叫張三, 今年18歲
這樣的 show 方法是和 person 實體相關聯的,如果創建了其他實體,并且講類當中的屬性重新賦值,那么 show 的行為就會發生變化,
Person person2 = new Person();
person2.name = "李四";
person2.age = 20;
person2.show();
// 執行結果
我叫李四, 今年20歲
4.static 關鍵字
static關鍵字的作用:
- 修飾屬性 (記憶體開辟在方法區中)
- 修飾方法 (只有呼叫方法時才在堆疊中開辟記憶體)
- 代碼塊(本課件中會介紹)
- 修飾類(后面講內部類會講到)
1)修飾屬性:Java靜態屬性和類相關, 和具體的實體無關,換句話說, 同一個類的不同實體共用同一個靜態屬性,
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);
}
}
輸出結果:
1
1
============
1
2
若需要呼叫類當中的有static的屬性,則只需要類名.屬性 即可呼叫,而不能物件名.屬性 來呼叫,否則編譯器會報警告,
被static修飾的成員變數的記憶體在方法區中開辟,因為它不屬于物件因此不在堆上開辟記憶體;而在方法區中開辟記憶體開辟且僅開辟一次,
下圖體現出物件、類、屬性(實體成員變數、靜態成員變數)之間的關系,

2) 修飾方法
如果在任何方法上應用 static 關鍵字,此方法稱為靜態方法,
- 靜態方法屬于類,而不屬于類的物件,
- 可以直接呼叫靜態方法,而無需創建類的實體,
- 靜態方法可以訪問靜態資料成員,并可以更改靜態資料成員的值,
class TestDemo{
public int a;
public static int count;
public static void change() {
count = 100;
//a = 10; error 不可以訪問非靜態資料成員
}
}
public class Main{
public static void main(String[] args) {
TestDemo.change();//無需創建實體物件 就可以呼叫
System.out.println(TestDemo.count);
}
}
輸出結果:
100
注意事項:靜態方法和實體無關, 而是和類相關. 因此這導致了兩個情況:
- 靜態方法不能直接使用非靜態資料成員或呼叫非靜態方法(非靜態資料成員和方法都是和實體相關的).
- this和super兩個關鍵字不能在靜態背景關系中使用(this 是當前實體的參考, super是當前實體父類實體的參考, 也是和當前實體相關)
- 因為main方法為static方法,因此只能實體化其他類后才能呼叫其他類中的實體成員變數或實體成員方法,當然main方法也可以直接用類名去呼叫其他類中的靜態成員變數或靜態方法,
觀察以下代碼及理解其記憶體布局:
class Person {
public int age;//實體變數 存放在物件內
public String name;//實體變數
public String sex;//實體變數
public static int count;//類變數也叫靜態變數,編譯時已經產生,屬于類本身,且只有一份,存放在方法區
public final int SIZE = 10;//被final修飾的叫常量,也屬于物件, 被final修飾,后續不可更改
public static final int COUNT = 99;//靜態的常量,屬于類本身,只有一份 被final修飾,后續不可更
改
//實體成員函式
public void eat() {
int a = 10;//區域變數
System.out.println("eat()!");
}
//實體成員函式
public void sleep() {
System.out.println("sleep()!");
}
//靜態成員函式
public static void staticTest(){
//不能訪問非靜態成員
//sex = "man"; error
System.out.println("StaticTest()");
}
}
public class Main{
public static void main(String[] args) {
//產生物件 實體化物件
Person person = new Person();//person為物件的參考
System.out.println(person.age);//默認值為0
System.out.println(person.name);//默認值為null
//System.out.println(person.count);//會有警告!
//正確訪問方式:
System.out.println(Person.count);
System.out.println(Person.COUNT);
Person.staticTest();
//總結:所有被static所修飾的方法或者屬性,全部不依賴于物件,
person.eat();
person.sleep();
}
}
輸出結果為:
0
null
0
99
StaticTest()
eat()!
sleep()!
資料屬性的記憶體布局:

四、封裝
什么是封裝??簡單地來說,在我們寫代碼的時候經常會涉及兩種角色: 類的實作者和類的呼叫者,而封裝能夠使得類的呼叫者不必關系類的實作者是如何實作類的,只要知道類中有什么方法直接呼叫即可,降低了類使用者的學習和使用成本, 從而降低了復雜程度,
1. private實作封裝
private/ public 這兩個關鍵字是訪問修飾限定符,
- 被 public 修飾的成員變數或者成員方法, 可以直接被類的呼叫者使用
- 被 private 修飾的成員變數或者成員方法, 不能被類的呼叫者使用
直接使用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 + "歲");
}
}
// 執行結果
我叫張三, 今年18歲
這樣的代碼導致類的使用者(main方法的代碼)必須要了解 Person 類內部的實作, 才能夠使用這個類,學習成本較高,
一旦類的實作者修改了代碼(例如把 name 改成 myName), 那么類的使用者就需要大規模的修改自己的代碼, 維護成本較高,
使用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();
}
}
// 執行結果
我叫張三, 今年18歲
此時欄位已經使用 private 來修飾,類的呼叫者(main方法中)不能直接使用. 而需要借助 show 方法. 此時類的使用者就不必了解 Person 類的實作細節,
同時如果類的實作者修改了欄位的名字, 類的呼叫者不需要做出任何修改(類的呼叫者根本訪問不到 name, age這樣的欄位)
private 不光能修飾欄位, 也能修飾方法
通常情況下我們會把欄位設為 private 屬性, 但是方法是否需要設為 public, 就需要視具體情形而定. 一般我們希望一個類只提供 “必要的” public 方法, 而不應該是把所有的方法都設為 public,
2.getter和setter方法
被private修飾的欄位不等于無法在類外使用該欄位,那么如何在類外中獲取被private修飾的欄位呢?此處jdk為我們提供了getter和setter方法 ,
代碼示例:
class Person {
private String name;//實體成員變數
private int age;
public void setName(String name){
//name = name;//不能這樣寫,否則name仍為0,區域變數優先
this.name = name;//this參考,表示呼叫該方法的物件的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();
}
// 運行結果
caocao
name: caocao age: 0
注意事項:
- getName 即為 getter 方法, 表示獲取這個成員的值
- setName 即為 setter 方法, 表示設定這個成員的值
- 當set方法的形參名字和類中的成員屬性的名字一樣的時候,如果不使用this, 相當于自賦值. this 表示當前實體的參考
- 不是所有的欄位都一定要提供 setter / getter 方法, 而是要根據實際情況決定提供哪種方法
- 在 IDEA 中可以使用 alt + insert (或者 alt + F12) 快速生成 setter / getter 方法. 在 VSCode 中可以使用滑鼠右鍵選單 -> 源代碼操作 中自動生成 setter / getter 方法

五、構造方法
1.構造方法的基本語法及使用
構造方法是一種特殊方法, 使用關鍵字new實體化新物件時會被自動呼叫, 用于完成初始化操作,
new 執行程序:
- 為物件分配記憶體空間
- 呼叫物件的構造方法
語法規則:
- 方法名稱必須與類名稱相同,
- 構造方法沒有回傳值型別宣告,
- 每一個類中一定至少存在一個構造方法(如果沒有明確定義,則系統自動生成一個無參構造方法)
注意事項:
- 如果類中沒有提供任何的建構式,那么編譯器會默認生成一個不帶有引數的建構式
- 若類中定義了構造方法,則默認的無參構造將不再生成,如果再需要呼叫無參的構造方法則需要手動寫一個,
- 構造方法支持多載,規則和普通方法的多載一致,(對回傳值不作要求,方法名相同,引數不同可包括引數個數不同或引數型別不同)
代碼示例:
class Person {
private String name;//實體成員變數
private int age;
private String sex;
//默認建構式 構造物件
public Person() {
this.name = "caocao";
this.age = 10;
this.sex = "男";
}
//帶有3個引數的建構式
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();//呼叫不帶引數的建構式 如果程式沒有提供會呼叫不帶引數的建構式
p1.show();
Person p2 = new Person("zhangfei",80,"男");//呼叫帶有3個引數的建構式
p2.show();
}
}
// 執行結果
name: caocao age: 10 sex: 男
name: zhangfei age: 80 sex: 男
2.this關鍵字
this表示當前物件參考(注意不是當前物件),可以借助 this 來訪問物件的欄位和方法,this表示當前物件參考是因為在創建物件的程序中會呼叫合適的構造方法,而構造方法內部能夠用this關鍵字,而物件在創建的程序當中(物件還未被創建出來)就使用了this關鍵字,證明this指向的是當前物件的參考,
class Person {
private String name;//實體成員變數
private int age;
private String sex;
//默認建構式 構造物件
public Person() {
//this呼叫建構式
this("bit", 12, "man");//必須放在第一行進行顯示
}
//這兩個建構式之間的關系為多載,
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();//呼叫不帶引數的建構式
person.show();
}
}
// 執行結果
name: bit age: 12 sex: man
this既可以指的是當前物件的參考中的屬性,也可以在構造方法內部使用(若是呼叫其它構造方法則只能在構造方法內部使用),
代碼示例:
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();
}
}
運行結果:

結論:
- 如果用this關鍵字呼叫其它構造方法的放在第二行則會報錯;并且呼叫構造方法只能怪呼叫一次,
- 要習慣于使用this關鍵字,this關鍵字能夠有效地避免在物件的屬性賦值時兩邊變數名相同會出錯,
六、Java中的代碼塊
欄位的初始化方式有:
- 就地初始化
- 使用構造方法初始化
- 使用代碼塊初始化
前兩種初始化方式都已介紹過,那么如何單純用代碼塊來初始化屬性??
1.認識代碼塊
使用 {} 定義的一段代碼.
根據代碼塊定義的位置以及關鍵字,又可分為以下四種:
- 普通代碼塊(只做了解)
- 構造塊
- 靜態塊
- 同步代碼塊(后續講解多執行緒部分再談)
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);
}
}
// 執行結果
x1 = 10
x2 = 100
3.構造代碼塊
構造塊:定義在類中的代碼塊(不加修飾符),也叫:實體代碼塊,構造代碼塊一般用于初始化實體成員變數,
代碼示例:
class Person{
private String name;//實體成員變數
private int age;
private String sex;
public Person() {
System.out.println("I am Person init()!");
}
//實體代碼塊
{
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();
}
}
// 運行結果
I am instance init()!
I am Person init()!
name: bit age: 12 sex: man
注意事項: 實體代碼塊優先于建構式執行,
4.靜態代碼塊
使用static定義的代碼塊,一般用于初始化靜態成員屬性,
class Person{
private String name;//實體成員變數
private int age;
private String sex;
private static int count = 0;//靜態成員變數 由類共享資料 方法區
public Person(){
System.out.println("I am Person init()!");
}
//實體代碼塊
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
//靜態代碼塊
static {
count = 10;//只能訪問靜態資料成員
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();//靜態代碼塊是否還會被執行?
}
}
注意:
- 靜態代碼塊不管生成多少個物件,其只會執行一次,且是最先執行的,
- 靜態代碼塊執行完畢后, 實體代碼塊(構造塊)執行,再然后是建構式執行
代碼塊中的重點是主要了解實體代碼塊、靜態代碼塊、構造方法的運行順序,總結:先運行的是靜態代碼塊,再運行實體代碼塊(構造代碼塊),最后運行構造方法,
七、toString方法
1.重寫println的toString方法
我們剛剛注意到,我們在把物件的屬性進行列印的時候,我們是自己實作了show函式,但在Java中它提供了一個給我們列印屬性的方法,叫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);
}
//重寫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);
}
}
// 執行結果
name:caocao age:19
Person{name='caocao', age=19}
注意事項:
- toString 方法會在 println 的時候被自動呼叫
- 將物件轉成字串這樣的操作我們稱為序列化
- toString 是 Object 類提供的方法, 我們自己創建的 Person 類默認繼承自 Object 類, 可以重寫 toString 方法實作我們自己版本的轉換字串方法. (關于繼承和重寫這樣的概念, 我們后面會重點介紹).
- @Override 在 Java 中稱為 “注解”, 此處的 @Override 表示下面實作的 toString 方法是重寫了父類的方法,關于注解后面的課程會詳細介紹.
- IDEA快速生成Object的toString方法快捷鍵:alt+f12(insert)

若我們要觀察println中的toString方法,則我們可以按住ctrl鍵,將滑鼠點到println中的位置,點入println中會看到如圖所示:

再按ctrl鍵將滑鼠放在紅框處點入,看到的如圖所示:

最后將進入紅框內的方法當中,如圖所示:

因此我們能夠證實println中的toString方法是按照哈希值來進行處理后列印的,因此如果我們重寫了它的toString方法來列印我們類中的屬性,則直接System.out.println(person);即可(代碼如上所示),若沒有重寫println中的toString方法,則再用System.out.println(person);時列印的結果為:類名+@+經過哈希值處理的地址,

2.匿名物件
匿名只是表示沒有名字的物件
- 沒有參考的物件稱為匿名物件
- 匿名物件只能在創建物件時使用
- 如果一個物件只是用一次, 后面不需要用了, 可以考慮使用匿名物件
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();//通過匿名物件呼叫方法
}
}
// 執行結果
name:caocao age:19
重點:注意匿名物件是如何呼叫類中的方法的,
八、交換兩個數的值(實參交換)
代碼:
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());
}
}
運行結果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/341868.html
標籤:java
