Java 面向對象-作用域

在Java中,我們經常看到publicprotectedprivate這些修飾符。在Java中,這些修飾符可以用來限定訪問作用域。

public

定義爲publicclassinterface可以被其他任何類訪問:

package abc;

public class Hello {
    public void hi() {
    }
}

上面的Hellopublic,因此,可以被其他包的類訪問:

package xyz;

class Main {
    void foo() {
        // Main可以訪問Hello
        Hello h = new Hello();
    }
}

定義爲publicfieldmethod可以被其他類訪問,前提是首先有訪問class的權限:

package abc;

public class Hello {
    public void hi() {
    }
}

上面的hi()方法是public,可以被其他類調用,前提是首先要能訪問Hello類:

package xyz;

class Main {
    void foo() {
        Hello h = new Hello();
        h.hi();
    }
}

 

private

定義爲privatefieldmethod無法被其他類訪問:

package abc;

public class Hello {
    // 不能被其他類調用:
    private void hi() {
    }

    public void hello() {
        this.hi();
    }
}

實際上,確切地說,private訪問權限被限定在class的內部,而且與方法聲明順序無關。推薦把private方法放到後面,因爲public方法定義了類對外提供的功能,閱讀代碼的時候,應該先關注public方法:

package abc;

public class Hello {
    public void hello() {
        this.hi();
    }

    private void hi() {
    }
}

由於Java支持嵌套類,如果一個類內部還定義了嵌套類,那麼,嵌套類擁有訪問private的權限:

public class Main {
    public static void main(String[] args) {
        Inner i = new Inner();
        i.hi();
    }

    // private方法:
    private static void hello() {
        System.out.println("private hello!");
    }

    // 靜態內部類:
    static class Inner {
        public void hi() {
            Main.hello();
        }
    }
}

輸出:

private hello!

定義在一個class內部的class稱爲嵌套類(nested class),Java支持好幾種嵌套類。

protected

protected作用於繼承關係。定義爲protected的字段和方法可以被子類訪問,以及子類的子類:

package abc;

public class Hello {
    // protected方法:
    protected void hi() {
    }
}

上面的protected方法可以被繼承的類訪問:

package xyz;

class Main extends Hello {
    void foo() {
        Hello h = new Hello();
        // 可以訪問protected方法:
        h.hi();
    }
}

package

最後,包作用域是指一個類允許訪問同一個package的沒有publicprivate修飾的class,以及沒有publicprotectedprivate修飾的字段和方法。

package abc;
// package權限的類:
class Hello {
    // package權限的方法:
    void hi() {
    }
}

只要在同一個包,就可以訪問package權限的classfieldmethod

package abc;

class Main {
    void foo() {
        // 可以訪問package權限的類:
        Hello h = new Hello();
        // 可以調用package權限的方法:
        h.hi();
    }
}

注意,包名必須完全一致,包沒有父子關係,com.apachecom.apache.abc是不同的包。

局部變量

在方法內部定義的變量稱爲局部變量,局部變量作用域從變量聲明處開始到對應的塊結束。方法參數也是局部變量。

package abc;

public class Hello {
    void hi(String name) { // ①
        String s = name.toLowerCase(); // ②
        int len = s.length(); // ③
        if (len < 10) { // ④
            int p = 10 - len; // ⑤
            for (int i=0; i<10; i++) { // ⑥
                System.out.println(); // ⑦
            } // ⑧
        } // ⑨
    } // ⑩
}

我們觀察上面的hi()方法代碼:

  • 方法參數name是局部變量,它的作用域是整個方法,即①~⑩;

  • 變量s的作用域是定義處到方法結束,即②~⑩;

  • 變量len的作用域是定義處到方法結束,即③~⑩;

  • 變量p的作用域是定義處到if塊結束,即⑤~⑨;

  • 變量i的作用域是for循環,即⑥~⑧。

使用局部變量時,應該儘可能把局部變量的作用域縮小,儘可能延後聲明局部變量。

final

Java還提供了一個final修飾符。final與訪問權限不衝突,它有很多作用。

final修飾class可以阻止被繼承:

package abc;

// 無法被繼承:
public final class Hello {
    private int n = 0;
    protected void hi(int t) {
        long i = t;
    }
}

final修飾method可以阻止被子類覆寫:

package abc;

public class Hello {
    // 無法被覆寫:
    protected final void hi() {
    }
}

final修飾field可以阻止被重新賦值:

package abc;

public class Hello {
    private final int n = 0;
    protected void hi() {
        this.n = 1; // error!
    }
}

final修飾局部變量可以阻止被重新賦值:

package abc;

public class Hello {
    protected void hi(final int t) {
        t = 1; // error!
    }
}

最佳實踐

如果不確定是否需要public,就不聲明爲public,即儘可能少地暴露對外的字段和方法。

把方法定義爲package權限有助於測試,因爲測試類和被測試類只要位於同一個package,測試代碼就可以訪問被測試類的package權限方法。

一個.java文件只能包含一個public類,但可以包含多個非public類。如果有public類,文件名必須和public類的名字相同。

小結

Java內建的訪問權限包括publicprotectedprivatepackage權限;

Java在方法內部定義的變量是局部變量,局部變量的作用域從變量聲明開始,到一個塊結束;

final修飾符不是訪問權限,它可以修飾classfieldmethod

一個.java文件只能包含一個public類,但可以包含多個非public類。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章