web-dev-qa-db-ja.com

Java 7で文字列をオンにする利点は何ですか?

私がJavaでプログラミングを始めたとき、switchステートメントが文字列を取らないという事実は私を苛立たせました。次に、Enumを使用する際に、生の値を渡すのではなく、型の安全性(リファクタリングが容易になる)と他の開発者にわかりやすさを提供するよりも、Enumを使用するメリットを実感しました。

SE7で、Enumsではなく文字列を入力として持つスイッチを使用することを決定する状況を考えるのに苦労しています。文字列全体の切り替え(たとえば、部分一致や正規表現の一致ではなく)を介して実装されている場合、コードが変更される理由はそれほど多くないようです。

また、IDEツールとコーディングの読み取り/書き込み比率を使用すると、文字列値を渡すよりも、余分なEnumを自動生成するほうがはるかに便利です。

彼らはプログラマーとして私たちにどんな利益をもたらしますか?ボイラープレートが少ない?

言語がこの機能を求めていたようには思えません。多分私は見落としているユースケースがあります。

19
anotherdave

私が知る限り、問題は、文字列定数を列挙型にラップすることが言語ユーザーのニーズをカバーするのに十分であると見なされなかった理由です。これは、JDK 7(プロジェクトコイン)メーリングリストで発表された公式の 機能提案 で対処されています。

私の提案を読んだところ、列挙型を使用する代わりの方法は、型膨張を導入しているという理由で却下されました。便宜上、提案の関連部分を以下に引用します。ステートメントのアドレス指定列挙体はboldで引用されています。

主要な利点:提案を有利な変更にしたのはなぜですか?

一定の文字列値のセットに基づいて選択された操作には、より規則的なコーディングパターンを使用できます。新しい構成の意味は、Java開発者には明らかです。

主要なメリット:提案が採用された場合、プラットフォームが優れているのはなぜですか?

文字列ベースのディスパッチコードのパフォーマンスが向上する可能性があります。

主な欠点:常にコストがかかります。

コンパイラの実装とテストの複雑さが増しました。

代替案:言語の変更なしに、利点と利点を何らかの方法で得ることができますか?

番号;文字列の等価性に関するチェーニングされたif-then-elseテストは潜在的にコストがかかり、対象の文字列値ごとに1つの切り替え可能な定数の列挙型を導入すると、正当な原因なしに別の型がプログラムに追加されます...

12
gnat

コードを読みやすくすることとは別に、_if/else if_の比較に比べてパフォーマンスが向上する可能性があります。変更が価値があるかどうかは、比較をいくつ行うかによって異なります。文字列スイッチは、2つの個別のスイッチ命令として発行されます。 1つ目はハッシュコードで動作するため、lookupswitchになる傾向があり、最終的にはO(log n)の複雑さになります。 2番目は常に完全なO(1)tableswitchなので、結合された複雑さはO(log n)のままです。 _if/else if_ステートメントの単一の線形チェーンは、O(n)の複雑さをやや悪化させます。

たとえば、3つ以上の文字列を比較する場合は、switchの方が読みやすくコンパクトです。ホットコードパスで多数の比較を行わない限り、違いに気付くことはほとんどありませんが、パフォーマンスはおそらく向上します。

7
Mike Strobel

文字列のスイッチは、enumの値が外部から取得された場合、つまりデータベースに格納されている場合に使用できます。

JDK 7のもう1つの注目すべき点は、switchif-else構成よりもパフォーマンスがはるかに優れていることです。

また、ノードと属性タイプで多くのスイッチを作成する必要がある場合、高速な文字列switchesの素晴らしい使用例は、JSON/XMLストリームの解析です。これにはこれ以上の選択肢はありません。

3
Andrey Chaschev

シンプルさ

Switchサポートの文字列は、enumまたはif-elseロジックに変換せずにデータを処理するのに役立ちます。文字列をオンにする方が簡単な場合もあります。

JDK 7(project Coin)メーリングリストでの機能提案@ gnat answer )から

対象の文字列値ごとに1つ、その切り替え可能な定数の列挙型を導入すると、正当な理由なしにプログラムに別の型が追加されます...

If-Elseバージョン

これは短いですが、多くのif'sは読みにくいです。そして、これは遅いです。

if (color.equals("red")) {
    System.out.println("Color is Red");
} else if (color.equals("green")) {
    System.out.println("Color is Green");
} else {
    System.out.println("Color not found");
}

列挙型バージョン

列挙型を定義する必要がありますが、これは適切ですが、場合によっては必要ありません。

enum Color {RED, GREEN}

通常通りの処理

try {
    switch (Color.valueOf(color)) {
        case RED:
            System.out.println("Color is Red");
            break;
        case GREEN:
            System.out.println("Color is Green");
            break;
    }
} catch (IllegalArgumentException e) {
    System.out.println("Color not found");
}

JDK 7-switchステートメントバージョンの文字列

追加のタイプを変換および定義せずに処理できます。

switch (color) {
    case "red":
        System.out.println("Color is Red");
        break;
    case "green":
        System.out.println("Color is Green");
        break;
    default:
        System.out.println("Color not found");
}
2

どの言語でもほとんどの改善はコードを読みやすくすることです。私は、空想よりも可読性の高いコードを好む。

これは信じられないかもしれませんが、次のことを試してください。

public enum JettStaff {
  ADRIAN("Adrian German") {
    public String toString() {
      return name + " ([email protected])";
    }
  },
  ARJIT("Arjit Sengupta") {
    public String toString() {
      return name + " ([email protected])";
    }
  },

  // and on for the rest...

  private String name;

  public JettStaff(String n) { this.name = n; }
}

JettStaff x = JettStaff.SUZANNE;
System.out.println(x);
0
user2860598

列挙型は素晴らしいので、可能であれば文字列の代わりに列挙型を使用する必要があります。ただし、Javaの外部からの外部オブジェクトを処理する必要がある場合など、実行できない場合もあります。何かを解析する必要があると想像してください。サーバーの応答、構成、ログファイルなどのように、探しているオプションがたくさんあり、それらを列挙する方法はありません。つまり、Java <7では、

  if (something.equals("foo")) {
    // foo processing
  } else 
  if (something.equals("bar")) {
   // bar processing
  }

この場合でも、名前で取得しようとするか、カスタムのString-> Enumルーチンを提供することで列挙型を使用できますが、それが不可能な場合や、実用的でない場合もあります(つまり、作成する列挙型が多すぎる場合)。

[〜#〜] tldr [〜#〜]:純粋にJavaコードで作業している場合は、Enumsを使用する必要がありますが、外部オブジェクトでは常に使用できるとは限りません。私の説明が意味をなすことを願っています。

0
dimoniy

SwitchステートメントでStringsを使用すると、コードがよりクリーンで読みやすいとの意見には同意しません。これは、不適切なプログラミング手法だと思います。保存に使用する値を変更する場合は、スイッチまたはif-elseifの発生ごとに値を変更する必要があります。コードのすべての生成にハードコードされた値を置くので、これは良くありません。ある日、これらのハードコードされた値の1つを変更する場合はどうしますか?それのすべてのコピーを検索して置き換えますか?

If-elseifステートメントを実行するいくつかのハードコードされた値がある場合、それらに定数プリミティブ値を使用することは、Java 1.5より前のほうがタイプセーフになるため、はるかに優れています。

OK、(HTTPリクエストやファイルなどから)文字列値を取得し、それらをプリミティブ値に変換するのは簡単ではありません。しかし、Enumsはこの時点でうまく機能します。 Enumに格納する値を変更したいときは、宣言するときに変更するだけだからです。コードの他の部分を変更する必要はありません。 (もちろん、他の場所に保存されている値を変更する必要があります)。

汚くて怠惰なコードを実装しているだけなら、それは完璧です。たくさんのEnumsをコーディングする必要はありませんが、大規模で複雑なソフトウェアでは、あなたを殺します。

0
regulus