よくあるJava面接問題(3):リロードとリライト(overriding)
4704 ワード
この文章で紹介する一般的な面接問題は、オーバーロード方法とオーバーライド方法についてです.
Q.次のコードクリップの出力結果は?
A.出力結果:
MethodOverrideVsOverload equals method reached
objects o3 and o4 are equal
この問題はどのような概念を考察したのだろうか. Java言語では、1つのクラスが1つのクラスからのみ継承され(すなわち、単一継承構造)、継承されたクラスが明示的に明記されていない場合、自動的にObjectオブジェクトから継承されます. ほとんどの非finalオブジェクトクラスメソッドは、布団クラス書き換え(overridden): public boolean equals(Object obj);//make note of this method
public int hashCode();
public String toString();リロード・メソッドは、コンパイル時に機能し(例えば、静的バインディング)、書き換えメソッドは、実行時に機能する(例えば、動的バインディング).静的バインディングは、JVMがコンパイル時に呼び出すクラスまたはメソッドを決定することを意味します.動的バインディングの場合、JVMは実行時に呼び出されるクラスまたはメソッドを決定します.ダイナミックバインド設計はマルチステートの基礎である.
サブクラスで親を書き換える対応方法は、 のルールに従う必要があります.
パラメータ
可変ではありません(パラメータタイプと個数を含む).
戻りタイプ
可変ではありません.コヒーレント戻りタイプまたはそのサブタイプ(covariant(subtype)returnsを除きます.
異常
子クラスでは、より少ない例外を放出できますが、親クラスで定義されていないチェック済み例外は絶対に放出できません.
アクセス権
親クラスよりも対応方法がゆったりしています.
よびだし
実行時(すなわちダイナミックバインド)は、オブジェクトタイプに応じて呼び出しの具体的なメソッドを決定します.
次に、上記のコードを振り返ると、MethodOverrideVsOverloadクラスの「equals(M ethodOverrideVsOverload other)」メソッドは、Objectクラスの「public boolean equals(Object obj)」メソッドを書き換えていません.これは、1つがMethodOverrideVsOverloadタイプであり、もう1つがObjectタイプであるパラメータ規則に違反しているためです.したがって、この2つの方法は、関係を書き換えるのではなく、関係を再ロードすることです(コンパイル時に発生します).
従って、o 1が呼び出される.equals(o 2)の場合,objectクラスにおけるpublic boolean equals(Object obj)メソッドが実際に呼び出される.これは、コンパイル時にo 1とo 2がともにObjectタイプであり、Objectクラスのequals(…)メソッドがメモリアドレスの比較(例えば、Object@235f56およびObject@653af32)のためfalseが返されます.
o 3を呼び出すと.equals(o 4)では、MethodOverrideVsoverloadクラスのequals(MethodOverrideVsoverload other)メソッドが実際に呼び出されます.これは,コンパイル時にo 3とo 4がともにMethodOverrideVsoverloadタイプであるため,上記の結果が得られる.
次はどう質問すればいいですか?
Q.では、上記の問題をどのように解決しますか.
A.Java 5では、コンパイル時の注釈(compile time annotations)@overrideを含め、親メソッドが正しく書き換えられていることを保証する注釈が追加されました.上のコードに注記が追加されている場合、JVMはコンパイルエラーを放出します.
そこで,解決策として,MethodOverrideVsoverloadクラスのboolean equals(MethodOverrideVsoverload other)メソッドに@override注記を追加する.これにより,コンパイル時にエラーが投げ出され,開発者にある方法が親メソッドを正しく書き換えていないことを示唆する.その後、メソッドのパラメータを変更し、MethodOverrideVsOverloadからObjectに変更する必要があります.具体的には、次のようにします.
出力:
MethodOverrideVsOverload equals method reached
objects o1 and o2 are equal
MethodOverrideVsOverload equals method reached
objects o3 and o4 are equal
上のコードでは,実行時equalsメソッドがObjectの対応するメソッドを正しく書き換えている.これは混同されやすい問題で、面接の際には関連概念を詳しく説明する必要があります.
Q.次のコードクリップの出力結果は?
public class MethodOverrideVsOverload {
public boolean equals( MethodOverrideVsOverload other ) {
System.out.println("MethodOverrideVsOverload equals method reached" );
return true;
}
public static void main(String[] args) {
Object o1 = new MethodOverrideVsOverload();
Object o2 = new MethodOverrideVsOverload();
MethodOverrideVsOverload o3 = new MethodOverrideVsOverload();
MethodOverrideVsOverload o4 = new MethodOverrideVsOverload();
if(o1.equals(o2)){
System.out.println("objects o1 and o2 are equal");
}
if(o3.equals(o4)){
System.out.println("objects o3 and o4 are equal");
}
}
}
A.出力結果:
MethodOverrideVsOverload equals method reached
objects o3 and o4 are equal
この問題はどのような概念を考察したのだろうか.
public int hashCode();
public String toString();
パラメータ
可変ではありません(パラメータタイプと個数を含む).
戻りタイプ
可変ではありません.コヒーレント戻りタイプまたはそのサブタイプ(covariant(subtype)returnsを除きます.
異常
子クラスでは、より少ない例外を放出できますが、親クラスで定義されていないチェック済み例外は絶対に放出できません.
アクセス権
親クラスよりも対応方法がゆったりしています.
よびだし
実行時(すなわちダイナミックバインド)は、オブジェクトタイプに応じて呼び出しの具体的なメソッドを決定します.
次に、上記のコードを振り返ると、MethodOverrideVsOverloadクラスの「equals(M ethodOverrideVsOverload other)」メソッドは、Objectクラスの「public boolean equals(Object obj)」メソッドを書き換えていません.これは、1つがMethodOverrideVsOverloadタイプであり、もう1つがObjectタイプであるパラメータ規則に違反しているためです.したがって、この2つの方法は、関係を書き換えるのではなく、関係を再ロードすることです(コンパイル時に発生します).
従って、o 1が呼び出される.equals(o 2)の場合,objectクラスにおけるpublic boolean equals(Object obj)メソッドが実際に呼び出される.これは、コンパイル時にo 1とo 2がともにObjectタイプであり、Objectクラスのequals(…)メソッドがメモリアドレスの比較(例えば、Object@235f56およびObject@653af32)のためfalseが返されます.
o 3を呼び出すと.equals(o 4)では、MethodOverrideVsoverloadクラスのequals(MethodOverrideVsoverload other)メソッドが実際に呼び出されます.これは,コンパイル時にo 3とo 4がともにMethodOverrideVsoverloadタイプであるため,上記の結果が得られる.
次はどう質問すればいいですか?
Q.では、上記の問題をどのように解決しますか.
A.Java 5では、コンパイル時の注釈(compile time annotations)@overrideを含め、親メソッドが正しく書き換えられていることを保証する注釈が追加されました.上のコードに注記が追加されている場合、JVMはコンパイルエラーを放出します.
そこで,解決策として,MethodOverrideVsoverloadクラスのboolean equals(MethodOverrideVsoverload other)メソッドに@override注記を追加する.これにより,コンパイル時にエラーが投げ出され,開発者にある方法が親メソッドを正しく書き換えていないことを示唆する.その後、メソッドのパラメータを変更し、MethodOverrideVsOverloadからObjectに変更する必要があります.具体的には、次のようにします.
public class MethodOverrideVsOverload {
@Override
public boolean equals( Object other ) {
System.out.println("MethodOverrideVsOverload equals method reached" );
return true;
}
public static void main(String[] args) {
Object o1 = new MethodOverrideVsOverload(); //during compile time o1 is of type Object
//during runtime o1 is of type MethodOverrideVsOverload
Object o2 = new MethodOverrideVsOverload(); //during compile time o2 is of type Object
//during runtime o2 is of type MethodOverrideVsOverload
MethodOverrideVsOverload o3 = new MethodOverrideVsOverload(); //o3 is of type MethodOverrideVsOverload
// during both compile time and runtime
MethodOverrideVsOverload o4 = new MethodOverrideVsOverload(); //o4 is of type MethodOverrideVsOverload
// during both compile time and runtime
if(o1.equals(o2)){
System.out.println("objects o1 and o2 are equal");
}
if(o3.equals(o4)){
System.out.println("objects o3 and o4 are equal");
}
}
}
出力:
MethodOverrideVsOverload equals method reached
objects o1 and o2 are equal
MethodOverrideVsOverload equals method reached
objects o3 and o4 are equal
上のコードでは,実行時equalsメソッドがObjectの対応するメソッドを正しく書き換えている.これは混同されやすい問題で、面接の際には関連概念を詳しく説明する必要があります.