Java语言提供了很多修饰符,主要分为以下两类:
访问控制修饰符
非访问修饰符
访问控制修饰符
private
:私有访问权限,用于修饰类的属性和方法。被private修饰的成员只能在本类中进行访问。- default(默认访问权限,无修饰符):如果一个类中的属性或方法没有显式指定访问修饰符,它将具有默认的访问权限。默认访问权限允许本包中的其他类访问,但不能被其他包的类访问。
protected
:受保护访问权限。被protected修饰的成员可以在本包及不同包的子类中访问。public
:公共访问权限。被public修饰的成员可以在所有类中访问,不论是否在同一包中。
下面通过一张表总结上述的访问控制权限。
综上所述:
可以理解为将整个世界都打包成一块,同时划分为四个层次: 联合国(public)【其他包】、国家(protected)【继承子孙】、洲际(default)【同一包】、个人(private)【当前类】。
联合国制定规则所有人都可以用,国家制定的只有在国家内可以用,各联邦洲因地制宜有制定当地民法,个人制定的就给个人使用。
实例
//创建一个名为Person的类
class Person {private String name; // 私有属性,只能在本类中访问String gender; // 默认访问权限,本包中的其他类可以访问protected int age; // 受保护的属性,本包及子类可以访问public String address; // 公共属性,所有类都可以访问// 私有方法,只能在本类中调用private void printName() {System.out.println("名称:" + name);}// 默认访问权限的方法,本包中的其他类可以调用void printGender() {System.out.println("性别:" + gender);}// 受保护的方法,本包及子类可以调用protected void printAge() {System.out.println("年龄:"+ age);}// 公共方法,所有类都可以调用public void printAddress() {System.out.println("地址:"+ address);}
}//创建另一个名为Student的子类,继承自Person类
class Student extends Person {public void displayInfo() {// 在子类中可以访问父类的受保护属性和方法System.out.println("Student Info:");printName(); // 调用了父类的私有方法,间接访问了private属性printGender(); // 调用了父类的默认方法,访问本包中的属性printAge(); // 调用了父类的受保护方法,访问子类继承的属性System.out.println("Address: " + address); // 直接访问父类的公共属性}
}//主程序入口
public class MyClass {public static void main(String[] args) {Student student = new Student();// 在主程序中无法直接访问Person类的私有属性和方法// student.name = "Alice"; // 错误!私有属性不能在其他类中直接访问// student.printName(); // 错误!私有方法不能在其他类中直接调用// 可以访问默认、受保护和公共属性及方法student.gender = "Female";student.age = 18;student.address = "123 Street";student.displayInfo();}
}
非访问修饰符
为了实现一些其他的功能,Java 也提供了许多非访问修饰符。
- static:用来修饰类方法和类变量。通过使用static修饰,可以使得方法或变量与类本身相关联,而不是具体的实例对象。静态方法可以直接通过类名调用,而无需创建实例对象。
- final:用来修饰类、方法和变量。被final修饰的类不能被继承,即不能有子类。被final修饰的方法不能被继承类重新定义,即不能被子类重写。被final修饰的变量为常量,即其值在初始化后不可修改。
- abstract:用来创建抽象类和抽象方法。抽象类是不能被实例化的类,主要用作其他类的基类。抽象方法是没有具体实现的方法,必须在子类中进行重写。
- synchronized:用于多线程环境,用于实现线程安全的同步访问,确保多个线程对同一代码块的串行执行。
- volatile:用于多线程环境,用于声明变量是被多个线程共享的,保证了其在多线程环境下的可见性和有序性。
- transient:用于序列化,表示某个字段不会被持久化存储或网络传输,通常用于敏感信息或与序列化无关的临时数据。
- native:表示方法的实现是由外部的本地语言(如C、C++)提供,用于与操作系统或底层硬件进行交互。
- strictfp:用于浮点数计算,强制按照IEEE 754标准执行,保证浮点计算的结果在不同平台上的一致性。
实例
public class ModifierExample {// static修饰的变量和方法与类本身关联public static int staticVariable = 10;public static void staticMethod() {System.out.println("这是一种静态方法。");}// final修饰的变量为常量,值不可修改public final int finalVariable = 20;public final void finalMethod() {System.out.println("这是最后一种方法。");}// abstract修饰的方法没有具体实现,需要在子类中重写public abstract void abstractMethod();// synchronized修饰的方法确保多个线程对代码块的串行执行public synchronized void synchronizedMethod() {System.out.println("这是一种同步方法。");}// volatile修饰的变量被多个线程共享,保证可见性和有序性public volatile int volatileVariable = 0;// transient修饰的变量不会被序列化存储或网络传输public transient String transientVariable;// native修饰的方法使用外部的本地语言提供的实现public native void nativeMethod();// strictfp修饰的方法按照IEEE 754标准执行浮点数计算public strictfp void strictfpMethod() {double num1 = 0.1;double num2 = 0.2;double result = num1 + num2;System.out.println("结果:"+ result);}
}
注意:
abstract修饰的方法所在的类必须声明为抽象类。native修饰的方法通常需要与本地语言进行交互。