首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 修飾符關鍵字全解析:訪問控制與非訪問修飾符詳解

     編輯:Java 相關知識

修飾符分類總覽

Java 修飾符分為兩大類:

  • 訪問控制修飾符:控制類、方法、字段的可見性
  • 非訪問修飾符:賦予特殊語義(靜態、最終、抽象、同步、易變)

一、訪問控制修飾符(四種)

修飾符同類同包子類(異包)非子類(異包)
public✓✓✓✓
protected✓✓✓✗
default (包私有)✓✓✗✗
private✓✗✗✗

代碼演示:包內外訪問差異


// mypackage/Person.java
package mypackage;
class Person { // default 類,僅包內可見
    private String name; // 僅本類可見
    protected void setName(String name) { this.name = name; } // 包內+子類可見
    public String getName() { return name; } // 任意處可見
}

// mypackage/Company.java
package mypackage;
public class Company { // public 類,任意處可見
    private List<Person> people = new ArrayList<>(); // 僅本類可見
    public void addPerson(String name) {
        Person p = new Person();
        p.setName(name); // 同包訪問 protected 方法 ✓
        people.add(p);
    }
}

// MainDriver.java (無包 / 異包)
import mypackage.*;
public class MainDriver {
    public static void main(String[] args) {
        Company c = new Company(); // public 類 ✓
        c.addPerson("Nic");        // public 方法 ✓
        
        Person p = new Person();   // 編譯錯誤:Person 是 default 類,異包不可見
        p.setName("Maria");        // 編譯錯誤:protected 方法,異包非子類不可見
    }
}

二、非訪問修飾符(五大核心)

1. static - 靜態成員

  • 屬於類而非實例,無需 new 即可調用
  • 靜態方法不可訪問非靜態成員,不可用 this/super
  • 靜態代碼塊類加載時執行一次,用於初始化

// 經典用法
int max = Integer.MAX_VALUE;        // 靜態常量
int num = Integer.parseInt("1234"); // 靜態工具方法

2. final - 最終/不可變

修飾目標效果
類不可被繼承(如 String、Integer)
方法不可被重寫(但可重載)
變量(基本類型)值不可修改(編譯期常量)
變量(引用類型)引用不可修改,但對象內部狀態可變

3. abstract - 抽象

  • 抽象類:不可實例化,可包含抽象/具體方法,子類必須實現所有抽象方法(或繼續聲明抽象)
  • 抽象方法:只有聲明無實現,以分號結尾

abstract class Shape {
    abstract double area(); // 強制子類實現
}

class Circle extends Shape {
    private double r;
    @Override double area() { return Math.PI * r * r; }
}

4. synchronized - 線程同步

  • 修飾方法/代碼塊,提供互斥鎖
  • 同步方法鎖對象:實例方法鎖 this,靜態方法鎖 Class 對象
  • 確保同一時刻只有一個線程執行同步代碼

// 同步方法
public synchronized void print(String s) {
    for (int i = 0; i < 5; i++) 
        System.out.println(s + ": " + i);
}

// 同步代碼塊(更精細控制鎖範圍)
public void print(String s) {
    synchronized (this) { // 或自定義鎖對象
        for (int i = 0; i < 5; i++) 
            System.out.println(s + ": " + i);
    }
}

5. volatile - 內存可見性

  • 保證變量對所有線程的可見性(讀取主內存,寫入主內存)
  • 禁止指令重排序(JMM happens-before 語義)
  • 不保證原子性(如 volatile int i; i++ 仍非線程安全)

public class ThreadExample {
    // 狀態標誌,volatile 確保線程間可見
    public static volatile boolean isActive = true;

    public static void main(String[] args) {
        new Thread(() -> {
            while (true) if (isActive) { System.out.println("T1"); isActive = false; }
        }).start();
        new Thread(() -> {
            while (true) if (!isActive) { System.out.println("T2"); isActive = true; }
        }).start();
    }
}

無 volatile 時,線程可能緩存舊值導致只交替一次;加上後正常交替打印。

修飾符組合規則速查

  • abstract 不能與 final、private、static 共存
  • interface 中方法隱含 public abstract,字段隱含 public static final
  • enum 隱含 final,不可繼承
  • 局部變量只能用 final(Java 8+ 可省略)

面試高頻考點

  1. protected vs default:子類異包可見性區別
  2. static 方法能否重寫?:不能,只能隱藏
  3. volatile 能否替代 synchronized?:不能,僅保證可見性不保證原子性
  4. final 引用類型「不可變」含義:引用不可變 ≠ 對象不可變
  5. 抽象類 vs 接口:Java 8+ 接口可有 default/static 方法,但仍無構造器/狀態

總結

修飾符是 Java 封裝、繼承、多態、並發的基石。建議:

  • 優先使用最小權限原則(private > default > protected > public)
  • 常量用 static final,工具方法用 static
  • 共享可變狀態優先考慮 synchronized/Lock,單純狀態標誌用 volatile
  • 設計繼承體系時合理使用 abstract/final 控制擴展性
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved