Javaでの列挙とvalues()メソッド


Javaプログラムの作成では列挙(後述はenumで統一)タイプがよく使われますが、今日はenumでよく使われるvalues()メソッドを見てみましょう.
まず、Eclipseで簡単なクラスを作成します.
public class EnumTest {
    private enum Directions {
        NORTH, SOUTH, EAST, WEST
    }
}

ここでは、4つの方向を含むDirectionsというenumを定義します.次に、values()メソッドを呼び出すだけの簡単なmain関数を書きます.
public static void main(String[] args) {
    Directions.values();
}

Eclipseでは、関数、変数をクリックすると、対応するソースコードの位置にジャンプします.ここでvalues()をクリックしようとしたが、反応しなかったのはなぜだろうか.また、Directionsというenumタイプを定義する際にenumというjavaキーワードを使用していますが、ここではvalues()メソッドをどのように呼び出しますか?そのため、enumキーワードの背後にどのように実現されているかを知る必要があります.
最も直接的な方法はJDKのドキュメントを調べることです.oracleオンラインドキュメントのアドレスはここにあります.http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html 紙面はあまり長くありません.その中には私たちの2つの問題を説明する2つの説明があります.
The enum declaration defines a class (called an enum type). The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared.
まず、enum宣言は実際にクラスを定義します.したがって、定義されたenumでメソッドを呼び出すことができます.次に、Javaコンパイラは自動的にenumタイプにいくつかの方法を挿入します.その中にはvalues()が含まれています.だから、私たちのプログラムはコンパイルされていないとき、values()方法のソースコードを表示することはできません.
では、このenumはどんな種類ですか?次の説明があります.
All enums implicitly extend java.lang.Enum. Because a class can only extend one parent (see Declaring Classes), the Java language does not support multiple inheritance of state (see Multiple Inheritance of State, Implementation, and Type), and therefore an enum cannot extend anything else.
もともと、この列挙は実際にjava.lang.Enumというクラスで実現されており、プログラムで定義された列挙タイプは、暗黙的に継承されています.またjavaでの継承は単一継承であるため,我々が定義した列挙は他のクラスを継承することはできない.まず、先ほどのテストクラス(ここでEnumTestと名付けられた)の先頭にimportを追加します.
import java.lang.Enum;

Ctrl+左クリックでソースコードを表示します.
public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
            ......
        }

このクラスの実装を見ると,やはりvalues()メソッドはない.次に、コマンドラインを使用してEnumTest.javaファイルのディレクトリに入り、javacコマンドを使用してこのファイルをコンパイルします.
javac EnumTest.java

lsコマンドでコンパイルに成功したディレクトリのファイルを表示します.結果は次のとおりです.
EnumTest$Directions.class
EnumTest.class
EnumTest.java

コンパイラがEnumTest$Directions.classというclassファイルを生成していることがわかります.Javapコマンドを使用して、EnumTest$Directions.classを逆コンパイルしてコンテンツを表示します.
javap EnumTest\$Directions.class

結果は次のとおりです.
Compiled from "EnumTest.java"
final class EnumTest$Directions extends java.lang.Enum<EnumTest$Directions> {
  public static final EnumTest$Directions NORTH;
  public static final EnumTest$Directions SOUTH;
  public static final EnumTest$Directions EAST;
  public static final EnumTest$Directions WEST;
  public static EnumTest$Directions[] values();    //        
  public static EnumTest$Directions valueOf(java.lang.String);
  static {};
}

コンパイラがvalues()メソッドを自動的に挿入していることがわかります.
最後にまとめます:1.javaのenumキーワードの背後には実際にEnumというクラスが実現しています.2.カスタムenumを作成する場合、valuesメソッドは含まれていません.javaファイルを再コンパイルすると、javaコンパイラが自動的にこのメソッドを生成します.