Javaでメソッドに送信される引数は、呼び出し元メソッドの元のデータ構造を指しているため、Cなどの他の言語の標準と同様に、設計者はそれらを複数の値を返すために使用することを意図していましたか? ?
それとも、これは変数がポインタであるというJavaの一般的なプロパティの危険な誤用ですか?
ずっと前に、Ken Arnold(Javaチームの1回のメンバー)と会話しました。これは最初のJava 1つの会議でした。 、だから1996年。彼はあなたが次のようなものを書くことができるように複数の戻り値を追加することを考えていると言った:
x, y = foo();
当時および現在の推奨される方法は、複数のデータメンバーを持つクラスを作成し、代わりにそれを返すことです。
それと、Javaに携わった人々からのその他のコメントに基づいて、渡された引数を変更するのではなく、クラスのインスタンスを返すことが意図されていると思います。
これは一般的な方法です(Cプログラマーが引数を変更したいという願望があるように...最終的にはJava通常の方法です。構造体を返すと考えてください。:- )
(以下のコメントに基づいて編集)
私はファイルを読み取り、String型とint型の2つの配列を生成し、各行から両方の要素を1つ選択しています。この方法で分割するファイルを呼び出す関数に両方を返したいと思います。
私があなたを正しく理解しているなら、私はおそらくこのようなことをするだろうと思います:
// could go with the Pair idea from another post, but I personally don't like that way
class Line
{
// would use appropriate names
private final int intVal;
private final String stringVal;
public Line(final int iVal, final String sVal)
{
intVal = iVal;
stringVal = sVal;
}
public int getIntVal()
{
return (intVal);
}
public String getStringVal()
{
return (stringVal);
}
// equals/hashCode/etc... as appropriate
}
次に、次のようなメソッドを使用します。
public void foo(final File file, final List<Line> lines)
{
// add to the List.
}
そしてそれをこのように呼びます:
{
final List<Line> lines;
lines = new ArrayList<Line>();
foo(file, lines);
}
私の意見では、パブリックメソッドについて話している場合は、戻り値を表す別のクラスを作成する必要があります。別のクラスがある場合:
Point
クラス)渡された値を実際に変更するのではなく、常に新しいインスタンスを返すことを選択します。それは私にははるかに明確であり、不変性を支持します。
一方、内部メソッドの場合は、次のいずれかが使用される可能性があると思います。
new Object[] { "str", longValue }
_)Arrays.asList(...)
は不変のリストを返します)それでも、適切なコンストラクターを備えた最後のオプションをお勧めします。これは、同じタプルを複数の場所から返す場合に特に当てはまります。
主にこの理由で、JDKにPair<E,F>
クラスがあったらいいのにと思います。 Map<K,V>.Entry
がありますが、インスタンスの作成は常に大きな苦痛でした。
Pair
が必要なときにcom.google.common.collect.Maps.immutableEntry
を使用するようになりました
1999年に立ち上げられたこのRFEを参照してください。
http://bugs.Sun.com/bugdatabase/view_bug.do?bug_id=4222792
Java言語でそれを許可するつもりはなかったと思います。複数の値を返す必要がある場合は、それらをオブジェクトにカプセル化する必要があります。
Scalaのような言語を使用しますが、タプルを返すことができます。以下を参照してください。
http://www.artima.com/scalazine/articles/steps.html
Javaでジェネリックスを使用してオブジェクトのペアを返すこともできますが、それはAFAIKについてです。
編集:タプル
これにもう少し追加するだけです。 JDKが不足しているため、以前はプロジェクトにペアを実装しました。私の実装へのリンクはここにあります:
http://pbin.oogly.co.uk/listings/viewlistingdetail/5003504425055b47d857490ff73ab9
これにはハッシュコードまたは同等のものがないことに注意してください。おそらく追加する必要があります。
また、タプル機能を提供するこの質問について調査しているときに、これに遭遇しました。
他のタイプのタプルを含むペアを作成できます。
本当に複数の値を返すことはできませんが、canオブジェクトをメソッドに渡し、メソッドにそれらの値を変更させることができます。それは完全に合法です。オブジェクトを渡して、オブジェクト自体を別のオブジェクトにすることはできないことに注意してください。あれは:
_private void myFunc(Object a) {
a = new Object();
}
_
temporaryおよびlocallya
ですが、これによって呼び出し元の値が変更されることはありません。たとえば、次のようになります。
_Object test = new Object();
myFunc(test);
_
MyFuncが戻ると、oldオブジェクトが作成され、新しいオブジェクトは作成されません。
法的な(そしてしばしば落胆する)のは次のようなものです:
_private void changeDate(final Date date) {
date.setTime(1234567890L);
}
_
理由でDate
を選びました。これは、人々が広く同意するクラスであり、変更可能であってはなりません。上記のメソッドは、渡されたDate
オブジェクトの内部値を変更します。この種のコードは、メソッドが渡されるものを変更、構成、または変更することが非常に明確な場合に合法です。
注:一般的に、メソッドは次のいずれかを実行する必要があると言われています。
Collections.sort()
など)を変更するか、またはCollections.min()
など)、またはCollections.checkedList()
やCollections.singleton()
など)Collections
には例がありませんが、StringBuilder.append()
が良い例です)。着信オブジェクトを変更するメソッドおよびが個別の戻り値を返すメソッドは、多くの場合、多くのことを実行します。
パラメータとして渡されたオブジェクトを変更するメソッドは確かにあります( 例としてJava.io.Reader.read(byte [] buffer) を参照)が、の代わりに使用されるパラメータを見たことがありません。特に複数のパラメータがある場合の戻り値。技術的には機能する可能性がありますが、非標準です。
これは一般的にひどく良い習慣とは考えられていませんが、これが行われるJDKでは非常にまれなケースがあります。 View.getNextVisualPositionFrom()の「biasRet」パラメーターと関連するメソッドを見てください。たとえば、これは実際には「追加の戻り値」で埋められる1次元配列です。
では、なぜこれを行うのですか?さて、あなたを救うために、「時折余分な戻り値」のための余分なクラス定義を作成する必要があります。それは乱雑で、エレガントでなく、デザインが悪く、オブジェクト指向ではなく、何とか何とかです。そして、私たちは皆、時々それをしました...
メソッドパラメータとして一連の検証voidメソッドをカスケードするResultオブジェクトがありました。これらの検証voidメソッドはそれぞれ、結果パラメーターオブジェクトを変更して、検証の結果を追加します。
ただし、voidメソッドをスタブして、Resultオブジェクトの検証用のスタブ値を返すことができないため、これをテストすることはできません。
したがって、テストの観点からは、メソッドパラメータを変更するのではなく、オブジェクトを返す方がよいように思われます。
一般的にエディが言ったことですが、もう1つ追加します。