Java封裝

在面向?qū)ο蟪淌皆O(shè)計方法中,封裝(Encapsulation)是指一種將抽象性函式接口的實(shí)現(xiàn)細(xì)節(jié)部分包裝捅彻、隱藏起來的方法。
封裝可以被認(rèn)為是一個保護(hù)屏障、防止該類的代碼和數(shù)據(jù)被外部類定義的代碼隨機(jī)訪問凛剥。
要訪問該類的代碼和數(shù)據(jù),必須通過嚴(yán)格的接口控制轻姿。
封裝的主要的功能在于我們能修改自己的實(shí)現(xiàn)代碼犁珠,而不用修改那些調(diào)用我們代碼的程序片段。
適當(dāng)?shù)姆庋b可以讓程式碼更容易理解與維護(hù)互亮,也將強(qiáng)了程式碼的安全性犁享。

封裝的優(yōu)點(diǎn)

  • 良好的封裝能夠減少耦合
  • 類內(nèi)部的結(jié)構(gòu)可以自由修改
  • 可以對成員變量進(jìn)行更精確的控制
  • 隱藏信息,實(shí)現(xiàn)細(xì)節(jié)

實(shí)現(xiàn)Java的封裝

  • 修改屬性的可見性來限制對屬性的訪問(一般限制為private)豹休,例如:
public class Person {
        private String name;
        private int age;
}

這段代碼中炊昆,將name和age屬性設(shè)置為私有的,只能本類才能訪問威根,其它類都訪問不了凤巨,如此就對信息進(jìn)行了隱藏。

  • 對每個值屬性提供對外的公共方法訪問洛搀,也就是創(chuàng)建一對賦值方法敢茁,用于對私有屬性的訪問,例如:
public class Person{
    private String name;
    private int age;
?
    public int getAge(){
      return age;
    }
?
    public String getName(){
      return name;
    }
?
    public void setAge(int age){
      this.age = age;
    }
?
    public void setName(String name){
      this.name = name;
    }
}

采用this關(guān)鍵字是為了解決實(shí)例變量(private String name)和局部變量(setName(String name)中的name變量)之間發(fā)生的同名的沖突姥卢。

讓我們來看一個Java封裝類的例子:

/* 文件名: EncapTest.java */
public class EncapTest{
 
   private String name;
   private String idNum;
   private int age;
 
   public int getAge(){
      return age;
   }
 
   public String getName(){
      return name;
   }
 
   public String getIdNum(){
      return idNum;
   }
 
   public void setAge( int newAge){
      age = newAge;
   }
 
   public void setName(String newName){
      name = newName;
   }
 
   public void setIdNum( String newId){
      idNum = newId;
   }
}

以上實(shí)例中public方法是外部類訪問該類成員變量的入口卷要。
通常情況下渣聚,這些方法被稱為getter和setter方法。
因此僧叉,任何要訪問類中私有成員變量的類都要通過這些getter和setter方法奕枝。
通過如下的例子說明EncapTest類的變量怎樣被訪問:

/* F文件名 : RunEncap.java */
public class RunEncap{
   public static void main(String args[]){
      EncapTest encap = new EncapTest();
      encap.setName("James");
      encap.setAge(20);
      encap.setIdNum("12343ms");
 
      System.out.print("Name : " + encap.getName()+ 
                             " Age : "+ encap.getAge());
    }
}

以上代碼編譯運(yùn)行結(jié)果如下:

Name : James Age : 20

有時候在封裝的時候會遇到這樣的問題,就是我們的類名可能是重復(fù)的瓶堕。為了更好地組織類隘道,Java提供了包機(jī)制,用于區(qū)別類名的命名空間郎笆。

包的作用

  • 把功能相似或相關(guān)的類或接口組織在同一個包中谭梗,方便類的查找和使用。
  • 包采用了樹形目錄的存儲方式宛蚓。同一個包中的類名字是不同激捏,不同的包中的類的名字是可以相同的,當(dāng)同時調(diào)用兩個不同包中相同類名的類時凄吏,應(yīng)該加上包名加以區(qū)別远舅。
  • 包也限定了訪問權(quán)限,擁有包訪問權(quán)限的類才能訪問某個包中的類痕钢。

定義包語法

package 包名
//注意:必須放在源程序的第一行图柏,包名可用"."號隔開

例如:

//我們在定義文件夾的時候利用"/"來區(qū)分層次
//包中我們用"."來分層
package com.shiyanlou.Java 

不僅是我們這樣利用包名來區(qū)分類,系統(tǒng)也是這樣做的任连。

系統(tǒng)中的包
java.(功能).(類)
java.lang.(類) 包含java語言基礎(chǔ)的類
java.util.(類) 包含java語言中各種工具類
java.io.(類) 包含輸入蚤吹、輸出相關(guān)功能的類

那我們怎么在不同包中使用另一個文件中的類呢?這時候就需要用到import關(guān)鍵字随抠。比如我們要導(dǎo)入實(shí)驗樓下People這個類裁着。import com.shiyanlou.People,同時如果import com.shiyanlou.*這是將包下的所有文件都導(dǎo)入進(jìn)來暮刃,*是通配符跨算。
這里要注意一點(diǎn),包的命名規(guī)則是全小寫字母拼寫椭懊。

訪問修飾符

我們在前面的代碼中經(jīng)常用到privatepublic修飾符,這些修飾符的作用和意義是什么呢步势?接下來我們就來學(xué)習(xí)Java中的訪問修飾符氧猬。
訪問修飾符可以用來修飾屬性和方法的訪問范圍。

訪問修飾符 本類 同包 子類 其它
private
默認(rèn)
protected
public

如圖所示坏瘩,代表了不同的訪問能修飾符的訪問范圍盅抚,比如 private 修飾符的屬性或者方法,只能在當(dāng)前類中中訪問或者使用倔矾。默認(rèn)是什么修飾符都不加妄均,默認(rèn)在當(dāng)前類中和同一包下都可以訪問和使用柱锹。protected修飾的屬性或者方法,對同一包內(nèi)的類和所有子類可見丰包。public修飾的屬性或者方法禁熏,對所有類可見。
我們可以舉一個例子邑彪,比如 money瞧毙,如果我們用private修飾代表著這是私有的,只能我自己可以使用寄症。如果是protected代表著我可以使用宙彪,和我有關(guān)系的人,比如兒子也可以用有巧。如果是public就代表了所有人都可以使用释漆。

內(nèi)部類

可以將一個類的定義放在另一個類的定義內(nèi)部,這就是內(nèi)部類篮迎。而包含內(nèi)部類的類被稱為外部類灵汪。
內(nèi)部類的主要作用如下:

  • 內(nèi)部類提供了更好的封裝,可以把內(nèi)部類隱藏在外部類之內(nèi)柑潦,不允許同一個包中的其它類訪問該類
  • 內(nèi)部類的方法可以直接訪問外部類的所有數(shù)據(jù)享言,包括私有的數(shù)據(jù)
  • 內(nèi)部類所實(shí)現(xiàn)的功能使用外部類同樣可以實(shí)現(xiàn),只是有時使用內(nèi)部類更方便
  • 內(nèi)部類允許繼承多個非接口類型

注意:內(nèi)部類是編譯時的概念渗鬼,一旦編譯成功览露,就會稱為完全不同的兩類。對于一個名為outer的外部類和其內(nèi)部定義的名為inner的內(nèi)部類譬胎。編譯完成后出現(xiàn)outer.class和outer$inner.class兩類差牛。所以內(nèi)部類的成員變量/方法名可以和外部類的相同。

我們通過代碼來詳細(xì)學(xué)習(xí)以下內(nèi)部類把堰乔!

成員內(nèi)部類

ackage com.shiyanlou;

//外部類People
public class People {
    private String name = "LiLei";         //外部類的私有屬性
    //內(nèi)部類Student
    public class Student {
        String ID = "20151234";               //內(nèi)部類的成員屬性
        //內(nèi)部類的方法
        public void stuInfo(){
            System.out.println("訪問外部類中的name:" + name);
            System.out.println("訪問內(nèi)部類中的ID:" + ID);
        }
    }

    //測試成員內(nèi)部類
    public static void main(String[] args) {
        People a = new People();     //創(chuàng)建外部類對象偏化,對象名為a
        Student b = a.new Student(); //使用外部類對象創(chuàng)建內(nèi)部類對象,對象名為b
        // 或者為 People.Student b = a.new Student();
        b.stuInfo();   //調(diào)用內(nèi)部對象的suInfo方法
    }
}

由此镐侯,我們可以直到侦讨,成員內(nèi)部類的使用方法:

  • Student 類相當(dāng)于 People 類的一個成員變量,所以 Student 類可以使用任意訪問修飾符苟翻。
  • Student 類在 People 類里韵卤,所以訪問范圍在類里的所有方法均可以訪問 People 的屬性(即內(nèi)部類里可以直接訪問外部類的方法和屬性,反之不行)
  • 定義成員內(nèi)部類后崇猫,必須使用外部類對象來創(chuàng)建內(nèi)部類對象沈条,即內(nèi)部類 對象名 = 外部類對象.new 內(nèi)部類();
  • 如果外部類和內(nèi)部類具有相同的成員變量或方法,內(nèi)部類默認(rèn)訪問自己的成員變量或方法诅炉,如果要訪問外部類的成員變量蜡歹,可以使用 this 關(guān)鍵字 加上述代碼中:a.this

注:成員內(nèi)部類不能含有static的變量和方法屋厘,因為成員內(nèi)部類需要先創(chuàng)建了外部類,才能創(chuàng)建它自己的月而。

靜態(tài)內(nèi)部類

靜態(tài)內(nèi)部類通常被稱為嵌套類汗洒。

package com.shiyanlou;

//外部類People
public class People {
    private String name = "LiLei";         //外部類的私有屬性

/*外部類的靜態(tài)變量。
Java 中被 static 修飾的成員稱為靜態(tài)成員或類成員景鼠。它屬于整個類所有仲翎,而不是某個對象所有,即被類的所有對象所共享铛漓。靜態(tài)成員可以使用類名直接訪問溯香,也可以使用對象名進(jìn)行訪問。
*/
    static String ID = "510xxx199X0724XXXX"; 

    //靜態(tài)內(nèi)部類Student
    public static class Student {
        String ID = "20151234";               //內(nèi)部類的成員屬性
        //內(nèi)部類的方法
        public void stuInfo(){
            System.out.println("訪問外部類中的name:" + (new People().name));
            System.out.println("訪問外部類中的ID:" + People.ID);
            System.out.println("訪問內(nèi)部類中的ID:" + ID);
        }
    }

    //測試成員內(nèi)部類
    public static void main(String[] args) {
        Student b = new Student();   //直接創(chuàng)建內(nèi)部類對象浓恶,對象名為b
        b.stuInfo();                 //調(diào)用內(nèi)部對象的suInfo方法
    }
}

以上代碼編譯運(yùn)行結(jié)果如下:

訪問內(nèi)外部類中的name:LiLei
訪問外部類中的ID:510xxx199X0724XXXX
訪問內(nèi)部類中的ID:20151234

靜態(tài)內(nèi)部類是static修飾的內(nèi)部類玫坛,這種內(nèi)部類的特點(diǎn)是:

  • 靜態(tài)內(nèi)部類不能直接訪問外部類的非靜態(tài)成員,但可以通過 new 外部類().成員的方式訪問
  • 如果外部類的靜態(tài)成員與內(nèi)部類的成員名稱相同包晰,可通過類名.靜態(tài)成員訪問外部類的靜態(tài)成員湿镀;如果外部類的靜態(tài)成員與內(nèi)部類的成員名稱不相同,則可通過成員名直接調(diào)用外部類的靜態(tài)成員
  • 創(chuàng)建靜態(tài)內(nèi)部類的對象時伐憾,不需要外部類的對象勉痴,可以直接創(chuàng)建內(nèi)部類 對象名=new 內(nèi)部類();

局部內(nèi)部類

局部內(nèi)部類,是指內(nèi)部類定義在方法和作用域內(nèi)树肃。
例如:

package com.shiyanlou;

//外部類People
public class People {    
    //定義在外部類中的方法內(nèi):
    public void peopleInfo() {
        final String sex = "man";  //外部類方法中的常量
        class Student {
            String ID = "20151234"; //內(nèi)部類中的常量
            public void print() {
                System.out.println("訪問外部類的方法中的常量sex:" + sex);
                System.out.println("訪問內(nèi)部類中的變量ID:" + ID);
            }
        }
        Student a = new Student();  //創(chuàng)建方法內(nèi)部類的對象
        a.print();//調(diào)用內(nèi)部類的方法
    }
    //定義在外部類中的作用域內(nèi)
    public void peopleInfo2(boolean b) {
        if(b){
            final String sex = "man";  //外部類方法中的常量
            class Student {
                String ID = "20151234"; //內(nèi)部類中的常量
                public void print() {
                    System.out.println("訪問外部類的方法中的常量sex:" + sex);
                    System.out.println("訪問內(nèi)部類中的變量ID:" + ID);
                }
            }
            Student a = new Student();  //創(chuàng)建方法內(nèi)部類的對象
            a.print();//調(diào)用內(nèi)部類的方法
        }
    }
    //測試方法內(nèi)部類
    public static void main(String[] args) {
        People b = new People(); //創(chuàng)建外部類的對象
        System.out.println("定義在方法內(nèi):===========");
        b.peopleInfo();  //調(diào)用外部類的方法
        System.out.println("定義在作用域內(nèi):===========");
        b.peopleInfo2(true);
    }
}

以上編譯運(yùn)行結(jié)果如下:

定義在方法內(nèi):===========
訪問外部類的方法中的常量sex:man
訪問內(nèi)部類中的變量ID:20151234
定義在作用域內(nèi):===========
訪問外部類的方法中的常量sex:man
訪問內(nèi)部類中的變量ID:20151234

局部內(nèi)部類也像別的類一樣進(jìn)行編譯蒸矛,但只是作用域不同而已,只在該方法或條件的作用域內(nèi)才能使用胸嘴,退出這些作用域后無法引用的雏掠。

匿名內(nèi)部類

匿名內(nèi)部類,顧名思義劣像,就是沒有名字的內(nèi)部類乡话。正因為沒有名字,所有匿名內(nèi)部類只能使用一次耳奕,它通常用來簡化代碼編寫绑青。但使用匿名內(nèi)部類還有個前提條件:必須繼承一個父類或?qū)崿F(xiàn)一個接口。
例如:

public class Outer { 

    public Inner getInner(final String name, String city) { 
        return new Inner() { 
            private String nameStr = name; 
            public String getName() { 
                return nameStr; 
            } 
        };
    } 

    public static void main(String[] args) { 
        Outer outer = new Outer(); 
        Inner inner = outer.getInner("Inner", "NewYork"); 
        System.out.println(inner.getName()); 
    } 
} 
interface Inner { 
    String getName(); 
}

以上代碼編譯運(yùn)行結(jié)果如下:

Inner

匿名內(nèi)部類是不能加訪問修飾符的吮铭。要注意的是时迫,new 匿名類,這個類是要先定義的谓晌,如果不限定義,編譯時會報錯該類找不到癞揉。
同時纸肉,在上面的例子中溺欧,當(dāng)所在的方法的形參需要在內(nèi)部類里面使用時,該形參必須為final柏肪。這里可以看到形參 name 已經(jīng)定義為 final 了姐刁,而形參 city 沒有被使用則不用定義為 final。
然而烦味,因為匿名內(nèi)部類沒名字聂使,是用默認(rèn)的構(gòu)造函數(shù)的,無參數(shù)的谬俄,如果需要該類有帶參數(shù)的構(gòu)造函數(shù)柏靶,示例如下:

public Inner getInner(final String name, String city) { 
        return new Inner(name, city) { 
            private String nameStr = name; 

            public String getName() { 
                return nameStr; 
            } 
        }; 
    } 

注意這里的形參 city,由于它沒有被匿名內(nèi)部類直接使用溃论,而是被抽象類 Inner 的構(gòu)造函數(shù)所使用屎蜓,所以不必定義為 final。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钥勋,一起剝皮案震驚了整個濱河市炬转,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌算灸,老刑警劉巖扼劈,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異菲驴,居然都是意外死亡荐吵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門谢翎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捍靠,“玉大人,你說我怎么就攤上這事森逮≌テ牛” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵褒侧,是天一觀的道長良风。 經(jīng)常有香客問我,道長闷供,這世上最難降的妖魔是什么烟央? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮歪脏,結(jié)果婚禮上疑俭,老公的妹妹穿的比我還像新娘。我一直安慰自己婿失,他們只是感情好钞艇,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布啄寡。 她就那樣靜靜地躺著,像睡著了一般哩照。 火紅的嫁衣襯著肌膚如雪挺物。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天飘弧,我揣著相機(jī)與錄音识藤,去河邊找鬼。 笑死次伶,一個胖子當(dāng)著我的面吹牛痴昧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播学少,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼剪个,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了版确?” 一聲冷哼從身側(cè)響起扣囊,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绒疗,沒想到半個月后侵歇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吓蘑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年惕虑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磨镶。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡溃蔫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出琳猫,到底是詐尸還是另有隱情伟叛,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布脐嫂,位于F島的核電站统刮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏账千。R本人自食惡果不足惜侥蒙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匀奏。 院中可真熱鬧鞭衩,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽会放。三九已至饲齐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咧最,已是汗流浹背捂人。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留矢沿,地道東北人滥搭。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像捣鲸,于是被迫代替她去往敵國和親瑟匆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 一栽惶、Java 簡介 Java是由Sun Microsystems公司于1995年5月推出的Java面向?qū)ο蟪绦蛟O(shè)計...
    子非魚_t_閱讀 4,154評論 1 44
  • 一.成員變量與局部變量的區(qū)別 成員變量:在類中定義愁溜,用來描述對象將要有什么(屬性)⊥獬В可被本類方法和其他跟當(dāng)前類有關(guān)...
    jeffierw閱讀 540評論 0 0
  • 哪里有什么靠譜的人冕象,只不過是功利心不夠強(qiáng)罷了。 最近和一些人合作汁蝶,他們的處事行為實(shí)在太不靠譜渐扮,深感失望,心累至極掖棉。...
    至善福閱讀 368評論 0 0
  • 感情自由: 想要達(dá)到感情的自由幔亥,首先就是要看到耻讽,自己的存在感是刷在什么地方。通常比較不會出問題的是事業(yè)紫谷、宗教信仰(...
    Sarah瀟瀟閱讀 398評論 0 0
  • 還記得去年高調(diào)上市的網(wǎng)易味央豬肉么捺僻?最近,丁磊又出來搞事了,這次要上線一個全民養(yǎng)豬眾籌計劃匕坯,眾籌的價格不等束昵,共分1...
    氪星情報局閱讀 226評論 0 0