既に回答もいただいていて質問者 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>
Supplier
のget
メソッドで返すインスタンスが今回の質問で要望されている「複数の値の内、いずれか」に相当するものですが、返されたインスタンスのクラスが変数condition
で示す状況により変わっていることが分かると思います。