全能の列挙

入門


非常に頻繁に、意図した目的のためにツールを厳密に使用し、左または右に一歩踏み出すことを禁止します。 しかし、少し「忘れられた」としたらどうでしょうか? 慣れ親しんだものを別の角度から見るとどうなりますか? この記事では、列挙を使用するためのアプローチを収集し、それらに対して小規模な実験を行いました。 皮肉、ユーモア、哲学的な質問。 誰も気にしない、猫へようこそ。

ご注意


この記事では、新しい技術的知識や啓示を見つけることはできません。それらを切望する場合は、大胆に次の記事に進んでください。 それにもかかわらず、驚くべきことと考えるべきことがあります。 ライン間の技術的なユーモアと哲学的思考。

語られない物語...


開発者が運命が決定される場所に着いたら。 しばらくして、彼の前に画像が現れ、尋ねます:
-あなたは誰ですか?
-開発者である私は、Ivanに電話します
再び声:
-そこに行きたいですか? 。 ドアを見ると、その先には楽園があります。
「ええ 、」I病なアイヴァン。
-何を教えてくれますか? -声を尋ねます。
少し考えた後、イヴァンは言い始めます:
-java Enum-Almightyにあります。
-どうして、全能? -声をinさせます。 -これは単なるリストです!

public enum JavaLanguage { JAVA("Forever"), SCALA("Next generation") {}, KOTLIN("Future") {}; private final String claim; JavaLanguage(String claim) { this.claim = claim; } public String getClaim() { return claim; } } 

-はい 、-開発者は答えますが、 それだけではありません。
-それを証明してください!
-爪、スクラップ墓のような列挙。

 public enum LanguageUtils { ; /** java-doc */ LanguageUtils() { throw new IllegalStateException("  "); } /** java-doc */ public static String[] getKeyWords(String languageName) { if (languageName != null) { //    return loadFromResource(languageName + "/keywords.dat"); } throw new IllegalStateException("  "); } /** java-doc */ private static synchronized String[] loadFromResource(String resourceName) { String[] items = null; //    return items; } /**     */ } 

「それで奇跡ですが、彼には相続人がいません!」
-そして、これが見方です。 そして、誰が相続人と見なされるべきですか? スカラ? コトリン?
-開発者が質問を完了するまで待たずに例を挙げてください

  //  JavaLanguage.java  public static void main(String[] args) { // it's true if (JAVA.getClass() == SCALA.getClass().getSuperclass()) { System.out.println("  !"); } // it's true if (JAVA.getClass() == KOTLIN.getClass().getSuperclass()) { System.out.println("  !"); } } 

-ええ、あなたたちはおもしろいです、プログラマー -すでに笑って、声を言います-しかし何か小さなものがあるでしょう
カブをひっかいた後、イヴァンは続けました:
-列挙、工場があります!
-いいえ、すでにありました。
Ivanの最後の切り札を取得する必要がありました
-Enum-Singleton、確かに!
あなたを選択してください
あなたはJavaのためですか?
 public enum Highlander { JAVA; Highlander() { if (ordinal() != 0) { throw new IllegalStateException("     "); } init(); } private void init() { //  ! } /** java-doc */ public String getOwner(String index) { //   return " , Sun Microsystems"; } } 

Scalaをご利用ですか?
 public enum Highlander { SCALA {}; Highlander() { if (ordinal() != 0) { throw new IllegalStateException("     "); } init(); } private void init() { //  ! } /** java-doc */ public String getOwner(String index) { //   return " ,    "; } } 

あなたはコトリンのためですか?
 public enum Highlander { KOTLIN {}; Highlander() { if (ordinal() != 0) { throw new IllegalStateException("     "); } init(); } private void init() { //  ! } /** java-doc */ public String getOwner(String index) { //   return " , JetBrains"; } } 


-Joshua Bloch氏は、これがシングルトンの最高の実装であると述べています。
-さて、あなたは?
-私は何ですか? これ、これ-これは、単一の要素、ポンドポンドを格納するシングルトン工場です...

 Highlander.valueOf("JAVA"); 
これは、配列にアクセスして1つの要素、ポンドポンドを格納するポイントです...

 Highlander.values()[0]; 

これはクラスの相続人です... 、イヴァンは続けたいと思っていましたが、うれしい驚きでした。
-さあ...

いくつかの結論


合計すると、ビューポイントに応じて、enumには次の品質とプロパティを付与できます。


実験


列挙要素を生成できることを理解することにしました。 私自身の答えと現実は非常に異なっていたので、自分の知識を疑っていました。 以下を見る前に、自分で答えてみてください。 簡略化して、少なくとも順序を教えてください。 列挙クラスを生成するために使用したコードを次に示します(クイックリファレンス用)。

コード生成列挙型?
 package com.enums; import java.io.*; public class EnumGeneratorShort implements Closeable { private BufferedWriter writer; public EnumGeneratorShort(File outputFile) throws IOException { writer = new BufferedWriter(new FileWriter(outputFile)); } void append(String line) throws IOException { writer.append(line); } void appendLine(String line) throws IOException { writer.append(line).append("\n"); } @Override public void close() throws IOException { if (writer != null) { writer.close(); } } /**   enum*/ private static final int ENUM_COUNT = XXXX; //  XXXX -  private static final char[] ALPHABET = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; public static void main(String[] args) throws IOException { System.out.println("Start generation"); File outputFile = new File("src/main/java/com/enums/BigEnumShort.java"); try (EnumGeneratorShort enumGen = new EnumGeneratorShort(outputFile)) { enumGen.appendLine("package com.enums;"); enumGen.appendLine(""); enumGen.appendLine("public enum BigEnumShort {"); enumGen.append("A"); int index = 1; for (; index < ENUM_COUNT; index++) { enumGen.appendLine(","); String name = getName(index, ""); if ("if".equals(name) || "do".equals(name)) { name = getName(++index, ""); } enumGen.append(name); } enumGen.appendLine(";"); enumGen.appendLine(""); enumGen.appendLine(" public static void main(String[] args) {"); enumGen.appendLine(" System.out.println(\"Find enum \" + BigEnumShort.valueOf(\"B\"));"); enumGen.appendLine(" }"); enumGen.appendLine("}"); System.out.println("End generation. Total " + index); } } public static String getName(int index, String before) { if (index < ALPHABET.length) { return before + ALPHABET[index]; } int tail = index / ALPHABET.length; int current = index % ALPHABET.length; return getName(tail, before + ALPHABET[current]); } } 

すでに推測しましたか? そのため、7つで合計2746の列挙要素を生成できました。 そして、これ:

Error_3
合計5000
[エラー]ゴールの実行に失敗しましたorg.apache.maven.plugins:maven-compiler-plugin:3.1:プロジェクトbigenumでのコンパイル(default-compile):コンパイルの失敗
[エラー] /home/XXX/temp/BigEnum/bigenum/src/main/java/com/enums/BigEnumShort.java:[4,1] code too large

しかし、私は唇を4つのフロアに転がしたので、最初はこのエラーが発生しました。

Error_1
合計134217727
1つのソースファイルを/ home / XXX / temp / BigEnum / bigenum / target / classesにコンパイルする
コンパイラで例外が発生しました(1.7.0_51)。 バグパレードの重複を確認した後、Java Developer Connection(http://java.sun.com/webapps/bugreport)でバグを提出してください。 レポートにプログラムと次の診断を含めます。 よろしくお願いします。
java.lang.IllegalArgumentException

そして、次のように少しひねります:

Error_2
合計8388607
エラー]ゴールの実行に失敗しましたorg.apache.maven.plugins:maven-compiler-plugin:3.1:プロジェクトbigenumでコンパイル(default-compile):コンパイル失敗:コンパイル失敗:
[エラー] /home/XXX/temp/BigEnum/bigenum/src/main/java/com/enums/BigEnumShort.java:[4,1] code too large
[エラー] /home/XXX/temp/BigEnum/bigenum/src/main/java/com/enums/BigEnumShort.java:[3,8] too many constants

また、このような列挙が有名な逆コンパイラをどのように消化できるかにも興味がありました。 期待の総合的な主観的評価:
場所逆コンパイラ結果
1fernflower.jarわかった
2ヤッドわかった
3procyon待った
4cfr_0_115.jar待たなかった

ご清聴ありがとうございました。

ソースとインスピレーション


効果的なJava、第2版、Joshua Bloch *
ウィキペディア
Javaの正しいシングルトン
apanasevichによるコメント
シリキッドによるコメント

Source: https://habr.com/ru/post/J321152/


All Articles