質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.31%
Java

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

Q&A

解決済

4回答

665閲覧

Javaで複数の型を戻り値として指定できないでしょうか?

shark-

総合スコア3

Java

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

1グッド

0クリップ

投稿2025/03/31 09:48

編集2025/03/31 11:22

実現したいこと

例えば
public String | Error method(){}

のように状況に応じてどちらかの型を返すように指定したいです。

試したこと

下記のような記述をすれば、一応状況に応じて処理ができそうなのですが、もっと合理的な方法などがあれば知りたいです。

Result.java

1class Result<R1, R2, R3> { 2 private R1 r1 = null; 3 private R2 r2 = null; 4 private R3 r3 = null; 5 6 public Result(R1 r1, R2 r2, R3 r3) { 7 this.r1 = r1; 8 this.r2 = r2; 9 this.r3 = r3; 10 } 11 12 public boolean isExistR1() { 13 return r1 != null; 14 } 15 16 public boolean isExistR2() { 17 return r2 != null; 18 } 19 20 // 省略 21 22 public R1 getR1() { 23 return r1; 24 } 25 26 public R2 getR2() { 27 return r2; 28 } 29 30 // 省略 31}

Main.java

1public class Main { 2 public static void main(String[] args) { 3 Result<String, Integer, Boolean> result = new Result<>("hello", null, null); 4 // Result<String, Integer, Boolean> result = new Result<>(null, 2, null); 5 if (result.isExistR1()) { 6 System.out.println(result.getR1()); 7 } else if (result.isExistR2()) { 8 System.out.println(result.getR2()); 9 } 10 } 11}
xail2222👍を押しています

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

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

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

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

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

dodox86

2025/03/31 10:32

「どちらかの型」を呼び出し側が意識することになるのが必然のように思うので、返り値はObjectを継承した何らかのクラスか、もうすこしインテリジェント(?)にするのであれば、interfaceを返すなりすればどうでしょうか。
shark-

2025/03/31 11:06

ご回答ありがとうございます! 「返り値をObjectを継承したクラスにする」と「interfaceを返す」それぞれの方法について考えてみたのですが、具体的な実装方法がいまいち掴めていません。 もし可能でしたら、サンプルコードなどを交えて詳しく教えていただけますでしょうか?
guest

回答4

0

public String | Error method(){}

正常値かエラーかというなら、普通の java ならエラーは例外を使うのでは無いでしょうか。

投稿2025/04/01 02:24

jimbe

総合スコア13318

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

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

shark-

2025/04/03 11:27

ご回答ありがとうございます! すみません、質問の仕方が悪かったです。 戻り値としてString型やint形などが返る場合について考えていました。 エラーの場合は例外処理を使うというのはその通りだと思います!
jimbe

2025/04/03 15:42 編集

呼び出し側で「返されたのは A ですか? B ですか? それとも…」と判断して処理を分けなければならないようでは Object r = method(); if(r instanceof String) {} else if(r instanceof Integer) {} else … と大して変わらない気がします。 多様な型の結果というものを(統一的に?)どう扱いたいのか、本当に多様な型を返すメソッド(という設計)で良いのかと言ったところから見直すやり方もあるかなと思います。
guest

0

ベストアンサー

Either型を定義してみる、とか。

投稿2025/03/31 11:19

shiketa

総合スコア4110

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

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

shark-

2025/03/31 12:01 編集

ご回答ありがとうございます! Either というものがあることを初めて知りました! Javaの場合はこれが一番良い方法だと思いました!
guest

0

既に回答もいただいていて質問者 satouさんも納得され、ベストアンサーで閉じた質問ですが、当方でも別解で途中まで試していたので、放流しておきます。

尚、質問の件名は「Javaで複数の型を戻り値として指定」とありましたが、質問文中には以下のようにありましたので

public String | Error method(){}

のように状況に応じてどちらかの型を返すように指定したいです。

2つ以上(すなわち複数)の型の内、状況に応じていずれかの型(クラス)とのように解釈しての回答です。

質問へのコメント欄において私の[2025/03/31 19:32]のコメント

「どちらかの型」を呼び出し側が意識することになるのが必然のように思うので、返り値はObjectを継承した何らかのクラスか、もうすこしインテリジェント(?)にするのであれば、interfaceを返すなりすればどうでしょうか。

に沿って考えていましたが、Objectの継承、あるいはinterfaceの使用を包括し、戻り値を求めることからSupplierインターフェースが適当ではないかと考えました。

Supplier - Java Platform SE 8

そのサンプルコードと実行例を示します。

java

1import java.util.function.Supplier; 2 3public class Main6 { 4 public static void main(String[] args) { 5 Main6 main = new Main6(); 6 // 状況(condition)に応じて返す型が変わるテスト 7 for (int condition = 0; condition <= 4; condition++) { 8 System.out.println(condition + " --------"); 9 10 Supplier<?> result = main.doSomething(condition); 11 System.out.println("Supplier classname: " + result.getClass().getName()); 12 Object obj = result.get(); 13 System.out.println("Object classname: " + obj.getClass().getName()); 14// System.out.println(obj.toString()); 15 System.out.println("[" + obj + "]"); 16 } 17 } 18 19 public Supplier<?> doSomething(int condition) { 20 Supplier<?> valueSupplier = null; 21 switch (condition) { 22 case 0: 23 // String 24 valueSupplier = () -> "This is a string!"; 25 break; 26 27 case 1: 28 // Integer 29 valueSupplier = () -> 123; 30 break; 31 32 case 2: 33 // Double 34 valueSupplier = () -> 456.789; 35 break; 36 37 case 3: 38 // ユーザー定義のクラスResult1 39 valueSupplier = new Result1(); 40 break; 41 42 case 4: 43 // ユーザー定義のクラスResult2 44 valueSupplier = new Result2(); 45 break; 46 47 default: 48 valueSupplier = () -> "Default case!"; 49 break; 50 } 51 return valueSupplier; 52 } 53 54 class Result1 implements Supplier<String> { 55 // Supplierで実装するgetメソッド 56 @Override 57 public String get() { 58 return "This is Result1 string!"; 59 } 60 61 @Override 62 public String toString() { 63 return "Result1 instance"; 64 } 65 } 66 67 class Result2 implements Supplier<Result2> { 68 // Supplierで実装するgetメソッド 69 @Override 70 public Result2 get() { 71 return this; 72 } 73 74 @Override 75 public String toString() { 76 return "Result2 instance"; 77 } 78 } 79}

古いバージョンのJavaでも使えることを示すため、Java SE8(1.8)でも使えるようオプションを指定してコンパイルし、実行します。Windows 10のPowerShell上で操作しています。

terminal

1PS C> javac -version 2javac 23.0.1 3PS C> java -version 4openjdk version "23.0.1" 2024-10-15 5OpenJDK Runtime Environment (build 23.0.1+11-39) 6OpenJDK 64-Bit Server VM (build 23.0.1+11-39, mixed mode, sharing) 7 8PS C> javac --release 8 .\Main6.java 9警告: [options] ソース値8は廃止されていて、今後のリリースで削除される予定です 10警告: [options] ターゲット値8は廃止されていて、今後のリリースで削除される予定です 11警告: [options] 廃止されたオプションについての警告を表示しないようにするには、-Xlint:オプションを使用します。 12警告3個 13 14PS C> java Main6 150 -------- 16Supplier classname: Main6$$Lambda/0x000001be86000a10 17Object classname: java.lang.String 18[This is a string!] 191 -------- 20Supplier classname: Main6$$Lambda/0x000001be86000c30 21Object classname: java.lang.Integer 22[123] 232 -------- 24Supplier classname: Main6$$Lambda/0x000001be86001000 25Object classname: java.lang.Double 26[456.789] 273 -------- 28Supplier classname: Main6$Result1 29Object classname: java.lang.String 30[This is Result1 string!] 314 -------- 32Supplier classname: Main6$Result2 33Object classname: Main6$Result2 34[Result2 instance] 35PS C>

Suppliergetメソッドで返すインスタンスが今回の質問で要望されている「複数の値の内、いずれか」に相当するものですが、返されたインスタンスのクラスが変数conditionで示す状況により変わっていることが分かると思います。

投稿2025/04/02 00:52

dodox86

総合スコア9369

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

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

shark-

2025/04/03 11:54

ご回答ありがとうございます! 詳細に教えていただき助かりました! 大変参考になりました! ありがとうございます!
guest

0

Javaで複数の型を戻り値として指定できないでしょうか?

できませんねー

投稿2025/03/31 09:53

y_waiwai

総合スコア88168

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

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

shark-

2025/03/31 11:35

ご回答ありがとうございます! やっぱり難しそうですね…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問