🔍

Javaのアクセス修飾子について

2021/06/18に公開

public

  • インスタンス化した後で呼び出し可能
Animal.java
public class Dog {

  public void bark() {
    System.out.println("baw");
  }
}
Main.java
public class Main {

 public static void main(String[] args) {
  Dog dog = new Dog();
  dog.bark();
 }
}
baw

private

  • クラス内のみで呼び出し可能
Dog.java
public class Dog {

  public void bark() {
    System.out.println("baw");
  }

  private void digest_food() {
    System.out.println("stomach, small intestine, large intestine...");
  }

  // privateなdigest_foodメソッドをeatメソッド内で使用
  public void eat(String food) {
    System.out.println(String.format("eating %s...", food));
    digest_food();
  }
}
Main.java
public class Main {

  public static void main(String[] args) {
    Dog dog = new Dog();
    dog.digest_food();
  }
}
java: digest_food()はDogでprivateアクセスされます
Main.java
public class Main {

  public static void main(String[] args) {
    Dog dog = new Dog();
    dog.eat("dog food"); // eatメソッドに内包される形でdigest_foodメソッドも呼び出される
  }
}
eating dog food...
stomach, small intestine, large intestine...

protected

  • 同じパッケージのクラス、又は継承した子クラスのみ呼び出し可能
Mammals.java
public class Mammals {

  protected void run() {
    System.out.println("Running through...");
  }
}
Dog.java
public class Dog extends Mammals{

  public void bark() {
    System.out.println("baw");
  }

  private void digest_food() {
    System.out.println("stomach, small intestine, large intestine...");
  }

  public void eat(String food) {
    System.out.println(String.format("eating %s...", food));
    digest_food();
  }
}
Bird.java
public class Bird {
  public void fly(){
    System.out.println("Flying in the sky");
  }
}
Main.java
public class Main {

  public static void main(String[] args) {
    Dog dog = new Dog();
    dog.run();
    Bird bird = new Bird();
    bird.run();
  }
}
Running through...
java: シンボルを見つけられません
  シンボル:   メソッド run()
  場所: タイプBirdの変数 bird

アクセス修飾子無し

  • 同じパッケージのクラスのみ呼び出し可能
├── src
│   ├── Main.java
│   ├── Mammals // 哺乳類用パッケージ
│   │   ├── Dog.java
│   │   └── Mammals.java
│   └── Sloth.java // ナマケモノクラス(哺乳類だけど今回はパッケージの外に出す)

Mammals.java
package Mammals;

public class Mammals {

  void run() {
    System.out.println("Running through...");
  }
}
Sloth.java
import Mammals.Mammals;

public class Sloth extends Mammals {

  public void catchPrey(String prey){
    run(); // 同一パッケージのメソッドでは無いが、無理矢理呼び出してみる
    System.out.println(String.format("I couldn't catch my %s", prey));
  }
}
Dog.java
package Mammals;

public class Dog extends Mammals {

  public void bark() {
    System.out.println("baw");
  }

  private void digest_food() {
    System.out.println("stomach, small intestine, large intestine...");
  }

  public void eat(String food) {
    System.out.println(String.format("eating %s...", food));
    digest_food();
  }

  public void catchPrey(String prey){
    run(); // 同一パッケージにあるクラスのため、呼び出し可能
    System.out.println(String.format("Caught the %s", prey));
  }
}
Main.java
import Mammals.Dog;

public class Main {

  public static void main(String[] args) {
    System.out.println("--- dog ---");
    Dog dog = new Dog();
    dog.catchPrey("something");
    System.out.println("--- sloth ---");
    Sloth sloth = new Sloth();
    sloth.catchPrey("something");
  }
}
--- dog ---
Running through...
Caught the something
--- sloth ---
java: シンボルを見つけられません
  シンボル:   メソッド run()
  場所: クラス Sloth
Sloth.java
import Mammals.Mammals;

public class Sloth extends Mammals {

  public void catchPrey(String prey){
    System.out.println(String.format("I couldn't catch my %s", prey));
  }
}
--- dog ---
Running through...
Caught the something
--- sloth ---
I couldn't catch my something

public static

  • クラス名.メソッド名などの形で、クラスを経由してアクセス可能
Dog.java
package Mammals;

public class Dog extends Mammals {

  // publicからpublic staticに変更してみる
  public static void bark() {
    System.out.println("baw");
  }

  private void digest_food() {
    System.out.println("stomach, small intestine, large intestine...");
  }

  public void eat(String food) {
    System.out.println(String.format("eating %s...", food));
    digest_food();
  }

  public void catchPrey(String prey){
    run();
    System.out.println(String.format("Caught the %s", prey));
  }
}
Main.java
import Mammals.Dog;

public class Main {

  public static void main(String[] args) {
    System.out.println("--- dog ---");
    Dog.bark(); // インスタンス化しなくても、クラスを経由してアクセス可能
  }
}
--- dog ---
baw

private static

  • staticなメソッドはインスタンスメンバ(変数やメソッド)にアクセスできないため、メソッド内でインスタンス変数を使わない場合に保守性を高めるために使う
    • staticなメソッドにthis.変数が使えないのは上記の理由
Dog.java
package Mammals;

public class Dog extends Mammals {

  private static void bark() {
    System.out.println("baw");
  }

  private void digest_food() {
    System.out.println("stomach, small intestine, large intestine...");
  }

  public void eat(String food) {
    System.out.println(String.format("eating %s...", food));
    digest_food();
  }

  public void catchPrey(String prey){
    run();
    System.out.println(String.format("Caught the %s", prey));
  }
}
Main.java
import Mammals.Dog;

public class Main {

  public static void main(String[] args) {
    System.out.println("--- dog ---");
    Dog.bark(); // クラスを経由してアクセス不可となるが、無理矢理アクセスしてみる
  }
}
java: bark()はMammals.Dogでprivateアクセスされます
Dog.java
package Mammals;

public class Dog extends Mammals {

  private static void bark() {
    System.out.println("baw");
  }

  private void digest_food() {
    System.out.println("stomach, small intestine, large intestine...");
  }

  public void eat(String food) {
    System.out.println(String.format("eating %s...", food));
    digest_food();
  }

  public void catchPrey(String prey){
    run();
    System.out.println(String.format("Caught the %s", prey));
  }

  // beHungryメソッド内でprivate staticなbarkメソッドを呼び出し
  public void beHungry(){
    bark();
    bark();
    bark();
  }
}
Main.java
import Mammals.Dog;

public class Main {

  public static void main(String[] args) {
    System.out.println("--- dog ---");
    Dog dog = new Dog();
    dog.beHungry(); // インスタンス化した後で、publicメソッドを呼び出すことが可能なため、beHungryメソッド内のbarkを間接的に呼び出すことが可能
  }
}
--- dog ---
baw
baw
baw

Discussion