Javaバイトコードは強く型付けされ、検証されます。つまり、呼び出し元のコードは、呼び出されたメソッドが返すコードと互換性がなければなりません。したがって、呼び出し元のメソッド参照に期待される戻り値の型が含まれていなくても、コードには暗黙の前提が含まれていました。結果をlong
とすると、Object
またはvoid
ではなく、long
が返されることが予測されます。
期待される戻り値の型を示すメソッド参照は検証を単純化し、プロセス全体をより効率的にする。実際のリンケージを実行せずに、期待されるメソッドのシグネチャを使用してメソッドのコードの正しさを検証できます。最終的にメソッド呼び出し命令がリンクされている場合、実行可能コードを検証する必要はなく、シグネチャのみが一致しなければなりません。
これは、Javaのソースコードが少なくとも以前のバージョンでは異なる戻り値の型を定義できなくても、そのように設計された理由です。 Java 5以降、ルールはこれ以上厳しくありません。
は、以下のインターフェイスを検討:
interface StringFunction<R> {
R apply(String input);
}
起因タイプ消去には、それは、バイトコードレベルでの方法Object apply(String input)
を有するであろう。
ここで、次の実装クラスを考える:許可され、より具体的な戻り値の型を宣言しているだけでなく、
class Length implements StringFunction<Integer> {
public Integer apply(String input) {
return input.length();
}
}
ジェネリック型システムによると、それは継承として、それは実際には、Java言語でを必要とします抽象メソッドInteger apply(String)
からStringFunction<Integer>
。バイトコードレベルで
、それは実際の実装方法Integer apply(String)
だけでなく、正式にバイトコードレベルでのinterface
の契約を履行し、実際の実装方法に委譲Object apply(String input)
ブリッジメソッドを持つことになります。ジェネリックが有効戻り型の狭小化を可能にするため
、非ジェネリックメソッドのためにそれを否定する理由は存在しなかった、従って、Java(登録商標)は、いわゆる可能共変戻り型同様のJava 5以降:
class Base {
Object getValue() {
return null;
}
}
class Sub extends Base {
@Override String getValue() {
return "now a string";
}
}
です。オーバーロードではありませんが、同じパラメータタイプで異なる戻り値の型を持つ複数のメソッドを持つクラスを生成することは可能です。
これらのケースは、別の方法で処理することもできます。共変リターン・タイプと互換性があるように、それらのメソッドがパラメータ・タイプのみで区別され、その戻り値のタイプが同じか、またはより特定である必要があることを定義することによって、メソッド・テーブルの構築時にJVMがすべてのリターン・タイプそのタイプが本当により具体的であるかどうかを検証することができます。それでも、呼び出し元と呼び出し先の間で適切な契約を結ぶためには、戻り値の型をコード化する必要があります。
戻り値の型が変更されてもエラーは発生しませんか?ライブラリのメソッドの結果を割り当ててもライブラリが変更され、voidや互換性のないオブジェクトが返される場合はどうなりますか? –