Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Java: Czego mi brak: Operator warunkowy

29 views
Skip to first unread message

Lasu

unread,
Dec 8, 2008, 10:08:32 AM12/8/08
to
Witam!

A więc brakuje mi operatora który by działał jak '.' z małym wyjątkiem
jeśli nadrzędny obiekt byłby null-em, wówczas null byłby zawsze
zwracany. Było by to pozytywne gdy komuś nie chce się deklarować tony
niepotrzebnych zmiennych tylko po to, żeby zajrzeć co jest w środku.
W bardziej skomplikowanych przypadkach niż ten niżej często aby
uniknąć zagrożenia wynikającego z możliwości użycia nieodpowiedniego
pola jest konieczność wydzielania sztucznych bloków tylko po to alby
zmienne się nie walały po metodzie.


Przykład użycia:

public class Test {

public static class SomeHouse {
public MainEntry mainEntry;
}

public static class MainEntry {
public RealyRealyGoodLock realyRealyGoodLock;
}

public static class RealyRealyGoodLock {
public LockMode lockMode;
}

public static class LockMode {

}

/**
* Good and hard
*/
public static LockMode getLockModeStandard(SomeHouse someHouse) {
if (someHouse == null) { return null; }
MainEntry mainEntry = someHouse.mainEntry;
if (mainEntry == null) { return null; }
RealyRealyGoodLock rGoodLock = mainEntry.realyRealyGoodLock;
if (rGoodLock == null) { return null; }
return rGoodLock.lockMode;
}

/**
* Can case some efficiency problems if <code>null</code> occurs
really often.
*/
public static LockMode getLockModeBad(SomeHouse someHouse) {
try {
return someHouse.mainEntry.realyRealyGoodLock.lockMode;
} catch (NullPointerException e) {
return null;
}
}

/**
* This will do not work properly while changing from other thread
*/
public static LockMode getLockModeWorst(SomeHouse someHouse) {
if (someHouse == null) return null;
if (someHouse.mainEntry == null) return null;
if (someHouse.mainEntry.realyRealyGoodLock == null) return null;
return someHouse.mainEntry.realyRealyGoodLock.lockMode;
}

/**
* Would be better
*/
public static LockMode getLockModeSuggested(SomeHouse someHouse) {
return someHouse.?.mainEntry.?.realyRealyGoodLock.?.lockMode;
}

/**
* Would be better
*/
public static LockMode getLockModeSuggestedOther(SomeHouse
someHouse) {
LockMode lockMode
=someHouse.?.mainEntry.?.realyRealyGoodLock.?.lockMode;
if (lockMode==null){
// Do what u want
}
return lockMode;
}

/**
* Mixed case where we know that {@link
MainEntry#realyRealyGoodLock}
* is mandatory and should never happen for this field to be null.
*/
public static LockMode getLockModeMixed(SomeHouse someHouse) {
return someHouse.?.mainEntry.realyRealyGoodLock.?.lockMode;
}
}


to samo na PJug:
http://groups.google.com/group/polish-java-user-group/browse_thread/thread/29afc1d5e227a27c?hl=pl
to samo na LJUG:
http://groups.google.com/group/lublin-jug/browse_thread/thread/ea6b11dbc0b297d1?hl=pl

Jaka jest wasza opinia ?


Tu natomiast jest bug na Eclipse odnośnie pomocy przy nawiasach
zamykających bloki:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=256933
--
Pozdrowionka
Lasu <Marek Kozieł>

Witold Szczerba

unread,
Dec 8, 2008, 10:24:52 AM12/8/08
to
On Dec 8, 4:08 pm, Lasu <develop4l...@gmail.com> wrote:
>   /**
>    * Good and hard
>    */
>   public static LockMode getLockModeStandard(SomeHouse someHouse) {
>     if (someHouse == null) { return null; }
>     MainEntry mainEntry = someHouse.mainEntry;
>     if (mainEntry == null) { return null; }
>     RealyRealyGoodLock rGoodLock = mainEntry.realyRealyGoodLock;
>     if (rGoodLock == null) { return null; }
>     return rGoodLock.lockMode;
>   }
>

Można zapisać też tak:

return someHouse != null
&& someHouse.mainEntrty != null
&& someHouse.mainEntrty.reallyGoodLock != null
? someHouse.mainEntrty.reallyGoodLock.lockMode
: null;

Kolejne linijki zaczynające się od && to kopia też wyżej + nowe pole.
Ale fakt, że dobrze by było mieć coś w stylu:

return someHouse?.mainEntrty?.reallyGoodLock?.lockMode;

Pozdrawiam,
Witold Szczerba

Lasu

unread,
Dec 8, 2008, 10:27:32 AM12/8/08
to
On 8 Gru, 16:24, Witold Szczerba <pljosh.m...@gmail.com> wrote:

> Można zapisać też tak:
>
> return someHouse != null
>   && someHouse.mainEntrty != null
>   && someHouse.mainEntrty.reallyGoodLock != null
>   ? someHouse.mainEntrty.reallyGoodLock.lockMode
>   : null;

> Pozdrawiam,
> Witold Szczerba

To niestety nie zawsze będzie działać na wielo-wątkowych aplikacjach.

Daniel Janus

unread,
Dec 8, 2008, 11:00:45 AM12/8/08
to
Dnia 08.12.2008 Lasu <develo...@gmail.com> napisał/a:
> Witam!
>
> A więc brakuje mi operatora który by działał jak '.' z małym wyjątkiem
> jeśli nadrzędny obiekt byłby null-em, wówczas null byłby zawsze
> zwracany. Było by to pozytywne gdy komuś nie chce się deklarować tony
> niepotrzebnych zmiennych tylko po to, żeby zajrzeć co jest w środku.
> W bardziej skomplikowanych przypadkach niż ten niżej często aby
> uniknąć zagrożenia wynikającego z możliwości użycia nieodpowiedniego
> pola jest konieczność wydzielania sztucznych bloków tylko po to alby
> zmienne się nie walały po metodzie.

O, dzięki. Pomysł przyda się jako materiał demonstracyjny do języków,
w których można sobie dodać wygodną konstrukcję składniową w pięć minut,
zamiast czekać parę lat na przeforsowanie nowego JSR :-)

pozdrawiam,
--
Daniel 'Nathell' Janus, mov...@nathell.korpus.pl, http://korpus.pl/~nathell
"Don't treat fictional people as if they were human beings.
It only encourages them."
-- Aris Katsaris, rec.arts.int-fiction

Witold Szczerba

unread,
Dec 8, 2008, 1:23:55 PM12/8/08
to

Dlaczego nie zawsze będzie działać? Mówimy o sytuacji hipotetycznej,
zakładając że program jest źle napisany, czy sytuację całkowicie
realną w poprawnej aplikacji?

Lasu

unread,
Dec 8, 2008, 2:07:07 PM12/8/08
to
> Dlaczego nie zawsze będzie działać? Mówimy o sytuacji hipotetycznej,
> zakładając że program jest źle napisany, czy sytuację całkowicie
> realną w poprawnej aplikacji?

Tą realną.
Musimy sobie uświadomić, że kod wykonuje się w etapach.

1. someHouse != null
2. someHouse.mainEntrty != null
3> modlimy się aby nikt nie ustawił someHouse.mainEntrty na null z
innego wątku
4. someHouse.mainEntrty.reallyGoodLock != null
5> modlimy się aby nikt nie ustawił someHouse.mainEntrty bądz
someHouse.mainEntrty.reallyGoodLock na null z innego wątku
6.someHouse.mainEntrty.reallyGoodLock.lockMode
7> modlimy się aby nikt nie ustawił someHouse.mainEntrty bądz
someHouse.mainEntrty.reallyGoodLock na null z innego wątku

I tu coś robimy. (możemy przestać się modlić)

Jak widać jeśli mamy aplikację typu server to wyjątek prędzej czy
puźniej się trafi (jesli zmienne podlegają modyfikacji), choć
teoretycznie się przed tym zabezpieczyliśmy.


Witold Szczerba

unread,
Dec 8, 2008, 2:42:07 PM12/8/08
to
On Dec 8, 8:07 pm, Lasu <develop4l...@gmail.com> wrote:
> > Dlaczego nie zawsze będzie działać? Mówimy o sytuacji hipotetycznej,
> > zakładając że program jest źle napisany, czy sytuację całkowicie
> > realną w poprawnej aplikacji?
>
> Tą realną.
> Musimy sobie uświadomić, że kod wykonuje się w etapach.
>
> 1. someHouse != null
> 2. someHouse.mainEntrty != null
> 3> modlimy się aby nikt nie ustawił someHouse.mainEntrty na null z
> innego wątku
> 4. someHouse.mainEntrty.reallyGoodLock != null
> 5> modlimy się aby nikt nie ustawił someHouse.mainEntrty bądz

...ciach - starczy tego modlenia...
Piszę aplikację klient-serwer już trochę czasu, ale nie zdarzyło mi
się jeszcze doprowadzić to tego, żeby wątki w tym samym czasie
wydzierały sobie współdzielone obiekty (jednoczesne odczyty + zapis)
beż żadnej synchronizacji/blokad (lub po prostu operowania na
kopiach). Tak czy inaczej po co nam zdobycz w postaci jakiegoś wyniku,
skoro jest już nieaktualny? (przytoczona wersja z zapisywaniem
pośrednich odwołań do zmiennych). Być może specyfika mojej aplikacji
jest inna i dlatego się z czymś takim nie spotkałem (chociaż na samą
myśl o takich operacjach nie mogę się oprzeć wrażeniu, że to nie
najlepszy pomysł).

Lasu

unread,
Dec 8, 2008, 3:01:23 PM12/8/08
to
I tak i nie.
^__^
Zależy to od stylu.
Ja poprostu lubię pisać aplikację wielowątkowe bez słowa
'synchronized' o ile to nie jest konieczne.
Poza tym nie zawsze ma znaczenie czy obiekt był aktualny.
A jeśli ma to trzeba synchronizować całe bloki.

Bo zauważ, że zanim wyświetlisz/prześlesz informacje może być ona nie
aktualna, a chodzi o to aby nie wystąpił NullPointerException, który
już widziałem na aplikacjach webowych.

To że nam się coś nie zdarzyło wcale nie znaczy, że nie mamy gdzieś
luki, która wyjdzie za 1 rok wieszając nam aplikacje co 5 dni. Albo
wyrzucając wyjątek powodujący nie zamknięcie połączenia do bazy
danych. Wydawało by się, że to mało prawdopodobne, i tak jest, ale się
zdarza choć moim zdaniem nie potrzebnie.

Pozdrawiam!

Tomasz Przybyła

unread,
Dec 8, 2008, 6:03:45 PM12/8/08
to
Czołem,

Zazwyczaj powstrzymuje sie od pisania komentarzy, gdyz w stosunku do
wiekszosci wypowiadajacych sie tu osob moja wiedza jest nikla. Jednak
tym razem nie moge ze spokojnym sumieniem czytac tego co kolega Lasu
pisze.

Z calym szacunkiem, ale w ktorym miejscu Twoj kod jest odporny na
wspolbiezne dzialanie kilku watkow? Co z tego ze robiesz wszystkie
sprawdzenia oddzielnie, jak miedzy sprawdzeniem, a wywolaniem metody
inny watek moze ustawic obiekt na ktorym owa metode wywolujesz na
nulla? Z teoretycznego punku widzenia nie ma zadnej roznicy czy
uzyjesz ifow, czy tez operatorow ?:. Z praktycznego zreszta pewnie tez
nie... Jak chcesz pisac aplikacje wielowatkowe to w takiej sytuacji
bez synchronizacji sie nie obejdzie.

A co do samego operatora to imho srednio potrzebny. Jakby wywolywana
metodka byla typu void to tez mialby zwracac nulla? Jakos tak
dziwnie.. No ale pewnie jakby byl to od czasu do czasu sam bym do
uzywal ;)

Pozdro, Tomek

Witold Szczerba

unread,
Dec 8, 2008, 6:21:42 PM12/8/08
to
On Dec 9, 12:03 am, Tomasz Przybyła <tomasz.przyb...@gmail.com> wrote:
> Z calym szacunkiem, ale w ktorym miejscu Twoj kod jest odporny na
> wspolbiezne dzialanie kilku watkow? Co z tego ze robiesz wszystkie
> sprawdzenia oddzielnie, jak miedzy sprawdzeniem, a wywolaniem metody
> inny watek moze ustawic obiekt na ktorym owa metode wywolujesz na
> nulla? Z teoretycznego punku widzenia nie ma zadnej roznicy czy
> uzyjesz ifow, czy tez operatorow ?:. Z praktycznego zreszta pewnie tez
> nie... Jak chcesz pisac aplikacje wielowatkowe to w takiej sytuacji
> bez synchronizacji sie nie obejdzie.


Przyjrzyj się konstrukcji jeszcze raz:
a = x.getA();
if (a == null) return null;
b = a.getB();
if (b == null) return null;
c = b.getC();
// i tak dalej

Najpierw jest przypisanie do zmiennej, potem sprawdzenie. Taki kod nie
rzuci NullPointerException gdy np. a.getB() zmieni się na null, bo w
zmiennej "b" pozostanie stara wartość (referencja do starego obiektu).
Tzn, że w "b" masz to, co było jak się wykonało a.getB() mimo tego,
że już po chwili a.getB() mogłoby zwrócić null... tylko, że nikt po
raz drugi a.getB() nie wywołuje.

Inna sprawa, że ja bym starał się czegoś takiego uniknąć, żeby jeden
wątek mógł w tym samym czasie zapisywać, w którym inny odczytuje, ale
to zupełnie inny temat. Co do synchronizacji - to nie jest jedyny
sposób na radzenie sobie w wielowątkowych aplikacjach, ale to też nie
na temat :)

Pozdrawiam,
Witold Szczerba

Waldek Kot

unread,
Dec 8, 2008, 6:49:50 PM12/8/08
to
On 8 Gru, 16:08, Lasu <develop4l...@gmail.com> wrote:
> Jaka jest wasza opinia ?
Przydałby się taki operator...

Na razie, to może takie coś pomoże - nie operator, ale powinno dać
podobny efekt (nawet chyba trochę "ładniej", bo bez potrzeby
modyfikacji już istniejącego kodu) - trochę na szybko pisane, więc do
głębszego potestowania:

package pl.waldekkot;

public aspect SafeNavigationAspect {
pointcut myPointcut() : (get(* *.*) || call(* *.*(..))) &&
!within(SafeNavigationAspect);

Object around(Object o) : myPointcut() && target(o) {
if(o == null)
return null;
return proceed(o);
}
}

Oczywiście trzeba to skompilować ajc z AspectJ (a używając Eclipse z
AJDK, to właściwie dewelopuje się jak z normalną aplikację Java...).
Druga uwaga, to, że ten aspekt w tej chwili jest globalny (dotyczy
wszystkich klas). Na potrzeby testowania ujdzie, ale znacznie lepsze
będzie jego selektywne aplikowanie do wybranych metod/klas/pakietów
(czyli w tym aspekcie, tam, gdzie definiuje się point cut, trzeba
dodać stosowną klauzulę ograniczającą). Zastosowanie adnotacji do
wybrania miejsc, w których ten aspekt ma zadziałać też wydaje się mieć
sens...

Pozdrawiam,
Waldek Kot

Tomasz Przybyła

unread,
Dec 9, 2008, 4:10:41 AM12/9/08
to
Ups.. ;)

Troche sie pospieszylem. Faktycznie wszystko jest ok, zwracam honor i
sorry za niepotrzebny zamęt ;)

Pozdro, Tomek

Lasu

unread,
Dec 9, 2008, 2:06:04 PM12/9/08
to
Poszło na:
http://blogs.sun.com/darcy/entry/small_language_changes_jdk_7
Zobaczymy czy coś z tego wyjdzie.

Przemysław Kowalczyk

unread,
Dec 9, 2008, 4:19:01 PM12/9/08
to
On Mon, 08 Dec 2008 16:08:32 +0100, Lasu <develo...@gmail.com> wrote:
>
> A więc brakuje mi operatora który by działał jak '.' z małym wyjątkiem
> jeśli nadrzędny obiekt byłby null-em, wówczas null byłby zawsze
> zwracany. Było by to pozytywne gdy komuś nie chce się deklarować tony
> niepotrzebnych zmiennych tylko po to, żeby zajrzeć co jest w środku.
> W bardziej skomplikowanych przypadkach niż ten niżej często aby
> uniknąć zagrożenia wynikającego z możliwości użycia nieodpowiedniego
> pola jest konieczność wydzielania sztucznych bloków tylko po to alby
> zmienne się nie walały po metodzie.

Troche z innej beczki: mam wrazenie, ze Twoj problem wynika z lamania
Prawa Demeter - http://en.wikipedia.org/wiki/Law_of_Demeter

Ponizszy kod (ktory wycialem z Twojego przykladu) dobrze to ilustruje:

> return someHouse.mainEntry.realyRealyGoodLock.lockMode;

Posiadacz referencji someHouse nie powinien znac tych wszystkich
szczegolow implementacyjnych potrzebnych do pobrania lockMode (zakladajac,
ze uzasadnione jest pobranie lockMode). I nawet zmiana odwolan do pol na
odwolania do getterow niewiele tu zmienia -- to sa wciaz szczegoly
implementacyjne, ktore powoduja, ze posiadacz someHouse jest uzalezniony
od tego, ze someHouse ma mainEntry, ktore ma realyRealyGoodLock, ktore ma
lockMode. Powodzenia przy refactoringu zycze :)

Jezeli posiadacz someHouse rzeczywiscie potrzebuje dobrac sie do lockMode,
someHouse powinno miec odpowiednia metode getLockMode(), ktora opakuje te
cala zabawe.

pzdr
szeryf

--
Przemysław ,,Szeryf'' Kowalczyk :: http://szeryf.wordpress.com/

Lasu

unread,
Dec 10, 2008, 2:46:55 AM12/10/08
to
Zgadzam się z tobą.
Jednak pic polega na tym, że nie zawsze programowanie może być w 100%
ładne i piękne.
Samo przetwarzanie XML w postaci obiektów to pokazuje.
0 new messages