Java 修饰符

修饰符

到目前为止,您已经非常熟悉出现在我们几乎所有例子中的 public 关键字:

public class Main

public 关键字是一个访问修饰符,这意味着它用于设置类、属性、方法和构造函数的访问级别。

我们将修饰符分为两组:

  • 访问修饰符 - 控制访问级别
  • 非访问修饰符 - 不控制访问级别,但提供其他功能

访问修饰符

对于类,您可以使用 publicdefault

修饰符 描述 试一试
public 任何其他类都可以访问该类。 试一试
default

该类只能由同一包中的类访问。在您未指定修饰符时使用。

您将在 这一章中学习有关包的更多内容。

试一试

对于属性、方法和构造函数,您可以使用以下之一:

修饰符 描述 试一试
public 所有类均可访问该代码。
private 代码只能在声明的类中访问。 试一试
default

该代码只能在同一个包中访问。在您未指定修饰符时使用。

您将在 这一章中学习有关包的更多内容。

试一试
protected

代码可以在同一个包和子类中访问。

您将在 继承 这一章中了解有关子类和超类的更多内容。

试一试

非访问修饰符

对于类,您可以使用 finalabstract

修饰符 描述 试一试
final

该类不能被其他类继承。

您将在 继承 这一章中学到有关继承的更多内容。

试一试
abstract

该类不能用于创建对象(要访问抽象类,它必须从另一个类继承)。

您将在 继承抽象 章节中了解有关继承和抽象的更多信息。

对于属性和方法,您可以使用以下修饰符之一:

修饰符 描述
final 属性和方法不能被覆盖/修改。
static 属性和方法属于类,而非对象。
abstract

只能在抽象类中使用,且只能在方法上使用。

该方法没有主体,例如 abstract void run();。主体由子类提供(继承自)。

您将在 继承抽象 章节中了解有关继承和抽象的更多信息。

transient 当序列化包含它们的对象时会跳过属性和方法。
synchronized 方法一次只能被一个线程访问。
volatile 属性的值不是在线程本地(thread-locally)缓存的,而是始终从“主内存”中读取。

Final

如果您不希望能够覆盖现有的属性值,请将属性声明为 final

实例

public class Main {
  final int x = 10;
  final double PI = 3.14;

  public static void main(String[] args) {
    Main myObj = new Main();
    myObj.x = 50; // 将产生错误:无法为 final 变量赋值
    myObj.PI = 25; // 将产生错误:无法为 final 变量赋值
    System.out.println(myObj.x);
  }
}

运行实例

Static

静态方法意味着它可以在不创建类的对象的情况下访问,与 public 不同:

实例

演示静态方法和公共方法之间差异的例子:

public class Main {
  // 静态方法:
  static void myStaticMethod() {
    System.out.println("无需创建对象即可调用静态方法");
  }

  // 公共方法:
  public void myPublicMethod() {
    System.out.println("公共方法必须通过创建对象来调用");
  }

  // 主方法:
  public static void main(String[ ] args) {
    myStaticMethod(); // 调用静态方法
    // myPublicMethod(); 这将输出错误

    Main myObj = new Main(); // 创建 Main 对象
    myObj.myPublicMethod(); // 调用公共方法
  }
}

亲自试一试

Abstract

abstract 方法属于 abstract 类,它没有主体。主体由子类提供:

实例

// 代码来自文件名:Main.java
// 抽象类
abstract class Main {
  public String fname = "Bill";
  public int age = 19;
  public abstract void study(); // abstract 方法
}

// 子类(继承自 Main)
class Student extends Main {
  public int graduationYear = 2018;
  public void study() { // 此处提供主体的 abstract 方法
    System.out.println("Studying all day long");
  }
}
// 来自文件名:Main.java 的代码结束了

// 代码来自文件名:Second.java
class Second {
  public static void main(String[] args) {
    // 创建 Student 类的一个对象(从 Main 继承属性和方法)
    Student myObj = new Student();

    System.out.println("名字:" + myObj.fname);
    System.out.println("年龄:" + myObj.age);
    System.out.println("毕业年份:" + myObj.graduationYear);
    myObj.study(); // 调用 abstract 方法
  }
}