Solo i miei 2 centesimi sulla questione del perché la semantica della visibilità privata in Java è a livello di classe piuttosto che a livello di oggetto.
Direi che la comodità sembra essere la chiave qui. Infatti, una visibilità privata a livello di oggetto avrebbe costretto ad esporre metodi ad altre classi (es. Nello stesso pacchetto) nello scenario illustrato dall'OP.
In verità non sono riuscito né a inventare né a trovare un esempio che dimostri che la visibilità a livello di classe-privato (come quella offerta da Java) crea problemi se paragonata alla visibilità a livello di oggetto-privato.
Detto questo, i linguaggi di programmazione con un sistema più dettagliato di politiche di visibilità possono offrire sia la visibilità degli oggetti a livello di oggetto che di classe.
Ad esempio Eiffel , offre l'esportazione selettiva: puoi esportare qualsiasi privilegio di classe in qualsiasi classe di tua scelta, da {NONE} (oggetto privato) a {ANY} (l'equivalente di pubblico, e anche l'impostazione predefinita), a {PERSON} (class-private, vedi l'esempio dell'OP), a gruppi specifici di classi {PERSON, BANK}.
È anche interessante notare che in Eiffel non è necessario rendere privato un attributo e scrivere un getter per impedire ad altre classi di assegnargli. Gli attributi pubblici in Eiffel sono accessibili per impostazione predefinita in modalità di sola lettura, quindi non è necessario un getter solo per restituire il loro valore.
Ovviamente hai ancora bisogno di un setter per impostare un attributo, ma puoi nasconderlo definendolo come "assegnatore" per quell'attributo. Ciò consente, se lo si desidera, di utilizzare l'operatore di assegnazione più conveniente invece dell'invocazione del setter.