Java 访问修饰符

Java 中的访问修饰符用于指定变量范围、数据成员、方法、类或构造函数。这些有助于限制和保护数据的访问(或访问级别)。

有四种访问级别:

  • 对以下人员可见包,默认值。不需要修饰符。
  • 仅对类可见(private)。
  • 对全世界可见(public)。
  • 对包和所有子类可见。 (protected)。

在本教程中,我们将通过示例了解 Java 访问修饰符及其各种类型。

Java 访问修饰符的类型

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

  • 默认(不需要关键字)
  • private
  • protected
  • public

Java 访问修饰符

1.默认访问修饰符

默认访问修饰符意味着我们没有显式地为类、字段、方法等声明访问修饰符。

没有任何访问控制修饰符声明的变量或方法是可用于同一包中的任何其他类。接口中的字段隐式为 public static final,接口中的方法默认为 public。

示例:默认访问修饰符

可以在不使用任何修饰符的情况下声明变量和方法,如以下示例所示 -

String version = "1.5.1";

boolean processOrder() {
   return true;
} 

2.private访问修饰符

声明为私有的方法、变量和构造函数只能在声明的类本身内访问。

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

如果类中存在公共 getter 方法,则声明为私有的变量可以在类外部访问。

使用 private 修饰符是主要的对象封装自身并向外界隐藏数据的方式。

示例 1:私有访问修饰符

以下类使用私有访问控制 

public class Logger {
   private String format;

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

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

这里,Logger 类的 format 变量是私有的,因此其他类无法直接检索或设置其值。

因此,要使该变量可供在外部,我们定义了两个公共方法:getFormat(),它返回 format 的值,以及 setFormat(String),它设置它的值。

示例 2:私有访问修饰符

在此示例中,Logger 类的数据成员和类方法是私有的。我们正在尝试访问另一个类 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) {
    // 创建对象
    Logger log = new Logger();
    //设置值
    log.setFormat("Text");
    //获取值
    System.out.println(log.getFormat());

  }
} 

输出

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 

3.protected访问修饰符

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

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

受保护的访问使子类有机会使用辅助方法或变量,同时防止不相关的类尝试使用它。

示例 1:受保护的访问修饰符

以下父类使用受保护的访问控制,以允许其子类重写 openSpeaker() 方法 -

class AudioPlayer {
   protected boolean openSpeaker(Speaker sp) {
      //实现细节
   }
}

class StreamingAudioPlayer extends AudioPlayer {
   boolean openSpeaker(Speaker sp) {
      //实现细节
   }
} 

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

示例 2:Protected 访问修饰符

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

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

//继承Main上的类一
public class Main extends One {
  public static void main(String[] args) {
    // 创建Main类的对象
    Main obj = new Main();

    //调用类One的printOne()方法
    //通过Main类的对象
    obj.printOne();
  }
} 

输出

printOne method of One class. 

4.公共访问修饰符

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

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

语法

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

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

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

示例:公共访问修饰符

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

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

public class Main {
  public static void main(String[] args) {
    // 创建类 One 的对象
    One obj = new One();

    //调用类One的printOne()方法
    obj.printOne();
  }
} 

输出

This example demonstrates the use of public access modifier. 

Java 访问修饰符和继承

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

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

  • 在超类中声明为 protected 的方法必须是子类中受保护或公共;它们不能是私有的。

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

下表显示了基于访问修饰符的相同/不同类(或包)中的可访问性摘要。

修饰符

本类

同包子类

同包其他类

不同包子类

不同包其他类

private

默认

protected

public

示例

在此示例中,我们创建了一个具有私有变量 age 和一个具有默认作用域的变量的类作为名字。使用 setter/getter 方法,我们更新年龄并获取值,名称直接更新。

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();

      //使用方法调用更新年龄变量
      myPuppy.setAge( 2 );

      //直接更新名称
      myPuppy.name = "Tommy";
      System.out.println("Age: " + myPuppy.getAge() +", name: " + myPuppy.name );
   }
} 

输出

Age: 2, name: Tommy