web-dev-qa-db-ja.com

Javaのメソッドから異なるタイプのデータを返しますか?

_public static void main(String args[]) {
    myMethod(); // i am calling static method from main()
 }
_

_public static ? myMethod(){ // ? = what should be the return type
    return value;// is String
    return index;// is int
}
_

myMethod()は、Stringとint値を返します。したがって、これらの戻り値をmain()から取得します。次の解決策を思い付きました。

クラス呼び出しReturningValuesを作成します

_public class ReturningValues {
private String value;
private int index;

// getters and setters here
}
_

myMethod()を次のように変更します。

_ public static ReturningValues myMethod() {
    ReturningValues rv = new ReturningValues();
    rv.setValue("value");
    rv.setIndex(12);
    return rv;
}
_

今私の質問、これを達成する簡単な方法はありますか?

最後に、戻り値の型の数が増えると、この種の実装が最善の方法でそれを行うため、私の方法がより良いと思いました。

public static ReturningValues myMethod() {
ReturningValues rv = new ReturningValues();
rv.setValue("value");
rv.setIndex(12);
return rv;
}

Enumを使用してさまざまな戻り値の型を作成します。自動的に定義されません。その実装は、ファクトリパターンのように見えます。

public  enum  SmartReturn {

    IntegerType, DoubleType;

    @SuppressWarnings("unchecked")
    public <T> T comeback(String value) {
        switch (this) {
            case IntegerType:
                return (T) Integer.valueOf(value);
            case DoubleType:
                return (T) Double.valueOf(value);
            default:
                return null;
        }
    }
}

単体テスト:

public class MultipleReturnTypeTest {

  @Test
  public void returnIntegerOrString() {
     Assert.assertTrue(SmartReturn.IntegerType.comeback("1") instanceof Integer);
     Assert.assertTrue(SmartReturn.DoubleType.comeback("1") instanceof Double);
  }

}
20
Wendel

いいえ。Javaメソッドは1つの結果(void、プリミティブ、またはオブジェクト)のみを返すことができ、このようなstruct- typeクラスの作成はまさにどうやるのですか。

注として、次のようにReturningValuesのようなクラスを不変にすることができます。

public class ReturningValues {
    public final String value;
    public final int index;

    public ReturningValues(String value, int index) {
        this.value = value;
        this.index = index;
    }
}

これには、スレッド間などでReturningValuesを渡すことができるという利点があり、誤って同期が取れなくなる心配はありません。

16
chrylis

通常、返される値がわからない場合は、すべての戻り値のスーパークラスとしてreturn-typeの使用を検討する必要があります。この場合、Stringまたはintを返す必要がある場合は、Objectクラス(Javaで定義されているすべてのクラスの基本クラス)を返すことを検討してください。

ただし、このメソッドを呼び出しているところでinstanceofチェックを使用するよう注意してください。または、ClassCastExceptionになってしまう可能性があります。

public static void main(String args[]) {
        Object obj = myMethod(); // i am calling static method from main() which return Object
    if(obj instanceof String){
    // Do something
    }else(obj instance of Integer) {
    //do something else
     }
6
Ankur Shanbhag

あなたが取ったアプローチは良いです。実装を改善する必要がある場合があります。たとえば、ReturningValuesは適切に定義する必要があり、ReturningValuesをimmutableとして作成できる場合は、その方が適切です。

// this approach is better
public static ReturningValues myMethod() {
    ReturningValues rv = new ReturningValues("value", 12);
    return rv;
}


public final class ReturningValues {
    private final String value;
    private final int index;


    public ReturningValues(String value, int index) {
      this.value = value;
      this.index = index;
     }

} 

または、キーと値のペアがたくさんある場合は、HashMapを使用できます

public static Map<String,Object> myMethod() {
  Map<String,Object> map = new HashMap<String,Object>();
  map.put(VALUE, "value");
  map.put(INDEX, 12);
  return Collections.unmodifiableMap(map); // try to use this 
}
2
veritas

これは解決策の1つです。しかし、現在のソリューションで十分です。また、新しい変数を追加しても、それをクリーンに保つことができます。これは現在のコードでは実行できません。

private static final int INDEX_OF_STRING_PARAM = 0;
private static final int INDEX_OF_INT_PARAM = 1;

public static Object[] myMethod() {
    Object[] values = new Object[2];
    values[INDEX_OF_STRING_PARAM] = "value";
    values[INDEX_OF_INT_PARAM] = 12;
    return values;
}
1
Narendra Pathai

私は自分の意見を述べたいだけです

したがって、汎用の戻り値型を作成し、さまざまなタイプの具体的な戻り値型で実装する必要があります。 Serviceクラスは、さまざまなタイプのオブジェクトコンクリートクラスを作成し、ジェネリックタイプとして返​​すことができます。

public interface GenericReturnType{
    public static RETURN_TYPE enum{
        MACHINE, PERSON;    
    }
    public RETURN_TYPE getReturnType();
}

public class PersonReturnType implements GenericReturnType{
    // CONSTRUCTORS //

    // GETTRE AND SETTER //

    public RETURN_TYPE getReturnType(){
        return PERSON;
    }
    public String getAddress(){
        return something;
    }
}

public class MachineReturnType implements GenericReturnType{
    // CONSTRUCTORS //

    // GETTRE AND SETTER //

    public RETURN_TYPE getReturnType(){
        return MACHINE;
    }
    public String getManufatureName(){
        return something;
    }
}


public class TestService{
    public GenericReturnType getObject(// some input //){
        GenericReturnType obj ;
        if(// some code //){
            obj = new  PersonReturnType();
            // some code //
        }
        if(// some code //){
            obj = new  MachineReturnType();
            // some code //
        }
        return obj;
    }
}

public class TestDriver{
    TestService service = new TestService();
    GenericReturnType genObj = TestService.getObject(// some input //);
    if(genObj.getReturnType() == RETURN_TYPE.MACHINE){
        // SOME CODE // 
    }
    if(genObj.getReturnType() == RETURN_TYPE.PERSON){
        // SOME CODE // 
    }
}
1
ParagFlume

オブジェクトとして返すことができます。そのオブジェクトを「オンザフライ」で作成します

function: if(int) 
 return new object(){
   int nr=..
}

文字列についても同じです。しかし、私はそれが高価なソリューションであることを心配しています...

1
Botea Florin

@ruchira ur solution it self best。しかし、整数と文字列だけであれば、非常に簡単で簡単な方法でそれを行うことができると思います。

 class B {   
    public String myfun() {         
        int a=2;           //Integer .. you could use scanner or pass parameters ..i have simply assigned
        String b="hi";      //String
        return Integer.toString(a)+","+b; //returnig string and int with "," in middle          
    }       
}

class A {    
    public static void main(String args[]){

        B obj=new B();  // obj of class B with myfun() method  
        String returned[]=obj.myfun().split(",");
             //splitting integer and string values with "," and storing them in array   
        int b1=Integer.parseInt(returned[0]); //converting first value in array to integer.    
        System.out.println(returned[0]); //printing integer    
        System.out.println(returned[1]); //printing String
    }
}

私はそれが有用だったことを望みます.. :)

0

お探しのクラスは既に存在します。 Map.Entry

public static Entry<Integer,String> myMethod(){
    return new SimpleEntry<>(12, "value");
}

以降:

Entry<Integer,String> valueAndIndex = myMethod();
int index = valueAndIndex.getKey();
String value = valueAndIndex.getValue();

キーと値を格納する単純な2フィールドのデータ構造です。特別な処理を行う必要がある場合、3つ以上のフィールドを保存する場合、またはその他のフリンジケースがある場合は、独自のクラスを作成する必要がありますが、それ以外の場合はMap.Entryは、利用率の低いJavaクラスの1つであり、このような状況に最適です。

0
ndm13

私はこれが遅れていることを知っていますが、これに対する答えを探しに来る誰かに役立つと思いました。 Bundleを使用して、別のメソッドを作成せずに複数のデータ型値を返すことができます。私はそれを試し、完璧に働きました。

メソッドを呼び出すMainActivityで:

Bundle myBundle = method();
String myString = myBundle.getString("myS");
String myInt = myBundle.getInt("myI");

方法:

public Bundle method() {
    mBundle = new Bundle();
    String typicalString = "This is String";
    Int typicalInt = 1;
    mBundle.putString("myS", typicalString);
    mBundle.putInt("myI", typicalInt);
    return mBundle;
}

追伸:このようなバンドルを実装しても大丈夫かどうかはわかりませんが、私にとっては完璧に機能しました。

0
Dante