記事を書こうと思った背景
Java Silverの学習中に題名の通りの疑問が浮かんだ
まずは問題
public class Main {
public static void main(String[] args) {
Object a = new Object();
Object b = null;
System.out.println(a.equals(b));
}
}
- true
- false
- コンパイルエラー
- 例外が発生
答えは2のfalse
解説によると、equalsメソッドでは引数にnullを渡された時はfalseを返すという条件があるから、とのこと。
そこで、いやいやnull同士の比較したらtrueになるんじゃね?
aもnullを参照していたらnull同士の比較になるのではないか、そしてnull同士なので、trueにならないかという疑問を抱いたわけです。
null同士の比較はあり得る?
結論としてはあり得ない。
nullを参照している変数からequalsメソッドを呼び出すとぬるぽ(NullPointerException)で強制終了してしまい、実行ができないから、という理由です。
例えば、下記のコードを実行するとぬるぽで落ちます。
public class Main {
public static void main(String[] args) {
Object a = null;
Object b = new Object();
System.out.println(a.equals(b));
}
}
(参考)ぬるぽとは
java.lang.NullPointerExceptionはJavaで最も一般的なランタイムエラーの一つで、オブジェクト参照がnullの状態でそのオブジェクトのメソッドを呼び出したり、フィールドにアクセスしようとしたときに発生します。
引用元:https://dtnavi.tcdigital.jp/cat_system/language_238/?utm_source=chatgpt.com
参照型の初期値はnullである、それならtrueになるのでは?
(別の角度からの視点ですが)同じ疑問を持った方がネット上で質問をしていました。
対象サイト:https://teratail.com/questions/27482
ここでは、質問者が「参照型の初期値はnullになる」ということを学び、じゃあオブジェクトをインスタンス化し、変数に値を入れなければnullが入っているから、null同士の比較もあり得るんじゃね?という疑問ですね。
つまり下記のコードでaにはnullが入っているのではないか、という解釈だと思われます。
public class Main {
public static void main(String[] args) {
Object a = new Object();
Object b = null;
System.out.println(a.equals(b));
}
}
結論としては、aにはnullを参照しておらず、実行結果はfalseとなります。
理由はすでに述べた通り、equalsメソッドでは引数にnullを渡された時はfalseを返すという条件があるかです。
では参照型の初期値がnullというのはどういうことか、オブジェクトのインスタンスがnullを参照しているのではなく、オブジェクトが持つ参照型の変数の初期値がnullということ。
例
// オブジェクトのインスタンスがnullを参照している例
Object obj2; // null
Object obj3 = null; // str1と同じnull
// オブジェクトが持つ参照型の変数の初期値がnull
public class User {
String name; // null
}
public class Main {
public static void main(String[] args) {
User u = new User();
if(u.name == null){
System.out.println("nameはnullです");
}
}
}
実行結果
nameはnullです
実行結果から分かる通り、Stringや他クラスのインスタンスなどの参照型の変数では初期値でnullが入っています。
ではaの場合はというと、試しに下記コードを実行してみると、ハッシュ値を出力されることがわかります。
public class Main {
public static void main(String[] args) {
Object a = new Object();
System.out.println(obj1);
}
}
実行結果
java.lang.Object@7ad041f3
ここからさらに深掘りしていくとキリがないので今回はここまでとします。
まとめ
少し話が逸れてしまいましたが、まとめます。
nullを参照しているオブジェクトからequalsメソッドを呼び出すと、ぬるぽで落ちる。
インスタンスがnullを参照していることと、オブジェクト型が持つ参照型の変数の初期値がnullを参照していることは意味が異なる。
Java初学者にはわかりずらいですがnullについて理解する一歩として、いいきっかけとなりました。