🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

4回答

2968閲覧

java switch文 case文を動的に増やす方法

kasai2_s_2_s

総合スコア8

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/03/30 04:30

javaのswitch,case文についての質問です。

case文の数を動的に決める方法はありますか?
私が実現したいのは、プログラム内で値が決まる変数numがあり、numの値の分のcase文を用意する。ということです。以下に実現したいプログラムのイメージを示します。

java

1int num = getNum(); 2 3switch (){ 4 case1: 5 ... 6 break; 7 case2: 8 ... 9 break; 10... 11 12 case 値num: 13 ... 14 break; 15}

どなたか詳しい方、ご教示いただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakaiY

2021/03/30 04:34

動的に増やすことは基本的にできないと思いますが、増やした時の処理本体(...になっているところ)にはどのような処理が入りますか? 内容によっては(というか、大抵は)、他の方法で実現できると思います。
K_3578

2021/03/30 04:36

処理次第です。一回思うように組んで動かしてみたらどうでしょう。
Luice

2021/03/30 04:53

変数numの値によって何がしたいか次第だと思います。 TakaiYさんの仰るとおりswitchでは難しくても、別の方法で実現する事は可能だと思います。
guest

回答4

0

ベストアンサー

java switch文 case文を動的に増やす方法

Javaの文法上、case文の値は定数値と決まっていることもあり、caseの部分を動的に増減することはできません。これは最新のJavaSE 16の言語仕様でも同様です。

Java SE16/Java Language and Virtual Machine Specification/Java SE16 - Oracle
14.11.1. Switch Blocks をご覧ください。

したがって、ご質問内容「case文の数を動的に決める方法はありますか?」を言葉どおり、そのままに受け止めると、「方法はありません。」となります。しかしながら他の方々の回答でも示されているように、代替の方法はあります。この回答ではHashMapConsumerインターフェースを使い、{値: その値に対応する処理}を動的に追加する方法をサンプルコードとしてご紹介します。このハッシュマップをswitchcasedefault部分で利用すれば、方法の良し悪しはさて置き、技術的にはやりたいことを実現することができるという例示です。

先に簡単に説明しておくと、Consumer (java.util.function.Consumer)とはあらかじめ用意された関数インターフェースのひとつで、指定した型の引数を1つだけ持ち、acceptと言うメソッドを実行できます。``accept`メソッドの実際の中身(処理内容)はプログラマーが定義します。最初は取っ付きにくいかもしれませんが、ラムダ式と共に理解すれば比較的気軽に使えるようになり、便利です。

Java

1import java.util.function.Consumer; 2import java.util.HashMap; 3 4public class Main { 5 6 private int field1 = 0; 7 8 private int method1() { 9 return 123; 10 } 11 12 private void run() { 13 HashMap<Integer, Consumer<Integer>> cases = new HashMap<>(); 14 15 Consumer<Integer> c1 = new Consumer<Integer>() { 16 @Override 17 public void accept(Integer v) { 18 System.out.println("動的に追加した" + v + "の処理"); 19 field1 = 2; 20 System.out.println("=== インスタンスフィールドを操作: " + field1); 21 System.out.println("=== インスタンスメソッドも呼べる: " + method1()); 22 } 23 }; 24 cases.put(3, c1); 25 26 // ラムダ式色々 27 Consumer<Integer> c2 = v -> System.out.println("動的に追加した" + v + "の処理"); 28 cases.put(4, c2); 29 cases.put(5, (v) -> System.out.println("動的に追加した" + v + "の処理")); 30 31 // ラムダ式であれば、(比較的自由に)メソッド内の変数も使える。 32 int v2 = 12345; 33 cases.put(6, (v) -> { 34 int v3 = v2 + 3; 35 System.out.println("動的に追加した" + v + "の処理 変数v3=" + v3); 36 }); 37 38 // case 0~7を実行してみる。 39 for (int num = 0; num <= 7; num++) { 40 switch (num) { 41 case 1: 42 System.out.println("組み込みのcase 1"); 43 break; 44 45 case 2: 46 System.out.println("組み込みのcase 2"); 47 break; 48 49 default: 50 // numに合致するものがあれば、accept()を呼び出し、処理を実行。 51 Consumer<Integer> c = cases.get(Integer.valueOf(num)); 52 if (c != null) { 53 c.accept(num); 54 } else { 55 System.out.println("!!! " + num + "の処理は存在しません。"); 56 } 57 break; 58 } 59 } 60 } 61 62 public static void main(String[] args) { 63 Main obj = new Main(); 64 obj.run(); 65 } 66}

これを実行すると以下のようになります。case 3~6相当の処理が実行されているのが分かります。

CMD

1C>java Main.java 2!!! 0の処理は存在しません。 3組み込みのcase 1 4組み込みのcase 2 5動的に追加した3の処理 6=== インスタンスフィールドを操作: 2 7=== インスタンスメソッドも呼べる: 123 8動的に追加した4の処理 9動的に追加した5の処理 10動的に追加した6の処理 変数v3=12348 11!!! 7の処理は存在しません。 12 13C>

Windows 10上で、Javaのバージョンは11( "11.0.9" 2020-10-20 LTS)で実行しました。コード自体はJava 8でも動きます。

投稿2021/03/30 18:18

dodox86

総合スコア9254

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

動的に増やすようなことはできません。
まあ、テーブルとループ使って判定させるってことでお望みのことができるかと思われます

投稿2021/03/30 04:53

y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こうするしかないですね、ということでは?

java

1int num = getNum(); 2 3switch () { 4case 1: 5 System.out.println("組み込みのcase 1"); 6 break; 7case 2: 8 System.out.println("組み込みのcase 2"); 9 break; 10default: 11 if (== num) { 12 // 上記定数のどれにも一致せず、かつ、getNum()の値と一致した場合の処理 13 } 14 break; 15}

投稿2021/03/31 01:24

FromMZ1500

総合スコア496

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/03/31 01:34

一周回って、こちらに落ち着くのが現実的かもしれませんね。一番良く見る、ある意味とても標準的なコードだと思います。
guest

0

いろんな方法が考えられます。

ただし、「条件次第」です。

とある条件下ではこれがいいけど、とある条件下では使えない……とか制限が強すぎる……のように場合によります。

一応、方向性のために書いておきます。


私がぱっと思いつく方法では、

方法1: 単純に分割する

たとえば、質問でいうgetNum関数……いやメソッドか。それみたいにする。

ただし、bool check(...) のような感じにしておく。(メソッド名は適当だが)

それで、

Java

1if( !check1( a ) ){ // check1 がだめなら 2 if( !check2( a ) ){ // check2でもダメなら 3 ... 4 } 5}

のようにする。

ただしコード例から見てもインデントが多くなるし、可読性も低い。

なので非推奨。
(もしかしたらやり方次第かもしれないが)

方法2: オブジェクト指向風でやる。

オブジェクト指向(以下 OOP) は、『データ(= フィールド) と処理(= メソッド)をひとまとめにしたオブジェクト』なるものを中心に見る発想法です。

オブジェクトだけがデータと処理を知っているという状態です。

なので、『オブジェクトだけが知っている』と言う状態で、言い換えると、『オブジェクトに任せる』のがOOP。

参考: よい子のC++(オブジェクト指向完全理解)

※ 上記サイトはC++での説明ですが、Javaでも発想自体は同じです。
単に メソッド => メンバ関数, フィールド => メンバ変数 と言い換えていたり、
書き方が違うだけです。

この方法では、『データ(あるいは変数)が分岐で変わる場合』に使えますね。

変数 a, b, c があって、条件1 のときは a, 条件2 のときは b, 条件3 のときは c と言う風に分岐する場合です。

方法3: デザインパターンの『ChainOfresponsibilityパターン』を適用する

ただし、この場合はクラスをそれぞれで実装するので、クラスファイルが増大します。

方法4: 諦めて、そのままべた書きする

そのままです。

投稿2021/03/30 05:07

BeatStar

総合スコア4962

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問