見出し画像

なぜなぜJAVAのお約束はムズイよね。

もう!JAVAでpablicなクラスやインターフェース、列挙型はソースファイルにひとつしかけないけどそれ以外は複数書けるって言うのがイマイチ理解できない〜!

----🔻

サンプルソースファイル「MyClass.java」を考えましょう。

// 列挙型
enum MyEnum {
    VALUE1,
    VALUE2,
    VALUE3;
}

// インターフェース
interface MyInterface {
    void method1();
    void method2();
}

// パブリッククラス
public class MyClass {
    // クラスのフィールドやメソッド
    private int myField;
    
    public void myMethod() {
        // メソッドの処理
    }
}

// 他のクラス
class AnotherClass {
    // クラスのフィールドやメソッド
    private String name;
    
    public void printName() {
        System.out.println(name);
    }
}

// もうひとつのクラス
class YetAnotherClass {
    // クラスのフィールドやメソッド
    private boolean flag;
}

このサンプルでは、4つの要素を含んでいます。

  1. 列挙型(MyEnum):このソースファイル内に1つだけ定義されています。

  2. インターフェース(MyInterface):同様に、このソースファイル内に1つだけ定義されています。

  3. パブリッククラス(MyClass):パブリックなので、他のソースファイルからアクセスすることができます。ソースファイル内に1つだけ定義されています。

  4. その他のクラス(AnotherClass、YetAnotherClass):これらのクラスはパブリックではないため、同一のソースファイル内に複数の定義が可能です。

これが言われている「ソースファイルにひとつしか定義できない」ルールです。パブリックなクラスやインターフェース、列挙型はソースファイルごとに1つしか定義できませんが、その他のクラスは同一のソースファイル内に複数の定義が可能です。

----▼

Javaでは、一つのソースファイルには一つのpublicなクラスしか宣言できません。publicなクラスは、他のプログラムからアクセスできるクラスです。例えば、以下のようなコードがあるとします。

JavaAI で生成されたコード。ご確認のうえ、慎重にご使用ください。FAQ で詳細を確認

// ソースファイル1.java
public class Person {
  // メンバ変数
  private String name;
  private int age;

  // コンストラクタ
  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  // メソッド
  public String getName() {
    return name;
  }

  public int getAge() {
    return age;
  }
}

この場合、ソースファイル1.javaはPersonというpublicなクラスを宣言しています。このクラスを他のプログラムから使うには、以下のようにインポートする必要があります。

// ソースファイル2.java
import java.util.Scanner; // Scannerクラスをインポートする

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in); // Scannerオブジェクトを作る
    System.out.println("名前を入力してください:");
    String name = sc.nextLine(); // 名前を入力する
    System.out.println("年年齢を入力してください:");
    int age = sc.nextInt(); // 年年齢を入力する

    Person p = new Person(name, age); // Personオブジェクトを作る
    System.out.println("こんにちは、" + p.getName() + "さん。" + p.getAge() + "歳です。"); // Personオブジェクトのメソッドを呼ぶ

    sc.close(); // Scannerオブジェクトを閉じる
  }
}

この場合、ソースファイル2.javaはScannerというパッケージに属するクラスをインポートしています。パッケージとは、Javaでで複数の関連するクラスやインターフェースをまとめたものです。パッケージ名は大文字で始めて小文字で終わります。例えば、java.utilやjava.ioなどがあります。

しかし、パッケージ内でも同じ名前のクラスやインターフェースがある場合は、どちらか一方だけが公開されていることに注意しなければなりません。例えば、以下のようなコードがあるとします。

// ソースファイル3.java
package java.util; // java.utilパッケージに属する

public class List { // Listというpublicなインターフェースを宣言する

}

この場合、ソースファイル3.javaはjava.utilパッケージ内にあるListというpublicなインターフェースを宣言しています。このインターフェースは他のプログラムから使えません。例えば、以下のように書くことができません。

// ソースファイル4.java
import java.util.List; // Listインターフェースをインポートする

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<String>(); // Listインターフェース型のリストオブジェクトを作る(エラー)
    
    System.out.println(list); // リストオブジェクト(エラー)
    
  }
}

この場合、ソースファイル4.javaはListというパッケージ内にあるListというpublicなインターフェース型(List<String>)を使おうとしていますが、エラーが発生します。これは、Listインターフェース型(List<String>)がパッケージ内にあるためです。Javaでは、同じパッケージ内にあるクラスやインターフェースは、その名前の前にパッケージ名を付けて宣言する必要があります。例えば、以下のように書くことができます。

// ソースファイル4.java
package java.util; // java.utilパッケージに属する

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<String>(); // Listインターフェース型のリストオブジェクトを作る
    System.out.println(list); // リストオブジェクト
  }
}

この場合、ソースファイル4.javaはjava.utilパッケージ内にあるListというpublicなインターフェース型(List<String>)を使っています。このインターフェースは他のプログラムからもアクセスできます。例えば、以下のように書くことができます。

// ソースファイル5.java
import java.util.List; // Listインターフェースをインポートする

public class Main {
  public static void main(String[] args) {
    List<String> list = new ArrayList<String>(); // Listインターフェース型のリストオブジェクトを作る
    System.out.println(list); // リストオブジェクト
  }
}

この場合、ソースファイル5.javaはjava.utilパッケージ内にあるListというpublicなインターフェース型(List<String>)を使っています。このインターフェースも他のプログラムからアクセスできます。


詳細情報:

1. qiita.com2. stackoverflow.com3. stackoverflow.com4. stackoverflow.com5. docs.oracle.com— 

この記事が気に入ったらサポートをしてみませんか?