Javaのprivateフィールドのアクセス権について

More than 3 years have passed since last update.


疑問

equals()をオーバーライドした時に、

なぜ、引数のprivateフィールドを読めるのか?


Food.java

public class Food {

// ===privateなのに===
private final Double TAX = 1.08;
private String name;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Food)) return false;

Food food = (Food) o;

// ===引数oのprivateフィールドに直接アクセス出来るの??===
return name != null ? name.equals(food.name) : food.name == null;
}
}


この疑問を実験してみました!!!!


実験1:privateフィールドって本当にアクセスできないの?

他のクラスでアクセスしてみましたが、

こちらはコンパイルエラーなので、

しっかりアクセスできませんでした。


CompileError

public class OtherClass {

public static void main(String[] args) {
Food tomato = new Food("トマト", 7, 100);
tomato.printInfo();

tomato.name = "違う名前";
System.out.println(tomato.name); //コンパイルエラー
}
}



実験2:もしかしてequals()だけなのか?

同じクラスにmain()を作成し、実行してみた。

こちら実行できたので、

どうやらequals()だけではないようです。


Food.java

public class Food {

private String name;

public Food(String name) {
this.name = name;
}

public static void main(String[] args) {
Food tomato = new Food("トマト", 7, 100);

tomato.name = "違う名前";
System.out.println(tomato.name); //違う名前
}
}



実験3:main()も特殊なメソッドだろうが(# ゚Д゚)

普通のメソッドでも

同様にアクセスできました


Food.java

public class Food {

private String name;

public Food(String name) {
this.name = name;
}

public void changeName(Food otherFood, String name) {
otherFood.name = name;
}

public String getName() {
return name;
}
}



OtherClass.java

public class OtherClass {

public static void main(String[] args) {
Food food = new Food("tomato");
food.changeName(food, "違う名前");
System.out.println(food.getName()); // 違う名前
}
}


結論

他のインスタンスでも、同じクラス内ならprivate fieldでも読めるし、書き変えも可能みたいです。

これはそのクラスが持つmainでも普通のメソッドでも同じようです。

ただし、危険な臭いがするので、

equals()以外で他のインスタンスのprivateフィールドにアクセスするのは

やめた方が良さそうです。