Pokazywanie postów oznaczonych etykietą java7. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą java7. Pokaż wszystkie posty

17 sierpnia 2012

O tym jak DelayQueue realizuje kontrakt Iterable oraz BlockingQueue

0 komentarzy
W poprzednim wpisie Króciutko o j.u.concurrent.DelayQueue zaprezentowałem dosyć uproszczony przykład zastosowania java.util.concurrent.DelayQueue, w którym kolejka ukrywała elementy nieaktywne, co w tym konkretnym przypadku oznaczało wszystkie elementy. DelayQueue jest najzwyczajniej w świecie kolejką, która posiada dodatkową cechę, która pozwala na "widoczność" elementów, których czas "zamrożenia" minął. Stąd też, nieblokująca metoda poll() zwracała specjalną wartość - null - oznaczającą niemożność wykonania, tj. natychmiastowego zwrócenia elementu z kolejki.

Klasa j.u.c.DelayQueue posiada następujące cechy:
  • jest kolejką
  • jest nieograniczona (metoda remainingCapacity() zawsze zwraca Integer.MAX_VALUE)
  • jest blokująca (niektóre operacje manipulujące elementami kolejki, np. wspomniane poll() czy take())
  • operuje wyłącznie elementami typu j.u.concurrent.Delayed.
Zagłębiłem się w javadoc tej klasy i znalazłem inne ciekawostki, które przykuły moją uwagę. Oto przykład z nimi, a Twoim zadaniem jest odpowiedź na pytania w komentarzach. Miłej lektury!
package pl.japila.java7;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class DelayQueueMain {

    static class Conference implements Delayed {

        long delay;

        public Conference(long delay) {
            this.delay = delay;
        }

        @Override
        public int compareTo(Delayed o) {
            Conference c = (Conference) o;
            return this.getDelay() < c.getDelay() ? -1 : this.getDelay() == c.getDelay() ? 0 : 1;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return getDelay();
        }

        public long getDelay() {
            return delay;
        }

        @Override
        public String toString() {
            return String.format("Conference starts in %s days", getDelay());
        }

    }

    public static void main(String[] args) {
        DelayQueue<Conference> conferences = new DelayQueue<Conference>();
        conferences.add(new Conference(5));
        conferences.add(new Conference(10));
        conferences.add(new Conference(15));

        System.out.println("Head (delay expired furthest in the past) element: " + conferences.poll());

        // Q1: Jakie elementy zostaną wypisane na ekran?
        for (Conference conf : conferences) {
            System.out.println(conf);
        }

        // Q2: Jaki efekt po wykonaniu poniższej linii?
        System.out.println(conferences.element());

        // Q3: Co się stanie tutaj?
        conferences.add(null);
    }

}

15 sierpnia 2012

Króciutko o j.u.concurrent.DelayQueue

2 komentarzy
Kolejny raz potwierdza się zasada, że kto czyta, nie błądzi. W przypadku pakietu java.util.concurrent możnaby powiedzieć, że jest to najbardziej nieprzestrzegana zasada, której hołduję od jakiegoś czasu i zamiast przysiąść nad dokumentacją javadoc, pozwalam sobie na poznawanie jej wyłącznie przy okazji i to w tak niewielkich dawkach, że byłoby grzechem nazwać je wykraczającymi przyzwoite minimum.

Image
Na szczęście przyszło mi recenzować nadchodzącą książkę o java.util.concurrent - Java 7 Concurrency Cookbook z wydawnictwa Packt, więc chciał, czy nie chciał, jestem zaangażowany i poznaję.

Mojemu Maksymowi stuknęło 10 miesięcy! Postępy jakie robi we własnym rozwoju często są niezwykle zaskakujące i chciałbym móc to samo powiedzieć o swoim w kontekście j.u.concurrent. Przez ostatni miesiąc nauczył się sprawnie raczkować, siadać, wstawać, a nawet zaczyna chodzić asekurowany, czy to meblami czy przez inną osobę. Zaczyna mówić i od kilku dni daje się słyszeć blablabla, mama, czy inne dźwięki, których opisanie uważam za niemożliwe. Rozumie frazy: biedronka, nie, wypluj smoka, gdzie...?, lampa, daj, chodź, piciu piciu, am, otwórz buźkę i jeszcze kilka innych. Zaczęliśmy go przyzwyczajać do mycia zębów, bo przy 4 zębach i kolejnych 4 wychodzących, nie daje nam innego wyboru. Jada chętnie, dużo pije i ogólnie cacy. Oby tak dalej! A mówią, że nic nie trwa wiecznie :(

Gdyby przełożyć jego rozwój na mój w kontekście j.u.concurrent, to ja dopiero zacząłem raczkować. Pora to zmienić, bo za moment, to nie ja jego, ale on mnie będzie wychowywał. A jak Wam idzie poznawanie nowego API? Korzystacie z niego regularnie czy tylko z doskoku i to w ramach własnych, prywatnych projektów?

Na zakończenie krótki przykład z klasą, o istnieniu której dowiedziałem się właśnie z książki. Oto, proszę Państwa, wchodzi java.util.concurrent.DelayQueue. Trzeba było widzieć moją minę, kiedy przeczytałem o tej klasie, a nigdy wcześniej nawet słowa o niej nie czytałem. Niedobrze z moją znajomością Javki.

Pytanie kontrolne: Co będzie wypisane na ekran po uruchomieniu poniższej klaski?

package pl.japila.java7;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class DelayQueueMain {

    static class Conference implements Delayed {

        long delay;

        public Conference(long delay) {
            this.delay = delay;
        }

        @Override
        public int compareTo(Delayed o) {
            Conference c = (Conference) o;
            return this.getDelay() < c.getDelay() ? -1 : this.getDelay() == c.getDelay() ? 0 : 1;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return delay;
        }

        public long getDelay() {
            return delay;
        }

    }

    public static void main(String[] args) {
        DelayQueue<Conference> conferences = new DelayQueue<Conference>();
        conferences.add(new Conference(5));
        conferences.add(new Conference(10));
        conferences.add(new Conference(15));

        System.out.println("Head (delay expired furthest in the past) element: " + conferences.poll());
    }

}

25 lipca 2012

Kilka ciekawostek z Java Concurrency API w Java 7 od Packt

0 komentarzy
Image
Trudno mi było uwierzyć, że dałem się namówić na kolejną recenzję książki z wydawnictwa Packt. Nie jestem ich fanem, a ich książki są zwykle zbyt lekkie merytorycznie, aby kilka ciekawostek, których doszukanie się i tak zajmuje sporo czasu, było w stanie zrekompensować mój ból.

Tym razem jestem mile zaskoczony zawartością planowanej książki o współbieżności w Java 7 - Java 7 Concurrency Cookbook. Wydaje się być odpowiednio dopasowana merytorycznie do moich potrzeb, a że o współbieżności mowa (z którą mam niezwykle rzadko okazję się spotykać), tym lepiej dla niej (i mnie)!

Jako recenzent techniczny odpowiadam za jej właściwą zawartość merytoryczną i jakkolwiek pierwszy rozdział mógłbym z uciechą wrzucić do kosza, to kolejne zdają się bronić bez większego problemu.

Mam za sobą przeczytane 3 rozdziały (z ośmiu) i zaczynam z niecierpliwością oczekiwać lektury kolejnych. Właśnie w rozdziale 3 pojawiły się java.util.concurrent.CyclicBarrier oraz mój ulubieniec z Java 7 - j.u.c.Phaser.

Sposób przekazywania wiedzy przez autora nie nastraja do zagłębniania się w treść, a raczej służy jako zajawka do dalszego studiowania na własną rękę. Najbardziej "rozbraja" mnie prezentacja kodu źródłowego, który poszatkowany jest na kilkanaście punktów, które okraszone są skromnym opisem, często wręcz trywialnym nawet dla laika. Zatem, czytasz co będzie, demonstracja tego, co miało być i kolejny punkt. Dodając do tego, opisywanie konstrukcji "Stwórz klasę, która implementuje Runnable" i pojawia się kawałek początku klasy z "implements Runnable" i ręce opadają. Trzeba przywyknąć.

Z ciekawostek, które musiałem sprawdzić na własną rękę, zanim wprowadziłem zmiany w obecnej wersji, to klasa j.u.c.TimeUnit (którą swego czasu przedstawił mi Tomek Nurkiewicz), multi-catch oraz kombinacja TimeUnit z Phaser, a także j.u.Collections.nCopies.

Poniżej przykładowy kod, który służył jedynie celom sprawdzenia API. Nic ponadto! I niech tak zostanie.

package pl.japila.java7;

import java.util.Collections;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class Main {

    public static void main(String[] args) {
        System.out.println("Millis in a day: " + TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS));
        System.out.println("Sleeping for 2 secs");
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Collections.nCopies(3, true));
        CyclicBarrier barrier = new CyclicBarrier(1);
        try {
            barrier.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
        Phaser phaser = new Phaser(2);
        try {
            phaser.awaitAdvanceInterruptibly(phaser.arrive(), 2, TimeUnit.SECONDS);
        } catch (InterruptedException | TimeoutException e) {
            e.printStackTrace();
        }
    }

}

15 grudnia 2011

ManagementFactory.getPlatformMXBeans() w Javie 7 i nauka generyków

4 komentarzy
Jestem technicznym recenzentem książki Java 7 New Features Cookbook przed jej oficjalnym wydaniem na początku 2012 (pisałem o tym w Pierwszy rozdział o Java 7 od Packt) i w rozdziale 9. Database, Security and System Enhancements trafiłem na metodę java.lang.management.ManagementFactory.getPlatformMXBeans().

Jej użycie od razu przykuło moją uwagę, przede wszystkim dlatego, że korzysta z typowego użycia typów generycznych w Javie. Zwykle generyki sprawiały mi trudność i postanowiłem tym samym sprawdzić swoją ich znajomość. Po przejrzeniu kodu źródłowego tej metody postanowiłem spróbować swoich sił i napisać własną metodę o podobnej funkcjonalności. Co jednak istotne, to zależało mi na użyciu generyków.

I tak powstała klasa poniżej.
package pl.japila.java7;

import static java.lang.System.out;

public class Demo {

    public static void main(String[] args) throws Exception {
        int i = getInstance(Integer.class);
        out.println("i=" + i);
    }

    public static <T extends Number> T getInstance(Class<T> clazz)
            throws InstantiationException, IllegalAccessException {
        return clazz.newInstance();
    }

}
Czy dostrzegasz błąd, który popełniłem? Czy potrafisz wskazać go bez uruchamiania tej klasy? Ja niestety nie wykazałem się odpowiednią dbałością o szczegóły i umknęło mi to jedno ważne założenie. A jak u Ciebie?

Przy okazji pisania tej klasy znalazłem również sposobność, aby przetestować skrót klawiszowy w Eclipse do utworzenia statycznego importu dla System.out - Cmd+Shift+M. Spróbowałem również odszukać tej funkcjonalności przez odpalenie Quick access i tam też to można znaleźć.

Image

Dzięki Marcinowi Stachniukowi (z Agile Development Day) mogłem nauczyć się czegoś nowego o Eclipse! Dziękuję!

Przeczytałem wpis Marcina, skomentowałem go, zrecenzowałem rozdział, popróbowałem się z generykami i jeszcze zapamiętałem dwa skróty klawiszowe w Eclipse. Nie za dużo jak na jeden dzień?! :)

05 grudnia 2011

j.u.concurrent.Phaser i wątek onAdvance w Java 7

9 komentarzy
Każdorazowo, kiedy przygotowywałem klasę wspomagającą rozpoznanie java.util.concurrent.Phaser jej uruchomienie wymagało dodania opcji -ea w konfiguracji uruchomieniowej w Eclipse. W ten sposób mogłem prezentować moje doświadczenia w postaci pojedynczej klasy z użyciem assert. To jednak wymagało ode mnie właściwej konfiguracji dla każdej uruchamianej klasy (!) Wystarczy jednak mała zmiana w konfiguracji JRE i po sprawie!

Image

Podczas mojego ostatniego wystąpienia o zmianach w Java 7 w kontekście programowania współbieżnego, w którym przedstawiłem j.u.c.Phaser, padło pytanie o wątek, który uruchamia metodę protected boolean onAdvance(int phase, int registeredParties). Za pomocą tej metody kontrolujemy dostępność obiektu Phaser. Kiedy zwróci true, Phaser kończy swoje działanie. Dzięki niej, mamy również możliwość uruchomienia akcji podsumowującej fazę, kiedy ostatni wątek w danej fazie zgłosi swoje przybycie, a przed przejściem do kolejnej (jeśli takowa w ogóle nastąpi).

Podczas spotkania nie byłem w stanie odpowiedzieć na pytanie o wątek, w którym będzie uruchomiona metoda onAdvance(), co czynię teraz, w poniższej klasie.
package pl.japila.java7.concurrent.phaser;

import java.util.concurrent.Phaser;

public class PhaserOnAdvanceDemo {

    static class MyPhaser extends Phaser {
        String threadName;

        public void setOnAdvanceThreadName(String threadName) {
            this.threadName = threadName;
        }

        protected boolean onAdvance(int phase, int parties) {
            assert threadName.equals(Thread.currentThread().getName());
            return true;
        }
    }

    public static void main(String[] args) throws Exception {

        final MyPhaser phaser = new MyPhaser();

        assert 0 == phaser.getPhase();
        assert 0 == phaser.getRegisteredParties();
        assert 0 == phaser.getUnarrivedParties();

        final int parties = 2;

        phaser.bulkRegister(parties); // register 2 threads - main's and one more

        assert 0 == phaser.getPhase();
        assert parties == phaser.getRegisteredParties();
        assert parties == phaser.getUnarrivedParties();

        phaser.arrive(); // main thread arrives

        assert 0 == phaser.getPhase();
        assert parties == phaser.getRegisteredParties();
        assert 1 == phaser.getUnarrivedParties();

        Thread t = new Thread() {
            public void run() {
                phaser.arrive(); // this (sub)thread arrives
            }
        };
        phaser.setOnAdvanceThreadName(t.getName());
        t.start();

        t.join(); // wait till t dies

        assert phaser.isTerminated(); // onAdvance returned true, and hence phaser is terminated
        assert 0 > phaser.getPhase(); // phaser is terminated, and hence getPhase() returns negative number
        assert parties == phaser.getRegisteredParties();
        assert 0 == phaser.getUnarrivedParties();
    }

}
Zanim uruchomisz powyższą klasę, zastanów się, jaka może być odpowiedź. Zmiana kolejności uruchomienia phaser.arrive() ułatwia znalezienie odpowiedzi. Wystarczy przenieść linię 36 z phaser.arrive() dla głównego wątku, po t.join() w linii 50. Potrafisz wytłumaczyć dlaczego? Chętnie odpowiem na wyraźną prośbę (jej brak będzie oznaką znajomości odpowiedzi). Dla mnie to teraz taaaaakie oczywiste, ale trzeba było widzieć moją minę na prezentacji! :)

p.s. W nadchodzący piątek, 9 grudnia, występuję w roli prelegenta na konferencji Cracow.mobi z tematem RESTful Android. Będzie to moje pierwsze, androidowe wystąpienie, a 45 minut na prezentację uważam jedynie za możliwość nakreślenia tematu i jestem zmuszony do potraktowania go wyłącznie slajdami. Sugestie odnośnie sposobu i zawartości prezentacji tematu mile widziane.

02 grudnia 2011

O register() i bulkRegister(int) z j.u.concurrent.Phaser w Java 7

0 komentarzy
Przeglądając źródła j.u.concurrent.Phaser trafiłem na ciekawostkę, która z początku zaskoczyła mnie, ale kiedy się nad tym chwilę zastanowiłem, byłem nie mniej zdumiony swoim zdumieniem.

Phaser oferuje dwie metody do zarejestrowania uczestników faz - public int register() oraz public int bulkRegister(int parties).

Trudno zrozumieć, dlaczego dopiero przegląd kodu źródłowego Phaser uzmysłowiło mi, że pierwsza metoda - public int register() - jest specjalnym przypadkiem drugiej - public int bulkRegister(int parties), dla której parties = 1.

Mam wrażenie, że wynikało to z mojego błędnego zrozumienia działania tych metod, w którym sądziłem, że rejestracja jest w jakiś sposób związana z konkretnym wątkiem. Pamiętam, jak próbowałem przekazać to błędne rozumienie uczestnikom ostatniego spotkania Warszawa JUG i tylko ich czujność doprowadziła do mojego "Nie jestem pewien, jak to dokładnie działa", co w efekcie sprawiło, że zajrzałem do kodu źródłowego i teraz znam prawidłową odpowiedź (!)

A wystarczyło czytać javadoc dla Phaser ze zrozumieniem, w którym napisano:

"As is the case with most basic synchronization constructs, registration and deregistration affect only internal counts; they do not establish any further internal bookkeeping, so tasks cannot query whether they are registered. (However, you can introduce such bookkeeping by subclassing this class.)"

Proste? Teraz tak!

Poniższy przykład powinien pomóc zrozumieć problem bardziej. Od teraz już nie pomylę się i kolejna odsłona moich prezentacyjnych wyczynów wokół java.util.concurrent powinna nosić znamiona bardziej profesjonalnej :)
package pl.japila.java7.concurrent.phaser;

import java.util.concurrent.Phaser;

public class Phaser2Demo {

    public static void main(String[] args) throws Exception {
        final Phaser phaser = new Phaser();

        int parties = 3;
        for (int i = 0; i < parties; i++) {
            phaser.register();
        }

        assert 0 == phaser.getPhase();
        assert 3 == phaser.getRegisteredParties();
        assert 3 == phaser.getUnarrivedParties();

        Thread t;

        (t = new Thread() {
            public void run() {
                phaser.arrive(); // arrive and move on
            }
        }).start();

        t.join(); // awaits thread t's death

        assert 0 == phaser.getPhase();
        assert 3 == phaser.getRegisteredParties();
        assert 2 == phaser.getUnarrivedParties();

        (t = new Thread() {
            public void run() {
                phaser.arrive(); // arrive and move on
                phaser.arrive(); // arrive and move on
            }
        }).start();

        t.join(); // awaits thread t's death

        assert 1 == phaser.getPhase();
        assert 3 == phaser.getRegisteredParties();
        assert 3 == phaser.getUnarrivedParties();
    }

}
Coś niejasne? Wyjaśnić? Służę pomocą. Czym więcej pytań, tym więcej rozpoznania i tym lepsze moje zrozumienie tematu (oby i Twoje).

01 grudnia 2011

Zagadka z Rethrowing Exceptions with More Inclusive Type Checking w Java 7

7 komentarzy
Czytając bardzo krótki, acz treściwy wpis A New Java Exception Handling Idiom o nowej cesze Java 7 - Rethrowing Exceptions with More Inclusive Type Checking pomyślałem o pewnej zagadce, której próba rozwiązania wymusi choćby minimalne zrozumienie zmian wokół obsługi wyjątków w najnowszym wydaniu Javy 7. Takie perełki sprawiają, że określenie zmian jako niewielkich w tym wydaniu jest czymś, z czym mam kłopot, aby się zgodzić.

Zagadka:
package pl.japila.java7;

public class PreciseRethrowDemo {

    public static void main(String[] args) throws Exception {
        PreciseRethrowDemo demo = new PreciseRethrowDemo();
        demo.createFoo();
    }

    Foo createFoo() throws FooException {
        Bar bar = new Bar();
        try {
            return new Foo(bar);
        } catch (Throwable t) {
            t = new SubFooException();
            bar.cleanup();
            throw t;
        }
    }

    @SuppressWarnings("serial")
    static class FooException extends Exception {}
    @SuppressWarnings("serial")
    static class SubFooException extends FooException {}
    static class Foo {
        Foo(Bar bar) throws FooException {
            throw new FooException();
        };
    }
    static class Bar {
        void cleanup() {};
    }

}
Czy powyższe skompiluje się? Jeśli tak, jaki będzie rezultat? Odpowiedzi można umieszczać w komentarzach. Proszę o kolejne zagadki, jeśli spotkałeś/-aś się z podobnymi w obszarze obsługi wyjątków w Java 7.

p.s. Za kilka dni - 17 grudnia 2011 - kończy się możliwość podejścia do testowego egzaminu na Oracle Certified Associate, Java SE 7 Programmer. System wyliczył mi koszt na poziomie 61 USD i przy niekorzystnym kursie USD/PLN mimo wszystko planuję podejść do niego za 2 tygodnie. A Ty?

29 listopada 2011

85 spotkanie Warszawa JUG o zmianach w Java 7 - Adam z JVM i ja z j.u.c.Phaser

0 komentarzy
Warszawska Grupa Użytkowników Technologii Java (Warszawa JUG)
Zwykłem zapowiadać spotkania Warszawskiej Grupy Użytkowników Javy (Warszawa JUG), ale tym razem było inaczej - zapowiedzi nie było, a spotkanie i tak się odbyło. Jedynym źródłem informacji o spotkaniu, w którym Adam Michalik przedstawił temat "Zmiany JVM w Java 7", a ja wystąpiłem z "java.util.concurrent.Phaser praktycznie", była strona i forum grupy. Okazało się, że wystarczyło, aby przyciągnąć blisko 30 osób, wśród których dało się dostrzec osoby, których dawno nie widziałem. To może być dowodem na to, że grupa (ponownie) przeżywa okres rozwoju i ma się całkiem dobrze. Dodając do tego plany spotkaniowe na kolejne 3 edycje i możnaby wyciągać wnioski o jej (ponownym) rozkwicie. Coraz bardziej skłaniam się ku tezie, że bez niej wiele rzeczy nie byłoby mi dane poznać, a tak 2 godziny i mam podsumowanie - chociażby dzisiaj o Java 7 i invokedynamic.

Chciałbym wierzyć, że moja, dzisiejsza prezentacja była równie dobra merytorycznie i prezentacyjnie jak Adama, który stał się moim wzorem do naśladowania. Znalazłem w jego prezentacji kilka ciekawych elementów, które zamierzam wprowadzić do własnych, publicznych wystąpień. Przede wszystkim slajdy, które zawierały dużą dawkę rysunków. To już nie pierwszy raz, kiedy dostrzegam siłę wyrazu obrazków, rysunków, diagramów, itp. Wszystko, co nie jest tekstem warto rozważyć jako element uzupełniający i uatrakcyjniający prezentację. Dobrym rozwiązaniem byłą agenda w postaci diagramu. I ten stoicki spokój w głosie. Jest z czego, a raczej od kogo, czerpać pomysły. Dzięki Adam!

Gdyby ktoś jeszcze zechciał wyjawić, jak JRuby wykorzystuje invokedynamic, o którym Adam wspomniał, że pojawia się z generowaniem klas, aby było szybciej, byłoby jeszcze cudniej. Albo lepiej - niech to przedstawi na naszym spotkaniu. Dla przyjezdnych mogę zorganizować fundusze związane z przyjazdem.

Około 7 wszedłem na scenę z przedstawieniem java.util.concurrent.Phaser z Java 7. Sądziłem, że od ostatniego razu temat jest już mi bliżej znany na tyle wystarczająco, aby nikt mi nie "podskoczył", ale czy to styl, w którym przedstawiałem podstawy, którym łatwo dotarłem do publiczności, czy to błyskotliwość zebranych, ale nie trwało długo, kiedy moja pewność została mocno nadszarpnięta. W przyjemnej atmosferze padło kilka pytań uzupełniających, które położyły się cieniem na kilka wcześniejszych, moich stwierdzeń o Phaser. Bardzo podobała mi się ta dociekliwość uczestników, którzy jedynie w niewielkim stopniu używali java.util.concurrent - klasy Executor i współbieżne struktury. Zdziwiłem się, że nikt nie korzystał z CountDownLatch czy CyclicBarrier. Zabrakło mi mojego "mentora" z poprzedniego spotkania, który podjął się trudu nakreślenia różnic między CountDownLatch, CyclicBarrier i Phaser, kiedy dało się zauważyć moje braki. Takich ludzi cenię najbardziej. Chciałoby się mieć do nich dostęp częściej.

Jako sukces dzisiejszego spotkania traktuję rozmowę na temat przyszłych wystąpień z osobami, których parkiet WJUGa jeszcze nie gościł. Pozdrowienia dla Michała i Piotra, których zapisałem sobie jako kandydatów. Od razu wziąłem ich adresy mailowe, aby mi nie "uciekli" :)

Prezentacja z mojego dzisiejszego spotkania dostępna jest jako JacekLaskowski-WJUG-j.u.concurrent.Phaser-2011.11.29.pdf.

Zachęcam do dzielenia się swoimi doświadczeniami z poznawania czegoś nowego. Nie trzeba być geek'em, aby prezentacja poszła gładko, a częściej była przyczynkiem do dokładniejszego zgłębiania tematu. Czego mogłem dzisiaj doświadczyć. Daleko mi do znawcy tematu java.util.concurrent, a jednak kilku z uczestników dzisiejszego spotkania pozwoliło mi sądzić, że było to dla nich wartościowe. Wystarczy, abym kontynuował temat. Kolejne odsłony tematu współbieżności w Javie 7 już niebawem.

A teraz pora na Androida i podsumowywanie myśli w temacie mojej prezentacji "RESTful Android - aplikacja androidowa jako klient REST" podczas cracow.mobi w Krakowie. Będzie to moje pierwsze wystąpienie w temacie aplikacji mobilnych na Androida i bardzo chciałbym, aby nie było ostatnim. Jeśli jest coś, co wartoby zaprezentować, rozpracować, czy podobnie, napisz mi na priv. Szczególnie ciekawi mnie, czy jako uczestnik wolał(a)byś więcej kodu czy teorii? I ile to znaczy "więcej"? Niech to będzie przymiarka do najlepszej prezentacji o Androidzie, jaką udało Ci się kiedykolwiek zobaczyć! :)

12 listopada 2011

Płynny interfejs java.nio.file.attribute.AclEntry.Builder w Java 7

4 komentarzy
Trudno stwierdzić, jak wiele jest tych ciekawostek w Java 7 pod kątem wzorców użytych do rozbudowy API, ale trafiłem dzisiaj na java.nio.file.attribute.AclEntry.Builder, który zbudowany jest w oparciu o warte wzmiankowania konstrukcje programistyczne - wzorzec Budowniczy z tzw. "fluent interface" (często tłumaczone dosłownie jako "płynny interfejs"), czyli techniką konstruowania klas tak, aby metoda zwracała instancję obiektu, dla której została wywołana. W ten sposób możemy wywoływać metody, jedna po drugiej, przez ich łączenie.

Jakkolwiek wątpię, abym często obcował z AclEntry i jej pobratyńcami, to cieszę się, że pojawiła się ta klasa, która uważam, że spopularyzuje ten sposób budowania API w Javie.

Skoro rysunek może zastąpić 1000 słów, to może przykładowy kod z AclEntry.Builder również?
package pl.japila.java7.nio2;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryFlag;
import java.nio.file.attribute.AclEntryPermission;
import java.nio.file.attribute.AclEntryType;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.attribute.UserPrincipalLookupService;

public class AclEntryDemo {

     public static void main(String[] args) throws IOException {
          // who...
          UserPrincipalLookupService principalLookupService =
              FileSystems.getDefault().getUserPrincipalLookupService();
          UserPrincipal principal = principalLookupService.lookupPrincipalByName("jacek");
          System.out.printf("Principal: %s %n", principal);
         
          // ...does what.
          AclEntry aclEntry = AclEntry.newBuilder()
                    .setType(AclEntryType.ALLOW)
                    .setPrincipal(principal)
                    .setPermissions(AclEntryPermission.LIST_DIRECTORY)
                    .setFlags(AclEntryFlag.DIRECTORY_INHERIT)
                    .build();
          System.out.printf("ACL Entry: %s %n", aclEntry);
     }

}
Niezłe, co? A to wszystko dostępne w Java 7.

Przy okazji, warto zajrzeć na blog pragmatists.pl, w którym Paweł Lipiński przedstawił temat we wpisie Płynne interfejsy.

Czy ma ktoś pomysły, gdzie użyć AclEntry i jej podobych? A może już jest w użyciu u Ciebie? Jakie zastosowanie? Zachęcam do podzielenia się doświadczeniami, których mi zauważalnie brakuje.

02 listopada 2011

84 spotkanie Warszawa JUG - Warszawski Eclipse DemoCamp 2011 - Java 7, JavaFX i Eclipse

0 komentarzy
Warszawska Grupa Użytkowników Technologii Java (Warszawa JUG)
Warszawska Grupa Użytkowników Javy (Warszawa JUG) zaprasza na 83 spotkanie, które odbędzie się w najbliższy wtorek, 8 listopada 2011 o godzinie 18:00 w sali 5440 Wydziału MIM UW przy ul. Banacha 2 w Warszawie. Spotkanie jest jednocześnie oficjalnym otwarciem sezonu spotkań 2011/12 oraz świętowaniem dwóch wielkich wydarzeń w kalendarzu entuzjasty Javy - wydania Java 7 oraz dziesiątej rocznicy Eclipse.org.

Temat: Warszawski Eclipse DemoCamp 2011
Prelegenci: Piotr Chmielewski, Paweł Szklarz, Jacek Laskowski

Agenda

18:00-18:25 JavaFX Piotr Chmielewski
18:25-19:00 pizza
19:00-19:25 Garbage-First Garbage Collection w Java 7 Paweł Szklarz
19:30-20:00 java.util.concurrent w Java 7 z Eclipse Indigo SR1 Jacek Laskowski

Sponsorem naszego spotkania została firma mLife.

mLife.pl

Strona minikonferencji na eclipse.org - Eclipse DemoCamps November 2011/Warszawa.

Uprasza się o rozsądną rejestrację (wymaga potwierdzenia) na stronie Warszawski Eclipse DemoCamp 2011, aby dopasować liczbę pizz i napoi.

Wstęp wolny

Zapraszam w imieniu prelegentów i grupy Warszawa JUG!

Kontakt z organizatorem: Jacek Laskowski.

01 listopada 2011

java.util.Objects w Java 7 jeszcze raz - ostatni?

0 komentarzy
Sądziłem, że poprzednie dwa wpisy na temat java.util.Objects wyczerpały temat, ale nie tylko, że nie wykorzystałem wszystkich metod oferowanych przez tę klasę, chociażby Objects.hash(Object... values), ale sprowokowany przez komentarz ags (znany również jako Andrzej Grzesik) udało mi się znacznie uatrakcyjnić mój przykład.

Zwracam uwagę na zmiany w samej klasie Customer - metody hashCode() oraz equals(Object) oraz sam test z assertNotSame() i assertSame().

Ufam, że teraz wszyscy są usatysfakcjonowani, nieprawdaż?

package pl.japila.java7;

import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import java.util.Objects;

import org.junit.Test;

public class ObjectsTest {

 class Customer {
  public final String code;
  public final String name;

  public Customer(final String name, final String code) {
   this.name = name;
   this.code = code;
  }

  @Override
  public int hashCode() {
   return Objects.hash(name, code);
  }

  @Override
  public boolean equals(Object obj) {
   if (this == obj)
    return true;
   if (obj == null)
    return false;
   if (getClass() != obj.getClass())
    return false;
   Customer other = (Customer) obj;
   if (!getOuterType().equals(other.getOuterType()))
    return false;
   return Objects.equals(name, other.name) && Objects.equals(code, other.code);
  }

  private ObjectsTest getOuterType() {
   return ObjectsTest.this;
  }
 }

 @Test
 public void testObjectsMethods() {

  Customer jacek = new Customer("Jacek", "X23");
  Customer klonJacka = new Customer("Jacek", "X23");

  assertTrue("Klon Jacka jest Jackiem", Objects.equals(jacek, klonJacka));
  assertNotSame("Jacek nierówny swojemu klonowi", jacek, klonJacka);
  
  Customer wskazanieNaJacka = jacek;

  assertTrue(Objects.equals(jacek, wskazanieNaJacka));
  assertSame(jacek, wskazanieNaJacka);
 }

}

31 października 2011

java.util.Objects w Java 7 ponownie - bardziej pouczający przykład?

1 komentarzy
Nie mogłem życzyć sobie lepszego komentarza do mojego ostatniego wpisu o java.util.Objects - java.util.Objects w Java 7. Michał Margiel zajrzał do mnie i nie zostawił suchej nitki na moim ostatnim przykładzie, którego celem było zademonstrowanie użycia nowej klasy java.util.Objects.

"Proponuje pozmieniać wszystkie Object.equals(a,b) na a==b lub a!=b (w zalezności od asercji).

Tak tak.. ten all-in-one-test za wiele nie pokazuje :)"

Chyba byłem tak podekscytowany spotkaniem java.util.Objects, że faktycznie rozum mi odjęło, żeby prezentować przykład, w którym zwykłe porównanie wystarczy (!) Kiedy pierwszy raz zobaczyłem komentarz Michała, nie wiedziałem, czy sobie żarty ze mnie robi, czy faktycznie całe piękno mojego przykładu poszło w zapomnienie. I stało się, po chwili wiedziałem, że owym przykładem mógłbym zrobić więcej krzywdy niż pomóc. Cóż, nadrabiam teraz wierząc, że co jak co, ale klasa java.util.Objects zapadnie już wszystkim w pamięci :)

Czy poniższy przykład oddaje użyteczność klasy java.util.Objects w Java 7? Czy widomo, dlaczego poprzednio zwykłe porównanie przez równość wystarczyło? Chętnie wytłumaczę.

Metody hashCode() oraz equals(Object) wygenerowałem przy użyciu funkcji Generate hashCode() and equals()... w Eclipse.
package pl.japila.java7;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Objects;

import org.junit.Test;

public class ObjectsTest {

 class Customer {
  String name;

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

  @Override
  public int hashCode() {
   final int prime = 31;
   int result = 1;
   result = prime * result + getOuterType().hashCode();
   result = prime * result + ((name == null) ? 0 : name.hashCode());
   return result;
  }

  @Override
  public boolean equals(Object obj) {
   if (this == obj)
    return true;
   if (obj == null)
    return false;
   if (getClass() != obj.getClass())
    return false;
   Customer other = (Customer) obj;
   if (!getOuterType().equals(other.getOuterType()))
    return false;
   if (name == null) {
    if (other.name != null)
     return false;
   } else if (!name.equals(other.name))
    return false;
   return true;
  }

  private ObjectsTest getOuterType() {
   return ObjectsTest.this;
  }
 }

 @Test
 public void testObjectsMethods() {

  Customer jacek = new Customer("Jacek");

  Customer klonJacka = new Customer("Jacek");

  assertTrue("Klon Jacka jest Jackiem", Objects.equals(jacek, klonJacka));
  assertFalse("Jacek nierówny swojemu klonowi", jacek == klonJacka);
 }

}
A dziękować wiemy komu. Najserdeczniejsze podziękowania Michał!

30 października 2011

java.util.Objects w Java 7

2 komentarzy
Jutro, w poniedziałek, 31.10 o 17:24 Maksymowi "stukną" 4 tygodnie! Chłopisko coraz bardziej roztropne i zaczynam zapominać pomału, że to jeszcze niemowlę. Podczas kąpieli przerzucam go w przód, tył, ale delikatnie, bo bardzo wrażliwy. Zauważyłem, że wystarczy zbyt gwałtownie wkładać do wanienki, a już zaczyna się krzywienie miny i krzyk. Na razie o płaczu nie ma mowy, ale potrafi krzyknąć, więc po co go denerwować i okolicę. Jak tak dalej pójdzie, zanim się obejrzę, a już będzie siadał.

Image

On śpi, ja czytam i tak trafiłem dzisiaj na artykuł Guava's Objects Class: Equals, HashCode, and ToString, a w zasadzie kopię wpisu jako artykuł, w którym poznałem com.google.common.base.Objects z Google Guava oraz java.util.Objects z Java SE 7. Wspomina się w nim również o projekcie Apache Commons, w którym istnieją klasy, na których można oprzeć tworzenie metod toString() (klasa org.apache.commons.lang3.builder.ToStringBuilder), equals() (klasa org.apache.commons.lang3.builder.EqualsBuilder) oraz hashCode() (klasa org.apache.commons.lang3.builder.HashCodeBuilder). Co jednak zrobiło na mnie największe wrażenie, to fakt wciągnięcie ich odpowiedników do Java 7.

W ten sposób zwrócono moją uwagę na java.util.Objects.

Poniższa klasa testująca pokazuje działanie większości (poza jedną) metod java.util.Objects.
package pl.japila.java7;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Objects;

import org.junit.Test;

public class ObjectsTest {

 class Customer {
  String name;

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

 @Test
 public void testObjectsMethods() {
  Customer jacek = new Customer("Jacek");
  Customer agatka = new Customer("Agatka");

  Customer[] customers = { jacek, agatka };

  assertTrue("Agatka jest Agatką", Objects.equals(agatka, agatka));
  assertFalse("Jacek nie jest Agatką", Objects.equals(jacek, agatka));
  assertFalse(Objects.deepEquals(customers, new Customer[0]));
  assertEquals(jacek.hashCode(), Objects.hashCode(jacek));
  assertEquals(0, Objects.hashCode(null));
  assertEquals("null", Objects.toString(null));

  final String nullDefaultToString = "mój toString()";
  assertEquals(nullDefaultToString, Objects.toString(null, nullDefaultToString));

  final String exceptionMsg = "Zostanie zgłoszony wyjątek NPE";
  try {
   Objects.requireNonNull(null, exceptionMsg);
   fail("Powinien zostać zgłoszony wyjątek NPE");
  } catch (NullPointerException npe) {
   assertEquals("Wyjątek jest oczekiwany", exceptionMsg, npe.getMessage());
  }
 }

}
Nie mniej zaskoczyło mnie bogactwo Apache Commons, kiedy przeczytałem komentarz Craig'a Ringer'a do wpisu JDK 7: The New Objects Class:

"I'd actually love to see much of Apache Commons Lang (and Apache Commons IO) pulled into Java. Certainly StringUtils (as static methods on String), IOUtils for the static stream copying methods, FileUtils, ObjectUtils (which sounds like the conceptual origin of much of the new Objects class), CompareToBuilder, HashCodeBuilder, EqualsBuilder, ToStringBuilder, ExceptionUtils.getRootCause as a method of Throwable, etc. The JDK has been focusing on adding huge new and fancy codebases, and really neglecting the usability of the core library."

Słyszałem o tej różnorodności, ale jakoś nie dane mi było spróbować jej. Wiedza uskrzydla, a praktyka pozwala utrzymać poziom, więc raz przeczytawszy (wchodząc na odpowiedni pułap przelotowy) należy przekuć wiedzę w czyn, aby...nie spaść (jak niejednokrotnie zwraca się uwagę w wątku CV po Warsjawa 2011 na forum Warszawskiego JUGa).

Nie pamiętam również, abym wiedział o istnieniu java.lang.String.isEmpty(), która pojawiła się w Java 6 (!) Teraz już wiem.

Przy okazji, Groovy importuje automatycznie klasy z java.util, więc i Objects (podobnie jak Java importuje java.lang).

21 października 2011

NIO2 w Java 7 i OCPJP 6 PrepKit od uCertify

0 komentarzy

NIO2 w Java 7

Na dzisiejszy dzień zaplanowałem recenzję drugiego rozdziału nowej książki z Packt o Java 7. Kiedy jeszcze wczoraj, przed zaśnięciem, przeczytałem JDK 7 Adoption Guide, dzisiejszy rozdział wydał mi się lekko nudny, jakby bez życia. Ciągle ten sam schemat przedstawiania nowości z Java 7 w postaci krótkich przepisów użycia i wałkowanie typów (klasy, enum i interfejs) z pakietu java.nio.file zwanego NIO2:
W całym tym analizowaniu i podsumowywaniu udało mi się wręcz wyłapać błąd w oficjalnym dokumencie od Oracle - we wspomnianym "JDK 7 Adoption Guide" w sekcji IO and NIO, w którym napisano (drugie zdanie):

"The previous mechanism, built around the java.io.File class, is still available, but the new mechanism, built around the java.nio.Path and java.nio.Files classes, offers more robust file I/O and much greater functionality."

Potrafisz znaleźć błąd? Nie?! Odpowiedź jest powyżej (niewprost) oraz na samym końcu tego wpisu.

NIO2 robi wrażenie swoim bogactwem. Przeglądając Java SE 7 API moje oko przyciągnęły poniższe interfejsy:
Aż się chce za nie wszystkie zabrać i skomponować aplikację!

W książce działanie poszczególnych klas prezentuje się z pomocą System.out, np.
Path path = Paths.get("/ścieżka/do/pliku/który/nie/istnieje.txt");
System.out.println("Czy plik istnieje? " + Files.exists(path));  // zwróci false
Bardzo mi się to nie podoba, bo dopiero wynik pokazuje, jaki jest efekt danej metody. Zaproponowałem użycie assert, aby już czytając kod było wiadomo, do czego nim zmierzamy. Powyższy kod mógłby być zaprezentowany tak:
Path path = Paths.get("/ścieżka/do/pliku/który/nie/istnieje.txt");
assert !!!Files.exists(path) : "Plik nie może istnieć";
albo nawet tak:
Path path = Paths.get("/ścieżka/do/pliku/który/nie/istnieje.txt");
assert Files.exists(path) == false : "Plik nie może istnieć";
Które z powyższych odpowiadałoby Twoim gustom? Znasz może ciekawsze podejścia prezentowania wyniku kodu?

OCPJP 6 PrepKit od uCertify

I jakby na życzenie, dostałem propozycję recenzji zestawów do testowania od uCertify:

"In the recent past, uCertify has launched a number of new PrepKits that might be helpful for your readers. I want one more review from you since your review will also help us in improving our products.

Please visit http://www.ucertify.com/download.html for the complete list of PrepKits and let me know the name/code of the PrepKit you would like to review."


Czy powinienem odmówić takiej propozycji?! Nie, co to, to nie! Dlaczegóż nie połączyć przyjemnego z pożytecznym? I tak zabrałem się za 1Z0-851: OCP Java SE 6 Programmer. Niestety, nie jest to zestaw testów ze znajomości Java 7, ale dogłębna znajomość Java 6 nie przeszkadza wcale poznawać nowszych wydań. A może przy okazji, uwierzę w swoje umiejętności i sprawdzę się przy Oracle Certified Professional, Java SE 6 Programmer? Najbardziej zależy mi na utrwaleniu wiedzy z java.util.concurrent. Tutaj zauważam u siebie największe braki.

A skoro o nich, to okazało się, że jest ich znacznie więcej.

Jeszcze przed pójściem do łóżka, zabrałem się za test oceniający mój poziom.

Image

Jak widać na załączonym obrazku, nie najlepiej poszło, tzn. oblałem. Moje ego do tej pory nie może się pozbierać. Jeśli tego byłoby mało, można sprawdzić, w jakim obszarze poszło mi najgorzej. Wystarczy przełączyć widok na Summary report i wszystko jasne.

Image

Tam, gdzie poszukuję największych wzrostów wiedzy, tj. przy java.util.concurrent mam 100%, ale powiedzmy, że 1 pytanie z tej kategorii niewielu powaliłoby. Zaskoczony byłem niemało wynikiem OO Concepts. Teraz jednak potrafię to łatwo wytłumaczyć - po prostu nie wiedziałem, jak odpowiadać na tego typu pytanie, które związane było z przykładami klas, które dziedziczą (relacja "is-a") lub realizują więcej interfejsów (wciąż "is-a"), albo posiadają atrybuty odpowiednich typów (relacja "has-a"). Wychodzi, że umiejętność zdawania testów jest również umiejętnością, której należy się nauczyć. Nauczka na przyszłość.

Test zajął mi 30 minut, co przy 15 pytaniach, również nie należy do chwalebnych osiągnięć. Praktyka, praktyka i jeszcze raz praktyka, panie Jacku! Pora przyjrzeć się, co tam w TomEE piszczy i przygotować przykładzik, który pozwoliłby mi na zapamiętanie tych wszystkich zmian w Java 7.

(uaktualniono po uwadze Marcina Molaka) Do zapamiętania: Pakiet java.nio istnieje, ale w nim nie istnieją typy java.nio.Path oraz java.nio.Files, jak wzmiankuje się w JDK 7 Adoption Guide - IO and NIO.

20 października 2011

Przygotowanie środowiska z Eclipse Indigo SR1 i Java 7

0 komentarzy
Zbyt wiele komputerów (stacji roboczych) może doprowadzić do lekkiego zamieszania w głowie i właśnie dzisiaj tego doświadczyłem.

Byłem przekonany, że nie tylko, że mam już zainstalowane Java SE 7, ale i zaktualizowanego Eclipse IDE do wersji Indigo SR1, które udostępnia wsparcie dla Java 7. Jakież było moje zdumienie, kiedy przypomniałem sobie, że tak mam, ale...nie na tym kompie (!)

Cóż było robić - chwila z aktualizacjami Eclipse IDE, aktualizacja Java 7 i można popróbować się z kilkoma przykładami. Nic wyrafinowanego - ot, takie małe przykładziki, których celem jest przyzwyczajenie mnie do zmian w składni i nowego API.

Java 7 na Mac OS X dostępna jest na stronie openjdk-osx-build. Instalacja przebiega niezwykle sprawnie, bo sprowadza się do przekopiowania pakietu do właściwego katalogu. Dalej? Zalecam lekturę na wspomnianej stronie.

Aktualizacja Eclipse przebiegła sprawnie. Wystarczy Help > Check for Updates i zatwierdzamy znalezione aktualizacje.

Image

Można również pobrać najnowszą wersję ze strony http://eclipse.org/downloads/.

Na początku nie byłem pewien, czy oferowane aktualizacje dają mi SR1, ale kolejny ekran nie pozostawiał złudzeń - 3.7.1 to właśnie to, czego potrzebowałem.

Image

Na koniec aktualizacji, restart Eclipse i upewnienie się, że aktualizacja dotarła poprawnie w About Eclipse.

Image

Po uruchomieniu Eclipse na Java 7 w zakładce Configuration widnieje OpenJDK 1.7.0 jako środowisko uruchomieniowe.

Image

Teraz jeszcze definicja Java SE 7 w Installed JREs...

Image

...i możemy rozpocząć tworzenie projektów z Java SE 7.

Image

Na MacOS X nie jest to wciąż trywialne, aby zestawić środowisko do pracy z Java 7, ale z pomocą stronki openjdk-osx-build jest zdecydowanie prościej.

Dla wzmocnienia swojej wiedzy o zmianach w Eclipse Indigo SR1 oraz Java 7 polecam dokument What's new for Java 7 oraz JDK 7 Adoption Guide. W kilka chwil można całkiem sporo się nauczyć i nabrać przynajmniej pobieżne rozeznanie w nich. Powodzenia!

18 października 2011

Pierwszy rozdział o Java 7 od Packt

0 komentarzy
Już kiedyś wspominałem o zbiegach okoliczności i nie inaczej mógłbym zacząć ten wpis.

Skontaktowało się ze mną wydawnictwo Packt Publishing z propozycją recenzji technicznej książki o Java 7. Jakby zadań było mało, od razu się zgodziłem, aby przy okazji, a może przede wszystkim, zacząć poznawać nowości Java 7. W końcu i tak miałem się za to zabrać, a zbiegło się to w czasie z moimi planami na dokończenie października w ten sposób, więc mogę i "machnąć" recenzję.

Przeczytałem pierwszy rozdział, w którym wypisano zmiany określane mianem Project Coin. Napisałem "wypisano", ponieważ, jak na 40 stron, to i tak za mało w nich rozważań o zaletach tych zmian, więc na "opisano" to zdecydowanie za mało. Jeśli jednak wziąć pod uwagę, że książka zakłada styl ala książka kucharska (ang. cookbook), gdzie wiemy co i jak zastosować, ale niekoniecznie dlaczego, to przyjmuję ten styl.

W Java 7, dzięki Coin, dostajemy następujące zmiany (cytując stronę Coin):
  • Strings in switch
  • Binary integral literals and underscores in numeric literals
  • Multi-catch and more precise rethrow
  • Improved type inference for generic instance creation (diamond)
  • try-with-resources statement
  • Simplified varargs method invocation
W trakcie poznawania zmian dodatkowo poznałem java.lang.AutoCloseable (przy okazji tego wpisu zauważyłem, że jest nowa szata javadoc!), @SafeVarargs, java.util.Currency (klasie dostępnej od Java 1.4!), typie byte (przysiągłbym, że gdyby mnie zapytać o niego, to miałbym wątpliwości, czy istniał wcześniej, mimo częstego stosowania ByteArrayInputStream - a jest od Java 1.1!), java.nio.file.Paths i wreszcie heap pollution.

Dla mnie najbardziej wartościową zmianą w składni języka jest "more precise rethrow". Resztę uważam za ciekawą - try-with-resources, czasami mniej - strings in switch, a nawet zbędną - underscores in numeric literals.

Pewnie wiele z tych zmian, gdyby zaproponowano je w innym języku, albo zachęcano nimi do niego, nie znalazłyby uznania, ale zmian w samej konstrukcji języka Java 7 pewnie ominąć się nie da i, nawet jeśli nie ja je użyję, to zapewne inni, których kod będę czytał.

Zachęcam do zapoznania się ze wskazanymi dokumentami (pod linkami), aby po trochu zaznajamiać się z nieuniknionym.

A czy Ty masz już okazję pracować z Java 7? Która ze zmian przypadła Ci do gustu? Co w Java 7 API zasługuje na szczególną uwagę?

04 października 2011

Październik z Java 7? Tylko, jak to praktycznie wykorzystać?

1 komentarzy
Czytanie książek technicznych zaczyna przypominać u mnie objawy nałogu. Uwielbiam czytać, a książki informatyczne wręcz pochłaniam. Przyczyna jest bardzo błaha - prostota w pozyskiwaniu wiedzy, a jeśli dodać do tego możliwość poprawienia języka obcego, to jedynie ciągłość tego "procederu" zaczyna mnie niepokoić. Podobnie jak z nałogiem.

Na początku, zwykle jest banalnie, od czasu do czasu. Później ma się wrażenie, że jest dokładnie tak samo - wciąż od czasu do czasu, a jedynie obserwatorzy zauważają, że owe "od czasu do czasu" skróciło się w czasie, tj. jest wciąż od czasu do czasu, ale częściej. Z książkami jest jakoś inaczej - nałóg jest akceptowalny mimo, że z definicji, z nałogiem należy walczyć (patrz pierwsze zdanie w definicji nałogu na Wikipedii). A może jest tak, że czytanie książek nie jest i nigdy nie może być nazwane nałogiem. A więc jak?

W czytaniu książek cenię sobie ułożenie wiedzy, skompletowanie jej w jednym miejscu i różnorodny format - na urządzenia mobilne (epub czy mobi) lub po prostu stary, dobry PDF, albo tradycyjnie - druk. Z ostatnim, moim zakupem Samsung Galaxy S2 dostęp do książek jest jeszcze powszechniejszy - mam je ze sobą wszędzie. Kiedyś chodziłem z jedną pod pachą i było to dosyć uciążliwe, ale teraz mam je zawsze pod ręką. Jestem zachwycony i moja żona jest zachwycona (wyjazdy na zakupy są dla mnie po prostu zaproszeniem do lektury), i dzieciaki też skaczą z radości, bo ojciec przestał marudzić, że "shopping" to już nie marnotrastwo czasu. To chyba nazbyt różowo, co?

Image
I w zasadzie nie byłoby w tym nic nadzwyczajnego, bo każdy z nas ma swoje przywary, więc i moje uzależnienie od czytania można potraktować jak jedno, a skoro to czytanie, to nawet nie jest powszechnie traktowane w tej kategorii (paradoks?), gdyby nie fakt, że dzisiaj dotarła do mnie książka - "Java The Complete Reference", 8th Edition autorstwa Herberta Schildt'a z McGraw-Hill.

Kilka dni temu skończyłem czytać "Hello, Android", wydanie 3 i zaplanowałem sobie, i to właśnie dzisiaj, że zabiorę się za "Pro Android 2" z Apress. Cegła ogromna, bo ponad 700 stron, a mam ją w tradycyjnej postaci - drukowaną, więc taszczenie jej nie uśmiechało mi się zbytnio. Cóż jednak było robić - chce się wiedzieć więcej, to trzeba czasami pocierpieć - Android wciągnął mnie i zamiast samodzielnie rozpracowywać tematy (przynajmniej te początkowe, z którymi na pewno musiałbym się zmierzyć), wolałem postawić na przeczytanie książki. Teraz jednak, z "Java The Complete Reference" o Java 7 i nadchodzącym spotkaniu Warszawa JUG o niej, mam nielada problem. Przypomina mi się historia z osiołkiem i żłobem.

Z jednej strony chciałbym liznąć trochę tych nowości z Java 7 (skoro liznąć i wcześniej osioł to na myśl przychodzi mi scena ze Shreka, w której osioł chciał tylko liznąć gofra - patrz 0:30 w Shrek 4 Polski zwiastun HD), a z drugiej wiem, że nie dane mi z nich skorzystać w najbliższej przyszłości - powiedzmy jeszcze w tym roku. I to mnie właśnie zniechęca. Z trzeciej strony, ucząc się o Java 7 zgłębiałbym niuanse poprzednich wersji, bo nowe zwykle kontrastowane jest ze starym. Jeśli jednak miałbym postawić na inny temat niż Android w tym miesiącu, to byłaby to z pewnością tematyka Java EE 6 z IBM WebSphere Application Server 8. Skoro nie ma ciekawej pozycji książkowej na ten temat, nie mam wyboru i pozostanę jeszcze na dłuższy moment przy Androidzie. Takie wybory lubię najbardziej!

A jak to jest z Twoimi decyzjami - wybierasz książkę, czy raczej samodzielne zmagania z danym tematem z Google pod ręką. Dlaczego nie książka? I w końcu, czy masz już do czynienia z Java 7 produkcyjnie w projekcie? Zamieniam się w słuch.

07 lipca 2011

Warszawskie przywitanie Java 7 w siedzibie TouK

0 komentarzy
Wracam z obfitującego w dyskusje, warszawskiego przywitania nowej wersji Java 7, którą mieliśmy przyjemność "uruchomić" w siedzibie TouK na al. Bohaterów Września 9. Dziękuję organizatorom - Krzyśkowi i Jakubowi - za przeprowadzenie spotkania w miłej atmosferze.

Spotkanie rozpoczęliśmy o godzinie 17. Największą liczność - 12-15 osób - osiągnęliśmy już o godzinie 17:30. Rozpoczęcie prezentacji zaplanowano na godzinę 18:00, więc w międzyczasie zamówiliśmy pizzę, a kilka osób przyniosło ze sobą piwo. Strawa była zapewniona.

Chwilę po 18:00 zaczęło się ożywiać na stronie Oracle. Rozpoczęto oficjalne nadejście Java 7, której D-Day zaplanowano na dzisiaj, ale finalne wydanie będzie dostępne dopiero pod koniec lipca, więc jeszcze trochę poczekamy.

Początkowo miałem wrażenie, że spotkanie rozwali się szybciej niż się rozpoczęło, bo nie kleiło się za bardzo. Coś tam dyskutowaliśmy, coś tam zerknęliśmy na prezentację, później pizza i tak szło niemrawo, aż około godziny 18:45, kiedy widać było pierwsze znużenie tematem Java 7 omawianym dość ogólnie, przeszliśmy na dyskusje bliżej związane z naszymi aktywnościami. Porozmawialiśmy o spotkaniach WJUGa (a w zasadzie ich braku), różnicy między poziomem prezentacji na konferencjach i spotkaniach WJUGa, trochę o możliwości pracy w bankach czy innych nietechnicznych instytucjach, w których nie liczymy na wielkiej klasy inteligencję, a raczej nudę i przewalanie papierów, trochę o projektach OSS oraz kilka innych bliższych naszemu portfelowi aktywnościach. Ach, jeszcze zanim wpadliśmy na pomysł dyskutowania, zabraliśmy się za test Java 7 New Core Features na BlackBeltFactory. Testu nie przeszliśmy (!), ale zawsze mogę powiedzieć, że to była ich wina :) Nauczyłem się wiele, więc choćby z tego powodu warto było wpaść na spotkanie.

Pamiętam, jak planowałem zakończyć moją wizytę w TouKu na godzinę 19:00, ale jakoś tak dyskusje się przeciągnęły i skończyliśmy o 21:30. Sądzę, że tego typu spotkania powinny odbywać się częściej, przynajmniej raz na miesiąc i utrwaliły mnie w przekonaniu, że należy kontynuować spotkania WJUGa regularnie, co dwa tygodnie, bez względu na "wielkość" tematu, bo zawsze znajdą się chętni, aby podjąć się wyzwania wysłuchania prelegenta. Padła propozycja pisania testów jednostkowych, a może wręcz łatania oprogramowania podczas spotkań, co zamierzam wdrożyć w życie po wakacyjnej przerwie. Wydanie ostateczne Java 7 planowane jest na 28.07.2011 (za stroną domową OpenJDK 7), więc będzie można posiłkować się jej możliwościami.

Dziękuję organizatorom, szefom firmy TouK oraz innym uczestnikom za umożliwienie mi spędzenia kilku godzin czwartkowego wieczoru w bardzo miłej atmosferze. Piszę się na kolejne!