天天看點

JAVA的通路控制2-public,protected,private和package-private

作者:小朝的程式設計生涯

JAVA的通路控制2-public,protected,private和package-private

在前文JAVA的通路控制1-通路控制的必要性,包中介紹了通路控制的由來以及包的概念,本文将繼續介紹通路控制的關鍵字public,protected,private以及沒有關鍵字時預設的package-private。

這些關鍵字可以用于修飾字段,方法和内部類,另外,隻有public和預設的package-private可以用于外部類定義。

package-private預設權限

當字段等沒有任何修飾符時,就是預設權限,也就是包通路權限。包通路權限可以讓目前包的所有類進行調用,其他包的類則無法調用。

比如,類Persion在包org.xxx.model下,代碼如下:

package org.xxx;

public class Person {
    String name;

    String getName() {
        return name;
    }
}
           

那麼,同樣在包org.xxx.model下的其他類就可以通路到name字段和getName()方法,而其他包,比如org.xxx.util包下的類,就無法通路。

預設權限的一個用途是單元測試,被測試類中一些待測試字段和方法設定為預設權限,測試類可以友善地設定和調用。

大部分的方法都可以設定為包通路權限。

public

public關鍵字表示所有人都可以通路,通常是用于對外開放的方法上,如下所示:

package org.xxx.package1;

public class Formatter{
    public String describe() {
        return "formatter";
    }
}
           

Formatter的包是org.xxx,提供了一個describe()的方法,該方法可以被任何類調用。可以像下面這樣來使用:

package org.xxx.package2;

import org.xxx.package1.Formatter;

public class User{
    public String describeFormatter() {
        Formatter formatter = new Formatter();
        return formatter.describe();
    }
}
           

使用Formatter的類位于另一個包下面,是可以正常使用的。

一般而言,不建議public修飾字段,如果開放某個字段,可以提供對應的getter和setter方法,比如:

public class Person {
    // private修飾符 後面會提到
    private String name;

    public String getName() {
        return name;
    }

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

這個也叫java bean,是一種非常常見的使用方法。

public修飾字段一般是用于常量的聲明,比如一周有七天,很多地方需要使用這個資訊,就可以聲明一個常量public static final int DAYS_OF_WEEK = 7;,後面需要用這個數字進行計算的都使用DAYS_OF_WEEK常量來計算,可以使代碼比較清晰明了。

private

private關鍵字意味着這個方法/字段無法被其他類以正常方法(非正常方法指反射)通路,包括同一個包裡面的其他類,也無法通路。下面是一個樣例:

public class Constants {
    public static final int DAYS_OF_WEEK = 7;

    private Constants() {
    }
}
           

這個樣例中,private被用到了構造器上,說明這個類無法被其他類通過new Constants()的方法執行個體化,原因是這個類是用于定義常量的類,它本身不需要被執行個體化。上文提到的常量一般可以通過這種方式定義。

如果某個常量隻在一個類裡面使用,也可以直接定義在類内部,比如:

public class WeekUtil {
    private static final int DAYS_OF_WEEK = 7;

    public static int daysOfWeeks(int weekNum) {
        return DAYS_OF_WEEK * weekNum;
    }
}
           

daysOfWeeks(int weekNum)方法可以計算指定周數有多少天,這裡就使用private來定義了DAYS_OF_WEEK常量。

protected

protected修飾的内容可以被子類通路,無論子類在哪個包下都可以。

比如我們有一個類Animal在包org.example下,聲明了一個age字段:

package org.example;

public class Animal {
    protected int age;
}
           

有一個類Duck繼承了這個類,它在org.example.duck下:

package org.example;
import org.example.Animal;

public class Duck extends Animal{
    public int ageOfDuck(){
        return age;
    }
}
           

在Duck中是可以自由使用age字段的。

package-private與protected

這兩種權限很容易混淆,在使用時,可以分開來看。**兩種權限是互相獨立的,隻要滿足其中一條就可以通路到。**比如上文的類Animal,加了個字段:

package org.example;

public class Animal {
    protected int age;
    String name;
}
           

子類在org.example包裡面時,包權限生效,name可以被通路到,子類不在org.example裡面時,隻能通路到age。同一個包裡面的其他類,隻能通路到name字段。

繼續閱讀