Różnica jest taka, że pola prywatne każda klasa ma swoje i widzi tylko swoje. ;) To, że nazwy się pokrywają, to przypadek. Kompilator nie protestuje, bo przecież "to prywatne jest". Każdy może sobie prywatnie robić co chce. W hierarchii ABCD będziesz więc miał cztery zupełnie niezależne pola. Przypadkiem o nazwie tej samej.
Pola protected albo public nie mają kolizji nazw, bo nie masz prawa w dziedziczeniu nadpisać deklaracji takiego pola - kompilator nie pozwala na kolizje.
Rzuć okiem na przykład poniżej, klasy A B C D. Każda ma pole prywatne. Każda ma metodę print (publiczną), która wypisuje SWOJE pole, oraz wywołuje super.print. Na ekranie latają 4 różne wartości. Na modyfikacje pól mogę sobie w przykładzie pozwolić, bo trzymam referencje do Field. Gdybym miał tylko nazwę "id", jako String, to nie wiedziałbym na rzecz której klasy zawołać getField("id").
package net.ranides.annotate;
import java.lang.reflect.Field;
public class ReflectDemo {
public static void main(String[] args) throws Exception {
D object = new D();
Class Dcc = object.getClass();
Class Ccc = Dcc.getSuperclass();
Class Bcc = Ccc.getSuperclass();
Class Acc = Bcc.getSuperclass();
Field Did = Dcc.getDeclaredField("id");
Field Cid = Ccc.getDeclaredField("id");
Field Bid = Bcc.getDeclaredField("id");
Field Aid = Acc.getDeclaredField("id");
Aid.setAccessible(true);
Bid.setAccessible(true);
Cid.setAccessible(true);
Did.setAccessible(true);
object.print();
System.out.println();
Aid.setInt(object, 66677);
Bid.setInt(object, 66678);
object.print();
System.out.println();
Cid.setInt(object, 66679);
Did.setInt(object, 66680);
object.print();
System.out.println();
}
}
class A {
private int id = 11;
public void print() {
System.out.println("a.id = " + id);
}
}
class B extends A {
private int id = 22;
@Override
public void print() {
System.out.println("b.id = " + id);
super.print();
}
}
class C extends B {
private int id = 33;
@Override
public void print() {
System.out.println("c.id = " + id);
super.print();
}
}
class D extends C {
private int id = 44;
@Override
public void print() {
System.out.println("d.id = " + id);
super.print();
}
}