第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程

Java 封裝

上一小節(jié)中,我們已經(jīng)對(duì)類和對(duì)象有了一個(gè)基本的認(rèn)識(shí)。不止于 Java,在各個(gè)面向?qū)ο笳Z言的書籍資料中,都會(huì)提到面向?qū)ο蟮娜筇卣鳎?strong>封裝、繼承、多態(tài)。本小節(jié)我們就從封裝開始,探討面向?qū)ο蟮奶卣鳌1拘」?jié)我們將學(xué)習(xí)什么是封裝、為什么需要封裝,最后也會(huì)以一個(gè) NBA 球員類的案例來實(shí)現(xiàn)封裝。

1. 概念和特點(diǎn)

類的基本作用就是封裝代碼。封裝將類的一些特征和行為隱藏在類內(nèi)部,不允許類外部直接訪問。

封裝可以被認(rèn)為是一個(gè)保護(hù)屏障,防止該類的代碼和數(shù)據(jù)被外部類定義的代碼隨機(jī)訪問。

我們可以通過類提供的方法來實(shí)現(xiàn)對(duì)隱藏信息的操作和訪問。隱藏了對(duì)象的信息,留出了訪問的接口。

在我們?nèi)粘I钪校庋b與我們息息相關(guān),智能手機(jī)就是一個(gè)擁有良好封裝的例子,我們不需要關(guān)心其內(nèi)部復(fù)雜的邏輯電路設(shè)計(jì),可以通過手機(jī)的屏幕、按鍵、充電口、耳機(jī)接口等等外部接口來對(duì)手機(jī)進(jìn)行操作和使用。復(fù)雜的邏輯電路以及模塊被封裝在手機(jī)的內(nèi)部,而留出的這些必要接口,讓我們更加簡(jiǎn)便地使用手機(jī)的同時(shí)也保護(hù)了手機(jī)的內(nèi)部細(xì)節(jié)。

封裝有兩個(gè)特點(diǎn):

  1. 只能通過規(guī)定的方法訪問數(shù)據(jù);
  2. 隱藏類的實(shí)例細(xì)節(jié),方便修改和實(shí)現(xiàn)。

2. 為什么需要封裝

封裝具有以下優(yōu)點(diǎn):

  • 封裝有利于提高類的內(nèi)聚性,適當(dāng)?shù)姆庋b可以讓代碼更容易理解與維護(hù);
  • 良好的封裝有利于降低代碼的耦合度;
  • 一些關(guān)鍵屬性只允許類內(nèi)部可以訪問和修改,增強(qiáng)類的安全性;
  • 隱藏實(shí)現(xiàn)細(xì)節(jié),為調(diào)用方提供易于理解的接口;
  • 當(dāng)需求發(fā)生變動(dòng)時(shí),我們只需要修改我們封裝的代碼,而不需要到處修改調(diào)用處的代碼。

3. 實(shí)現(xiàn)封裝

在 Java 語言中,如何實(shí)現(xiàn)封裝呢?需要 3 個(gè)步驟。

  1. 修改屬性的可見性為private;
  2. 創(chuàng)建公開的 getter 和 setter 方法,分別用于屬性的讀寫;
  3. 在 getter 和 setter 方法中,對(duì)屬性的合法性進(jìn)行判斷。

我們來看一個(gè) NBA 球員類NBAPlayer

class NBAPlayer {
    // 姓名
    String name;
    // 年齡
    int age;
}

類內(nèi)部(即類名后面{}之間的區(qū)域)定義了成員屬性nameage,我們知道,在類外部調(diào)用處可以對(duì)其屬性進(jìn)行修改:

NBAPlayer player = new NBAPlayer();
player.age = -1;

如下是實(shí)例代碼:

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
public class NBAPlayer {
    // 姓名
    String name;
    // 年齡
    int age;

    public static void main(String[] args) {
        NBAPlayer player = new NBAPlayer();
        player.age = -1;
        System.out.println("球員年齡為:" + player.age);
    }
}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

運(yùn)行結(jié)果:

球員年齡為:-1

我們通過對(duì)象名.屬性名的方式對(duì)age賦值為 -1,顯然,球員的年齡為-1是反常理的。

下面我們對(duì)NBAPlayer類進(jìn)行封裝。

  1. 我們可以使用私有化訪問控制符修飾類內(nèi)部的屬性,讓其只在類的內(nèi)部可以訪問:
// 用private修飾成員屬性,限定只能在當(dāng)前類內(nèi)部可以訪問
private String name;
private int age;

private關(guān)鍵字限定了其修飾的成員只能在類內(nèi)部訪問,這樣之后就無法在類外部使用player.age =-1這樣的賦值方式進(jìn)行賦值了。

  1. 創(chuàng)建公開的(public) gettersetter方法:
// 通常以get+屬性名的方式命名 getter,返回對(duì)應(yīng)的私有屬性
public String getName() {
  	return name;
}

// 通常以set+屬性名的方式命名 setter,給對(duì)應(yīng)屬性進(jìn)行賦值
public void setName(String name) {
  	this.name = name;
}

public int getAge() {
  	return age;
}

public void setAge(int age) {
  	this.age = age;
}

顧名思義,getter就是取屬性值,setter就是給屬性賦值,這樣在類的外部就可以通過調(diào)用其方法對(duì)屬性進(jìn)行操作了。

  1. 對(duì)屬性進(jìn)行邏輯判斷,以age屬性的setter方法為例:
public void setAge(int age) {
  	// 判斷參數(shù)age的合法性
  	if(age < 0) {
      	this.age = 0;
    } else {
	  	this.age = age;
  	}
}

setAge方法中,我們將參數(shù)age小于 0 的情況進(jìn)行了處理,如果小于 0,直接將age賦值為0。除了給默認(rèn)值的方式,我們也可以拋出異常,提示調(diào)用方傳參不合法。

在類外部對(duì)屬性進(jìn)行讀寫:

NBAPlayer player = new NBAPlayer();
// 對(duì)屬性賦值:
player.setName("詹姆斯");
player.setAge(35);
// 獲取屬性:
System.out.println("姓名:" + player.getName());
System.out.println("年齡:" + player.getAge());

試想,如果在類外部,有很多地方都會(huì)操作屬性值,當(dāng)屬性值讀寫邏輯發(fā)生改變時(shí),我們只需修改類內(nèi)部的邏輯。

另外,對(duì)于有參構(gòu)造方法中,對(duì)屬性賦值時(shí),直接調(diào)用其setter方法。無需再寫重復(fù)的邏輯判斷,提高代碼復(fù)用性:

public NBAPlayer(int age) {
  	this.setAge(age);
}

如下是實(shí)現(xiàn)封裝后完整實(shí)例代碼:

實(shí)例演示
預(yù)覽 復(fù)制
復(fù)制成功!
public class NBAPlayer {
    // 姓名
    private String name;
    // 年齡
    private int age;

    // 無參構(gòu)造方法
    public NBAPlayer() {

    }

    // 單參構(gòu)造方法
    public NBAPlayer(int age) {
        this.setAge(age);
    }

    // 全參構(gòu)造方法
    public NBAPlayer(String name, int age) {
        this.setName(name);
        this.setAge(age);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        // 判斷參數(shù)age的合法性
        if(age < 0) {
            this.age = 0;
        }
        this.age = age;
    }

    public static void main(String[] args) {
        NBAPlayer james = new NBAPlayer();
        // 對(duì)屬性賦值:
        james.setName("詹姆斯");
        james.setAge(35);
        // 打印james實(shí)例屬性
        System.out.println("姓名:" + james.getName());
        System.out.println("年齡:" + james.getAge());
        System.out.println("-------------");
        // 實(shí)例化一個(gè)新的對(duì)象
        NBAPlayer jordan = new NBAPlayer("喬丹", 60);
        // 打印jordan對(duì)象實(shí)例屬性
        System.out.println("姓名:" + jordan.getName());
        System.out.println("年齡:" + jordan.getAge());
    }
}
運(yùn)行案例 點(diǎn)擊 "運(yùn)行案例" 可查看在線運(yùn)行效果

運(yùn)行結(jié)果:

姓名:詹姆斯
年齡:35
-------------
姓名:?jiǎn)痰?年齡:60

4. 小結(jié)

面向?qū)ο蟮娜筇卣鳎?strong>封裝、繼承、多態(tài)。

封裝隱藏了對(duì)象的信息,并且留出了訪問的接口。