列挙の深い理解
JVMは、最近の知識を学んで終え、それを分析するためにバイトコードの観点からなので、異機種として列挙考えます。関連する説明を列挙、非常に詳細なブログの多くは、ここではそれについて知っているに来て再びバイトコードの面です。
列挙クラスには、独自のコンストラクタを定義することができ、1つまたは複数のインターフェイスを実装することができ、独自のフィールド、メソッドを持つことができる特別なクラスです。
1.列挙クラスの継承構造:
2.列挙クラスと通常のクラスの違い:
(1)列挙クラスは、列挙型を使用して1つ以上のインターフェースを実装することができる代わりjava.lang.Enum列挙クラス継承デフォルトクラス、オブジェクト・クラスの継承を定義し、したがって、他の継承(単一継承継承列挙を表示できません制限が、インターフェースを実装することができます)。「java.lang.Enumは、」「同等」と「直列化」のインターフェイスを達成するためにどこに。
(2)使用列挙定義、非抽象クラスの列挙は、デフォルトの最終修正で使用され、したがってでき列挙しないクラスのサブクラス。
(3)列挙クラスのコンストラクタはプライベートアクセス指定子でのみ可能であるアクセス指定子がコンストラクタを省略した場合、private修飾子のデフォルトを使用し、唯一のプライベート修飾子を指定で強制アクセス制御を指定した場合。
すべてのインスタンス(4)列挙クラスは、そうでなければ列挙クラスは、例を生成することができなく、表示列挙クラスの最初の行にリストされなければなりません。これらをリアルタイムで一覧表示され、システムが自動的にのpublic static final修飾子を追加し、プログラマはディスプレイを追加する必要はありません。
(5)列挙クラスは、デフォルト値を列挙例の配列を返す方法を提供し、この方法は、容易にトラバースすべての列挙された値であってもよいです。
よりよく説明するために、これらの違いの上、「てjavap -c」それを逆コンパイルするのは、列挙型、使用することを定義してみましょう
public enum Season {
SPRING("春"),SUMMER("夏"),AUTUMN("秋"),WINTTER("冬");
private String name;
Season(String name) {
this.name = name;
}
}
逆コンパイルは、この情報を取得することができます:
"D:\Program Files\Java\jdk1.8.0_77\bin\javap.exe" -c com.bigdata.juc.enums.Season
Compiled from "Season.java"
public final class com.bigdata.juc.enums.Season extends java.lang.Enum<com.bigdata.juc.enums.Season> {
//所定义的所有实例都变为了final修饰的了,并且是static类型的
public static final com.bigdata.juc.enums.Season SPRING;
public static final com.bigdata.juc.enums.Season SUMMER;
public static final com.bigdata.juc.enums.Season AUTUMN;
public static final com.bigdata.juc.enums.Season WINTTER;
//自动提供了values方法
public static com.bigdata.juc.enums.Season[] values();
Code:
0: getstatic #1 // Field $VALUES:[Lcom/bigdata/juc/enums/Season;
3: invokevirtual #2 // Method "[Lcom/bigdata/juc/enums/Season;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[Lcom/bigdata/juc/enums/Season;"
9: areturn
//复写valueoff方法
public static com.bigdata.juc.enums.Season valueOf(java.lang.String);
Code:
0: ldc #4 // class com/bigdata/juc/enums/Season
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class com/bigdata/juc/enums/Season
9: areturn
//枚举类的对象实例化工作是在静态块中完成,无需用户手动实例化,也就是说上面的所定义的四个对象都是在静态块中完成实例化的
static {};
Code:
//第一次,实例化枚举类并赋值给实例SPRING
0: new #4 // class com/bigdata/juc/enums/Season
3: dup
4: ldc #8 // String SPRING
6: iconst_0
7: ldc #9 // String 春
9: invokespecial #10 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
12: putstatic #11 // Field SPRING:Lcom/bigdata/juc/enums/Season;
//第二次,实例化枚举类并赋值给实例SUMMER
15: new #4 // class com/bigdata/juc/enums/Season
18: dup
19: ldc #12 // String SUMMER
21: iconst_1
22: ldc #13 // String 夏
24: invokespecial #10 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
27: putstatic #14 // Field SUMMER:Lcom/bigdata/juc/enums/Season;
//第三次,实例化枚举类并赋值给实例AUTUMN
30: new #4 // class com/bigdata/juc/enums/Season
33: dup
34: ldc #15 // String AUTUMN
36: iconst_2
37: ldc #16 // String 秋
39: invokespecial #10 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
42: putstatic #17 // Field AUTUMN:Lcom/bigdata/juc/enums/Season;
//第四次,实例化枚举类并赋值给实例WINTTER
45: new #4 // class com/bigdata/juc/enums/Season
48: dup
49: ldc #18 // String WINTTER
51: iconst_3
52: ldc #19 // String 冬
54: invokespecial #10 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
57: putstatic #20 // Field WINTTER:Lcom/bigdata/juc/enums/Season;
60: iconst_4
//创建一个引用类型的数组,这个数组就是Season
61: anewarray #4 // class com/bigdata/juc/enums/Season
//复制栈顶一个字长的数据,将复制后的数据压栈。
64: dup
//0(int)值入栈。
65: iconst_0
//获取静态字段的值。
66: getstatic #11 // Field SPRING:Lcom/bigdata/juc/enums/Season;
//将栈顶引用类型值保存到指定引用类型数组的指定项。
69: aastore
//复制栈顶一个字长的数据,将复制后的数据压栈。
70: dup
//1(int)值入栈。
71: iconst_1
//获取静态字段的值
72: getstatic #14 // Field SUMMER:Lcom/bigdata/juc/enums/Season;
//将栈顶引用类型值保存到指定引用类型数组的指定项。
75: aastore
76: dup
77: iconst_2
78: getstatic #17 // Field AUTUMN:Lcom/bigdata/juc/enums/Season;
81: aastore
82: dup
83: iconst_3
84: getstatic #20 // Field WINTTER:Lcom/bigdata/juc/enums/Season;
87: aastore
88: putstatic #1 // Field $VALUES:[Lcom/bigdata/juc/enums/Season;
91: return
}
Process finished with exit code 0
あなたはそれが静的ブロック内の2つのものの合計を完了見つけることができます:
(1)クラスをインスタンス化し、列挙列挙インスタンスに割り当て
(2)配列を列挙することができる方法値の理由である配列の種類及び配列代入への参照を作成します。
「java.lang.Enum」クラスからの列挙クラスを継承するので、それは自動的にクラスのメソッドの一部を継承します。
「クレイジーギャングJAVAの配布資料」からの引用
クラスのメンバ変数、メソッドとコンストラクタを列挙する
列挙クラスもクラスであるが、それは特別なカテゴリですので、メンバ変数、メソッドとコンストラクタとして定義することができます。あるいは、上記のコード断片
public enum Season {
//枚举实例,必须要定义在第一行
SPRING("春"),SUMMER("夏"),AUTUMN("秋"),WINTTER("冬");
//定义了成员变量
private String name;
//定义了构造器,默认为private类型,无论是否显示修饰
Season(String name) {
this.name = name;
}
}
実際にはそれが私たちのデコンパイルの前でこれを見てきた、自動的にインスタンス化基盤となる仕事をし、それが静的オブジェクトで行われているブロックの仕事をインスタンス化されます。このように:
public static final SPRING=new SPRING("春");
public static final SPRING=new SUMMER("夏");
public static final SPRING=new AUTUMN("秋");
public static final SPRING=new WINTTER("冬");
4.列挙クラスが実装するインタフェース
継承他のクラスを列挙することは不可能ですが、インターフェースは、単一継承の制限はありませんので、まだ、他のインタフェースを実装することができますが。インタフェースのインタフェースと実装が同じ一般的なカテゴリで実装列挙クラスでは、本質的な違いはありません。
インタフェースの定義:
public interface GenderDesc {
void info();
}
列挙型クラスは、このインタフェースを実装しています。
//实现接口,并且以内部类的形式
public enum Gender implements GenderDesc
{
// public static final Gender MALE = new Gender("男");
MALE("男") {
public void info() {
System.out.println("gender male information");
}
},
FEMALE("女") {
public void info() {
System.out.println("gender female information");
}
};
private String name;
private Gender(String name) {
this.name = name;
}
}
public class enumTest {
public static void main(String[] args) {
// 通过valueof方法获取指定枚举类的值
Gender gf = Enum.valueOf(Gender.class, "FEMALE");
Gender gm = Enum.valueOf(Gender.class, "MALE");
System.out.println(gf + " is stand for " + gf.getName());
System.out.println(gm + " is stand for " + gm.getName());
gf.info();
gm.info();
}
}
コンパイル時に性別クラスには、三つのクラス「Gender.class」、「ジェンダーの$ 1.class」と2つの匿名内部クラスが表現されている性別$ 1、性別$「ジェンダーの$ 2.class」を、生成されます。
注1:上述した非抽象クラスの列挙については、抽象的修飾を用いて、「最終的な」改変、抽象列挙クラスを使用し、これは「てjavap -c Gender.class」を参照介し得ます。
D:\Project\JUCDmo\other\target\classes\com\bigdata\juc\enums>javap -c Gender.class
Compiled from "Gender.java"
//使用abstract修饰,因为尽管匿名内部实例MALE和FEMALE中实现了info方法,但是在Gender类中并没有实现info方法,所以它仍然会被认为是抽象的,除非显示的实现info方法
public abstract class com.bigdata.juc.enums.Gender extends java.lang.Enum<com.bigdata.juc.enums.Gender> implements com.bigdata.juc.enums.GenderDesc {
public static final com.bigdata.juc.enums.Gender MALE;
public static final com.bigdata.juc.enums.Gender FEMALE;
「ジェンダーの$ 1.class」
D:\Project\JUCDmo\other\target\classes\com\bigdata\juc\enums>javap -p Gender$1.class
Compiled from "Gender.java"
//使用final修饰
final class com.bigdata.juc.enums.Gender$1 extends com.bigdata.juc.enums.Gender {
com.bigdata.juc.enums.Gender$1(java.lang.String, int, java.lang.String);
public void info();
}
注2:列挙値の2つの方法が異なる挙動を示す、彼らは、出力情報の違い、および行動の何も特別の他の症状を参照してください。
オリジナルリンク:https://www.cnblogs.com/MarchThree/p/3720468.html
抽象クラスの列挙方法であって
列挙クラスは抽象メソッドが抽象キーワードを列挙するために使用することはできません定義する場合には(システムが自動的にそれのための抽象キーワードが追加されますので)抽象クラスとして定義されていますが、列挙値を作成するための表示列挙クラスに必要があるため、そのそれぞれの定義されました列挙値は、それ以外の場合は、例外をコンパイルするために表示されるときには、抽象メソッドの実装を提供する必要があります。
enum Operation {
PLUS {
public double eval(double x, double y) {
return x + y;
}
},
MINS {
public double eval(double x, double y) {
return x - y;
}
},
TIMES {
public double eval(double x, double y) {
return x * y;
}
},
DIVIDE {
public double eval(double x, double y) {
if (y == 0) {
return -1;
}
return x / y;
}
};
//为枚举类定义抽象方法,具体由枚举值提供实现
public abstract double eval(double x, double y);
}
public class OperationTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Operation.PLUS.eval(1, 2));
System.out.println(Operation.DIVIDE.eval(1, 0));
}
}
逆コンパイルの結果の一部:
D:\Project\JUCDmo\other\target\classes\com\bigdata\juc\enums>javap -c Operation.class
Compiled from "OperationTest.java"
//类名为abstract修饰
abstract class com.bigdata.juc.enums.Operation extends java.lang.Enum<com.bigdata.juc.enums.Operation> {
public static final com.bigdata.juc.enums.Operation PLUS;
public static final com.bigdata.juc.enums.Operation MINS;
public static final com.bigdata.juc.enums.Operation TIMES;
public static final com.bigdata.juc.enums.Operation DIVIDE;
public static com.bigdata.juc.enums.Operation[] values();
Code:
0: getstatic #2 // Field $VALUES:[Lcom/bigdata/juc/enums/Operation;
3: invokevirtual #3 // Method "[Lcom/bigdata/juc/enums/Operation;".clone:()Ljava/lang/Object;
6: checkcast #4 // class "[Lcom/bigdata/juc/enums/Operation;"
9: areturn
public static com.bigdata.juc.enums.Operation valueOf(java.lang.String);
Code:
0: ldc #5 // class com/bigdata/juc/enums/Operation
2: aload_0
3: invokestatic #6 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #5 // class com/bigdata/juc/enums/Operation
9: areturn
public abstract double eval(double, double);
com.bigdata.juc.enums.Operation(java.lang.String, int, com.bigdata.juc.enums.Operation$1);
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #1 // Method "<init>":(Ljava/lang/String;I)V
6: return
static {};
……
オリジナルリンク:https://blog.csdn.net/uni_ys/article/details/60956718 https://www.cnblogs.com/MarchThree/p/3720467.html
はじめに6.列挙
単一の実施形態において、列挙
```java
package com.bigdata.juc.singleton;
/*
* 枚举类型:表示该类型的对象是有限的几个
* 我们可以限定为一个,就成了单例
*/
enum EnumSingleton{
//等价于 public static final INSTANCE=new EnumSingleton();
INSTANCE
}
public class Singleton2 {
public static void main(String[] args) {
EnumSingleton s = EnumSingleton.INSTANCE;
System.out.println(s);
}
}
```
列挙クラス7.値方法?
列挙値()、どちらもJava.lang.Enumから、また列挙型が達成インターフェースから、それは自分自身の農産物をコンパイルするプロセスであり、かつ逆コンパイルプロセスの前に、私たちも見ますこの点に、我々はまた、それが実際に基礎となる参照型配列を生成していることがわかり、この方法は、列挙値の配列を返します。上の使用を参照することができます)(列挙値の列挙クラスメソッド
その起源の深い理解をしたい、あなたはブログを参照することができたJava列挙型(列挙型)の理解に深く