欢迎光临
我们一直在努力

Java 类级成员修饰符详解

一、四大访问权限修饰符(控制可见范围)

Java 一共有 4 个访问修饰符,用来限制类的成员(变量、方法)在不同位置能否被访问,权限范围从大到小排序:

1. public(公共的)

  • 修饰范围:可以修饰类、成员变量、成员方法。
  • 访问权限:任何包、任何类中都能直接访问。
  • 特点:权限最大,无访问限制。
  • 使用场景:对外提供的接口方法、需要全局访问的成员。

// 示例:public 修饰符在不同包/子类中的访问情况
// com.example.package1
package com.example.package1;

public class PublicExample {
public String publicField = "公共字段";
public void publicMethod() {
System.out.println("公共方法");
}
}

// com.example.package2
package com.example.package2;

import com.example.package1.PublicExample;

public class TestPublic {
public void test() {
PublicExample example = new PublicExample();
System.out.println(example.publicField); // ✅ 可以访问
example.publicMethod(); // ✅ 可以访问
}
}

// com.example.package2 的子类
package com.example.package2;

import com.example.package1.PublicExample;

public class SubClass extends PublicExample {
public void test() {
System.out.println(publicField); // ✅ 可以访问(继承)
publicMethod(); // ✅ 可以访问(继承)
}
}

2. protected(受保护的)

  • 修饰范围:只能修饰成员变量、成员方法,不能修饰普通类。
  • 访问权限:
  • 本类内部可以访问。
  • 同一个包下的类可以访问。
  • 不同包的子类可以继承访问。
  • 使用场景:希望子类继承、但不想对外公开的成员。

// 示例:protected 修饰符在不同包/子类中的访问情况
// com.example.package1
package com.example.package1;

public class ProtectedExample {
protected String protectedField = "受保护字段";
protected void protectedMethod() {
System.out.println("受保护方法");
}

public void testInSameClass() {
System.out.println(protectedField); // ✅ 本类可以访问
protectedMethod(); // ✅ 本类可以访问
}
}

// com.example.package1 的同包类
package com.example.package1;

public class SamePackageClass {
public void test() {
ProtectedExample example = new ProtectedExample();
System.out.println(example.protectedField); // ✅ 同包类可以访问
example.protectedMethod(); // ✅ 同包类可以访问
}
}

// com.example.package2 的子类
package com.example.package2;

import com.example.package1.ProtectedExample;

public class SubClass extends ProtectedExample {
public void test() {
System.out.println(protectedField); // ✅ 不同包子类可以访问(继承)
protectedMethod(); // ✅ 不同包子类可以访问(继承)
}
}

// com.example.package2 的非子类(无法访问)
package com.example.package2;

import com.example.package1.ProtectedExample;

public class OtherPackageClass {
public void test() {
ProtectedExample example = new ProtectedExample();
// System.out.println(example.protectedField); // ❌ 编译错误:不同包非子类不能访问
// example.protectedMethod(); // ❌ 编译错误:不同包非子类不能访问
}
}

3. 默认权限(缺省 / 包访问权限)

  • 写法:不写任何修饰符。
  • 访问权限:只有同一个包内的类可以访问,跨包无论是否是子类都无法访问。
  • 特点:介于 protected 和 private 之间,日常开发很少主动使用。

// 示例:默认权限在不同包/子类中的访问情况
// com.example.package1
package com.example.package1;

public class DefaultExample {
String defaultField = "默认权限字段"; // 没有修饰符,即默认权限
void defaultMethod() {
System.out.println("默认权限方法");
}

public void testInSameClass() {
System.out.println(defaultField); // ✅ 本类可以访问
defaultMethod(); // ✅ 本类可以访问
}
}

// com.example.package1 的同包类
package com.example.package1;

public class SamePackageClass {
public void test() {
DefaultExample example = new DefaultExample();
System.out.println(example.defaultField); // ✅ 同包类可以访问
example.defaultMethod(); // ✅ 同包类可以访问
}
}

// com.example.package2 的子类(无法访问)
package com.example.package2;

import com.example.package1.DefaultExample;

public class SubClass extends DefaultExample {
public void test() {
// System.out.println(defaultField); // ❌ 编译错误:不同包子类不能访问默认权限成员
// defaultMethod(); // ❌ 编译错误:不同包子类不能访问默认权限方法
}
}

// com.example.package2 的非子类(无法访问)
package com.example.package2;

import com.example.package1.DefaultExample;

public class OtherPackageClass {
public void test() {
DefaultExample example = new DefaultExample();
// System.out.println(example.defaultField); // ❌ 编译错误:不同包类不能访问
// example.defaultMethod(); // ❌ 编译错误:不同包类不能访问
}
}

4. private(私有的)

  • 修饰范围:只能修饰成员变量、成员方法,不能修饰类。
  • 访问权限:仅当前类内部可以访问,子类、同包类、外部类全都不能直接访问。
  • 使用场景:封装成员变量,配合 get/set 方法取值赋值,是 Java 封装思想的核心。

// 示例:private 修饰符在不同包/子类中的访问情况
// com.example.package1
package com.example.package1;

public class PrivateExample {
private String privateField = "私有字段";
private void privateMethod() {
System.out.println("私有方法");
}

// 提供公共访问方法(封装)
public String getPrivateField() {
return privateField;
}

public void setPrivateField(String value) {
this.privateField = value;
}

public void callPrivateMethod() {
privateMethod(); // ✅ 本类可以访问私有方法
}

public void testInSameClass() {
System.out.println(privateField); // ✅ 本类可以访问
privateMethod(); // ✅ 本类可以访问
}
}

// com.example.package1 的同包类(无法访问)
package com.example.package1;

public class SamePackageClass {
public void test() {
PrivateExample example = new PrivateExample();
// System.out.println(example.privateField); // ❌ 编译错误:同包类不能访问私有成员
// example.privateMethod(); // ❌ 编译错误:同包类不能访问私有方法

// 只能通过公共方法访问
System.out.println(example.getPrivateField()); // ✅ 通过getter访问
example.callPrivateMethod(); // ✅ 通过公共方法间接调用私有方法
}
}

// com.example.package2 的子类(无法访问)
package com.example.package2;

import com.example.package1.PrivateExample;

public class SubClass extends PrivateExample {
public void test() {
// System.out.println(privateField); // ❌ 编译错误:子类不能访问父类私有成员
// privateMethod(); // ❌ 编译错误:子类不能访问父类私有方法

// 只能通过继承的公共方法访问
System.out.println(getPrivateField()); // ✅ 通过继承的getter访问
callPrivateMethod(); // ✅ 通过继承的公共方法间接调用
}
}

// com.example.package2 的非子类(无法访问)
package com.example.package2;

import com.example.package1.PrivateExample;

public class OtherPackageClass {
public void test() {
PrivateExample example = new PrivateExample();
// System.out.println(example.privateField); // ❌ 编译错误:外部类不能访问
// example.privateMethod(); // ❌ 编译错误:外部类不能访问

// 只能通过公共方法访问
System.out.println(example.getPrivateField()); // ✅ 通过公共getter访问
example.callPrivateMethod(); // ✅ 通过公共方法间接调用
}
}

访问权限范围对照表

修饰符本类同包类不同包子类任意外部类
public
protected
默认(缺省)
private

二、非访问修饰符(不控制权限,修改特性)

1. static(静态修饰符)

  • 修饰成员变量:
    • 变成静态变量(类变量),不属于对象,属于整个类。
    • 内存只加载一次,所有对象共享同一份数据。
    • 调用方式:类名.变量名(推荐)、对象名.变量名。
  • 修饰成员方法:
    • 变成静态方法(类方法),可以直接用类名调用。
    • 静态方法不能直接访问非静态成员变量、非静态方法,因为静态优先加载,此时对象还未创建。
    • 静态方法中不能使用 this、super 关键字。
  • 使用场景:工具方法、全局共享常量、计数变量。

2. final(最终修饰符)

  • 修饰成员变量:
    • 变量变成常量,赋值后无法修改。
    • 成员常量必须手动初始化:要么定义时直接赋值,要么在构造方法中赋值。
  • 修饰成员方法:
    • 方法不能被子类重写(覆写)。
  • 修饰类:
    • 类不能被继承。

3. abstract(抽象修饰符)

  • 只能修饰方法和类,不能修饰变量。
  • 修饰方法:抽象方法,只有方法声明,没有方法体,必须放在抽象类中。
  • 修饰类:抽象类,不能 new 创建对象,用来被子类继承,强制子类实现抽象方法。

⚠️ 注意:abstract 和 final 不能同时修饰一个方法,抽象方法需要子类重写,final 禁止重写,二者矛盾。

4. transient(瞬态修饰符)

  • 仅修饰成员变量。
  • 作用:Java 序列化时,被 transient 修饰的变量不会被保存到文件中。

5. volatile(易变修饰符)

  • 仅修饰成员变量,多线程并发编程使用。
  • 作用:保证变量在多线程下的可见性,禁止指令重排序。

6. synchronized(同步修饰符)

  • 仅修饰方法。
  • 作用:多线程环境下给方法加锁,保证同一时间只有一个线程执行该方法,解决线程安全问题。

三、修饰符组合使用规则(高频考点)

  • private、protected、public 三者不能同时出现两个。
  • abstract 不能和 final、private、static 一起修饰方法。
  • static 方法不能使用 this、super。
  • 普通成员方法可以访问静态成员,但静态方法不能访问普通成员。
  • 类上面只能使用 public、abstract、final 三个修饰符。
  • 四、总结区分

  • 访问修饰符(public/protected/默认/private):管「能不能访问」。
  • static:管「属于类还是对象」。
  • final:管「能不能修改、重写、继承」。
  • abstract:管「是否需要子类实现」。
  • transient/volatile/synchronized:多用于 IO、多线程高级场景。
  • 赞(0)
    未经允许不得转载:171主机测评 » Java 类级成员修饰符详解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址