Java 简明教程

Java - Access Modifiers

Java *access modifiers*用于指定 scope of the variablesdata members、方法、类或 constructors。它们有助于限制和保护数据访问(或访问级别)。

Java 中有四种不同的访问修饰符类型,我们将其列出如下:

  1. Default (No keyword required)

  2. Private

  3. Protected

  4. Public

java access modifiers

Default Access Modifier

默认访问修饰符表示我们没有明确地为类、字段、 method 等声明访问修饰符。

在没有访问控制修饰符的情况下声明的变量或方法供相同包中的任何其他类使用。接口中的字段隐式为 public static final,接口中的方法默认情况下为 public。

Example of Default Access Modifiers

变量和方法可以在没有任何修饰符的情况下声明,如下例所示:

String version = "1.5.1";

boolean processOrder() {
   return true;
}

Private Access Modifier

仅在声明的类内部可以访问声明为 private 的方法、变量和构造函数。

私有访问修饰符是最严格的访问级别。类和接口不能为私有的。

如果类中有 public getter 方法,可以在类的外部访问声明为 private 的变量。

使用 private 修饰符是对象封装自身和隐藏来自外部世界数据的常用方法。

Examples of Private Access Modifiers

以下类使用私有访问控制:

public class Logger {
   private String format;

   public String getFormat() {
      return this.format;
   }

   public void setFormat(String format) {
      this.format = format;
   }
}

此处,Logger 类的 format 变量为 private,因此其他 classes 无法直接检索或设置其值。

所以,为了使此变量可供外部访问,我们定义了两个公共方法:getFormat(),它返回格式的值;和 setFormat(String),它设置其值。

在此示例中,Logger 类的 data 成员和类方法是私有的。我们尝试在另一个 Main 类中访问这些类方法。

class Logger {
  private String format;

  private String getFormat() {
    return this.format;
  }

  private void setFormat(String format) {
    this.format = format;
  }
}

public class Main {
  public static void main(String[] args) {
    // Creating an object
    Logger log = new Logger();
    // Setting the value
    log.setFormat("Text");
    // Getting the value
    System.out.println(log.getFormat());

  }
}

Output

Main.java:18: error: setFormat(String) has private access in Logger
    log.setFormat("Text");
       ^
Main.java:20: error: getFormat() has private access in Logger
    System.out.println(log.getFormat());
                          ^
2 errors

Protected Access Modifier

变量、方法和构造函数在超类中声明为 protected,只能由其他包中的子类或包含受保护成员类包中的任何类来访问。

不能将 protected 访问修饰符应用于类和接口。可以将方法、字段声明为 protected,但是不能将接口中的方法和字段声明为 protected。

Protected 访问为子类提供使用助手方法或变量的机会,同时防止不相关的类尝试使用它。

Examples of Protected Access Modifiers

以下父类使用 protected 访问控制,允许其子类重写 openSpeaker() 方法 −

class AudioPlayer {
   protected boolean openSpeaker(Speaker sp) {
      // implementation details
   }
}

class StreamingAudioPlayer extends AudioPlayer {
   boolean openSpeaker(Speaker sp) {
      // implementation details
   }
}

在这里,如果我们定义 openSpeaker() 方法为私有的,那么除 AudioPlayer 之外,任何其他类都不能访问它。如果我们将其定义为公有的,那么所有的外部世界都可以访问它。但我们的目的是仅将其方法公开给其子类,这就是我们使用 protected 修饰符的原因。

此示例演示 protected 访问修饰符的使用。

// Class One
class One {
  protected void printOne() {
    System.out.println("printOne method of One class.");
  }
}

// Inheriting class One on Main
public class Main extends One {
  public static void main(String[] args) {
    // Creating an object of Main class
    Main obj = new Main();

    // Calling printOne() method of class One
    // through the object of Main class
    obj.printOne();
  }
}

Output

printOne method of One class.

Public Access Modifier

声明为公有的类、方法、构造函数、接口等可从任何其他类访问。因此,可以在属于 Java Universe 的任何类中访问在公共类内部声明的字段、方法和块。

但是,如果我们尝试访问的公共类位于不同的包中,则仍然需要导入公共类。由于类继承,超类的所有公共方法和变量都会被其子类继承。

Syntax

以下函数使用公共访问控制 −

public static void main(String[] arguments) {
   // ...
}

应用程序的 main() 方法必须是公共的。否则,Java 解释器(例如 java)无法调用它来运行类。

Example of Public Access Modifiers

此示例演示公共访问修饰符的使用。

// Class One
class One {
  public void printOne() {
    System.out.println("printOne method of One class.");
  }
}

public class Main {
  public static void main(String[] args) {
    // Creating an object of class One
    One obj = new One();

    // Calling printOne() method of class One
    obj.printOne();
  }
}

Output

This example demonstrates the use of public access modifier.

Access Modifiers and Inheritance

强制执行以下继承方法规则 −

  1. 在超类中声明为 public 的方法也必须在所有子类中声明为 public。

  2. 在超类中声明为 protected 的方法在子类中必须声明为 protected 或 public;它们不能为 private。

  3. 声明为 private 的方法根本不会被继承,因此对它们没有规则。

下表总结了基于访问修饰符在同一/不同类(或包)中的可访问性。

java access modifiers uses in different scopes

Example of Access Modifiers with Inheritance

在此示例中,我们使用 private 变量 age 创建了一个类,并使用 name 作为默认作用域创建了一个变量。使用 setter/getter 方法,我们更新 age 并获取值,并直接更新 name。

public class Puppy {
   private int age;
   String name;

   public Puppy() {
   }

   public void setAge( int age ) {
      this.age = age;
   }

   public int getAge( ) {
      return age;
   }

   public static void main(String []args) {
      Puppy myPuppy = new Puppy();

      // update age variable using method call
      myPuppy.setAge( 2 );

      // update name directly
      myPuppy.name = "Tommy";
      System.out.println("Age: " + myPuppy.getAge() +", name: " + myPuppy.name );
   }
}

Output

Age: 2, name: Tommy