Jak v Javě ukazatele nejsou, ale vlastně tak trochu jsou, je podle mě ve
výsledku ještě komplikovanější, než kdyby opravdu byly :-)

Může se Vás zeptat na bug, který zmiňujete (
http://findbugs.sourceforge.net/bugDescriptions.html#EI_EXPOSE_REP)?  Jak
přesně se proti tomu bránit?

Tento prográmek by mi asi Findbugs označil právě chybou EI_EXPOSE_REP,
protože mi opravdu umoňuje vynulovat datum narození zaměstnance i když jsem
si ho označil jako private a nezveřejňuji setter.

import java.util.Date;

public class ZmenaBezSetteru {
    public static void main(String[] args) {
        Zamestnanec zam = new Zamestnanec(new
Date(System.currentTimeMillis()));
        System.out.println("Osoba2.getNarozeni() = " + zam.getNarozeni());

        zam.getNarozeni().setTime(0L);
        System.out.println("Osoba2.getNarozeni() = " + zam.getNarozeni());
    }
}

class Zamestnanec {
    private Date narozeni;

    Zamestnanec(Date narozeni) {
        this.narozeni = narozeni;
    }

    public Date getNarozeni() {
        /*Zamestnanec kopieZamestnance = new Zamestnanec(narozeni);
        return kopieZamestnance.getNarozeni();*/

        return narozeni;
    }
}

Ovšem do jaké podoby přepsat Zamestnanec.getNarozeni(), aby teda nevracela
referenci na privátní objekt Date, ale kopii. Tedy odolné proti
zam.getNarozeni().setTime(0L);, aby i po tomto příkazu zůstalo datum
narození v nezměné?

První co mě napadá je přepsat getNarozeni() na toto:

    public Date getNarozeni() {
        Zamestnanec kopieZamestnance = new Zamestnanec(narozeni);
        return kopieZamestnance.getNarozeni();
    }

Ovšem s tím nepochodím a skončím s ošklivou chybou:

Exception in thread "main" java.lang.StackOverflowError
    at Zamestnanec.<init>(ZmenaBezSetteru.java:16)
    at Zamestnanec.getNarozeni(ZmenaBezSetteru.java:21)
    (a tento řádek vypsán ještě asi 30x :-))

Proč skončí tato varianta s vytvořením nového objektu na sebe sama s chybou
StackOverflowError? Když zkusím druhé co mě napadá na toto:

    public Date getNarozeni() {
        return (Date) narozeni.clone();
    }

Pak již hlavní program vypíše 2x po sobě stejné datum.

--
Libor

2011/4/4 Ondřej Fafejta <[email protected]>

> 2011/4/4 Robert Novotny <[email protected]>:
> > Este by som to vylepsil, aby bolo vidiet efekt:
> >
> > I. Primitivy hodnotou:
> >
> > public static void zlyPokusOZmenuParametra(int i) {
> >    ++i;
> > }
> >
> > int i = 1;
> > zlyPokusOZmenuParametra(i);
> > System.out.println("i == " + i);  // 1
> >
> > II. Objekty referenciou
> >
> > public static void zmenDate(Date d) {
> >    d.setTime(0L);
> > }
> >
> > Date date = new Date();
> > System.out.println("date == " + date);    // v case mojeho spusteni
> > ... date == Mon Apr 04 14:15:27 CEST 2011
> > zmenDate(date);
> > System.out.println("date == " + date);    // date == Thu Jan 01
> > 01:00:00 CET 1970
>
>
> jj. tento příklad je výstižnější  ... (návratový typ je zbytečně matoucí
> ;-))
>
> Jinak ještě doplním, že findbugs hlásí chybu, když např. entita má
> getter pro parametr, u kterého můžeme přepsat hodnotu bez toho abychom
> volali setter...
>
> http://findbugs.sourceforge.net/bugDescriptions.html#EI_EXPOSE_REP
>
> např. (píšu z hlavy - určitě někde budu mít překlep ;))
>
> public class NejakaEntita implements Serializable {
>    private Date createdAt;
>
>   public Date getCreatedAt() {
>       return createdAt;
>   }
> }
>
> Fafi
>

Odpovedet emailem