Nowości w Java 7

Java w wersji 7 zbliża się wielkimi krokami, choć idzie jej to bardzo powoli. Termin wydania pełnej wersji był już kilkukrotnie przekładany, co wynikło również z faktu przejęcia firmy Sun przez Oracle’a. Postanowiono również rozłożyć w czasie wydanie pewnych nowych funkcji języka, dlatego część z nich ukaże się dopiero w wersji 8-mej. Jako że niedawno ukazał się kolejny kamień milowy (M12) 7-ki, który zawiera pełną funkcjonalność nowej wersji języka, a w internecie jest już sporo nieaktualnych informacji o nowościach, jakie mają się w niej ukazać, postanowiłem napisać kilka szczegółów na ten temat.

Zaczęło się od tego, że zainstalowałem dzisiaj środowisko IntelliJ IDEA. Eclipse czasem mnie drażni, ale o konfrontacji tych dwóch IDE opowiem innym razem. Po otworzeniu istniejącego projektu w pierwszej kolejności postanowiłem pogrzebać trochę w opcjach. Tak też dotarłem do ustawień struktury projektu, gdzie obok wyboru SDK można było sprecyzować, jakiej wersji języka chcemy używać. Co ciekawe, przy każdej wersji IDEA wypisuje kilka słów kluczowych związanych z danym wydaniem. Przy wersji 7-mej były to: „Diamonds”, strings in switch, etc. Jako że do tej pory nie byłem na bieżąco z nową Javą, postanowiłem to nadrobić i zobaczyć, co ciekawego kryje się w Javie 7.

Nowe wydanie udostępnia szereg usprawnień zarówno w zakresie maszyny wirtualnej Javy, jak i samego języka. Jako że dla programisty najważniejsze są te drugie, bo przecież pozwalają na łatwiejsze i szybsze pisanie kodu, na początek zajmę się nimi. Postaram się w miarę możliwości przedstawiać zarówno podejście stare jak i nowe.

Diamenty, czyli wnioskowanie typu

Pierwsza rzecz, nad którą zacząłem się zastanawiać: co to są diamenty? Okazuje się, że Java 7 wprowadza uproszczone powoływanie obiektów typowanych, gdzie typy generyczne podbierane są z deklaracji zmiennej, do której przypisywany jest nowy obiekt. Diamentem został nazwany znacznik <> występujący tuż po nazwie klasy, wewnątrz którego normalnie znajdowałyby się klasy typów generycznych. Oznacza to, że zapis:

Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();

można teraz uprościć do:

Map<String, List<Integer>> map = new HashMap<>();

Niby niewiele, jednak czasem drażnią takie przydługie deklaracje.

Ciągi znaków w instrukcji switch

Kolejnym uproszczeniem jest możliwość stosowania ciągów znaków w instrukcji switch. Do tej pory dozwolone było stosowanie jedynie typów, które dało się bezpośrednio zrzutować na int’a, bądź typów wyliczeniowych (enum). Teraz można zrobić tak:

String s = "a";

switch (s) {
  case "a":
    System.out.println("a");
    break;

  case "b":
    System.out.println("b");
    break;

  default:
    System.out.println("default");
    break;
}

Również czasem przydatne, może zaoszczędzić zbędnego tworzenia enum’ów, bądź na siłę stosowania tu liczb.

Bloki automatycznego zarządzania zasobami

Jeśli często używasz w Javie dostępu do plików, bądź wykorzystujesz strumienie danych w jakiejkolwiek innej postaci, pewnie wiesz, jak ważne jest poprawne zamykanie otwartych wcześniej zasobów. Nowa wersja języka tu również wprowadza pewne usprawnienia, a kod:

URL url = new URL("http://yuppy.avd.pl");
FileOutputStream fos = null;
InputStream is = null;
try {
  fos = new FileOutputStream(new File("output.txt"));
  is = url.openStream();

  byte[] buf = new byte[4096];
  int len;
  while ((len = is.read(buf)) > 0) {
    fos.write(buf, 0, len);
  }
} finally {
  fos.close();
  is.close();
}

da się zapisać teraz tak:

URL url = new URL("http://yuppy.avd.pl");
try (InputStream in = url.openStream()) {
  Files.copy(in, Paths.get("output.txt"));
}

Prawda, że prościej? Po pierwsze, nie musimy przejmować się zamykaniem zasobów (wewnątrz nawiasów można wymienić więcej zasobów rozdzielając je średnikiem, każdy zasób musi implementować interfejs Closeable), a po drugie Java 7 dostarcza szereg klas pomocniczych w pakiecie NIO.

Ulepszone przechwytywanie wyjątków

Pomimo tego, że wyjątki typu „checked” stosuje się coraz rzadziej (choć są bardzo przydatne), to dalej często można spotkać konstrukcje złożone z kilku bloków catch, w których występuje ten sam zestaw instrukcji. Załóżmy, że mamy kod:

class A extends Exception {}
class B extends Exception {}
class C extends Exception {}

try {
  System.out.println("try");
  (...)
} catch (A e) {
  System.out.println("catch");
} catch (B e) {
  System.out.println("catch");
} catch (C e) {
  System.out.println("catch");
}

możemy zapisać go w postaci:

class A extends Exception {}
class B extends Exception {}
class C extends Exception {}

try {
  System.out.println("try");
  (...)
} catch (A | B | C e) {
  System.out.println("catch");
}

Teraz jest dużo prościej i czytelniej. Nowa funkcjonalność nazywa się „multi-catch”.

Ulepszone definiowanie literałów

Wiesz pewnie, jak mało czytelne są czasem zapisy zmiennych liczbowych. Java 7 rozwiązuje i ten problem wprowadzając możliwość stosowania podkreśleń w zapisach liczb:

int number = 1_000_000;

Można też teraz definiować liczby w systemie binarnym stosując prefix „0b”:

int binary = 0b1101_1011;

co jest równoznaczne z liczbą 219.

Uproszczone wywoływanie metod o zmiennej ilości atrybutów

Jako że w tej chwili ciężko jest uniknąć generowania ostrzeżeń przez kompilator (bez użycia tłumienia), postanowiono przenieść miejsce zgłaszania ostrzeżenia z wywołania metody na definicję metody. Chodzi o to, że często nie jesteśmy w stanie zmienić istniejących klas, a wywołanie metod tych klas powoduje zgłaszanie ostrzeżeń, musimy wtedy tłumić ostrzeżenia przy każdym takim wywołaniu. Teraz ostrzeżenie będzie zgłoszone w miejscu definicji metody, więc ciężar obsługi ostrzeżeń spadnie na twórcę danej klasy, a nie programistów ją wykorzystujących.
Niestety nie jestem w stanie przetestować tego w praktyce, gdyż środowisko IntelliJ IDEA 10.0.2, którego używam w tej chwili do testów, nie rozpoznaje poprawnie nowej składni języka. Podobnie przy opisanych wcześniej zmianach IDEA zgłasza błędy, jednak program kompiluje się poprawnie.

 

Opisane tutaj zmiany w składni języka pochodzą z projektu Coin. Niestety inne zmiany zawarte w tym projekcie, np. dotyczące wsparcia kolekcji przez składnię języka oraz kilka innych usprawnień w posługiwaniu się literałami ukażą się dopiero w Javie 8.

Przesunięte zostało też wprowadzenie domknięć do składni języka, na co chyba liczyło wielu z nas. Po szczegóły na ten temat odsyłam na stronę projektu Lambda.

To jednak nie koniec nowości. Java 7 rozszerza funkcjonalność refleksji wprowadzając nowe API w pakiecie java.dyn. Dynamiczne wołanie metod ma być teraz prostsze i o wiele bardziej przydatne. Pojawi się też szereg usprawnień maszyny wirtualnej, np. wsparcie rozszerzeń dla języków dynamicznie typowanych, które teraz mają działać z wydajnością bliską czystej Javie. Poprawiona została też architektura ładowarek klas, która pozwoli uniknąć blokad w nie-hierarchicznych topologiach.

Do ciekawszych rzeczy należy też dodanie uproszczonej obsługi współbieżności (fork/join framework), którą zastosowano w nowych implementacjach kolekcji (np. HashMap). Dzięki temu operacje na wybranych kolekcjach będą nieco szybsze, niż w starszych wersjach języka.

Trochę szkoda, że wersja 7-ma nie zostanie wzbogacona o modularyzację (projekt Jigsaw). Wszystko wygląda jednak na to, że Java 7 będzie czymś więcej, niż Java 6 w stosunku do poprzedniego wydania. Poważniejsze zmiany (domknięcia i modularyzacja) zostaną wprowadzone co prawda dopiero w wersji 8-mej, jednak czas oczekiwania na następcę Javy 6 spowoduje, że przejście na nową wersję nastąpi nieco szybciej, niż to zazwyczaj bywa. Przynajmniej taką mam nadzieję, gdyż z przykrością stwierdzam, że wiele dużych firm stosuje jeszcze oprogramowanie zgodne z Javą 5 lub co gorsza 1.4 i wcale nie zamierza tego zmieniać. Java 7 wprowadza jednak kilka istotnych udogodnień, które na pewno szybko spodobają się programistom.

Całą listę nowości możesz zobaczyć tutaj. Teraz pozostaje tylko czekać na ostateczne wydanie Javy 7, które ma się ukazać w połowie tego roku.

Skomentuj

2 Komentarze.

  1. Hmm, „siódemka” wprowadza sporo zmian upraszczających programowanie. Szkoda jednak, że każą nam jeszcze tyle czekać… :cry:

    • Do finalnego wydania pozostało kilka miesięcy, więc nie jest tak źle. Większy problem jest w tym, że tak naprawdę większość programistów oczekuje zmian, które ukażą się w Javie 8, a na tą faktycznie przyjdzie nam jeszcze trochę poczekać. Na co dzień w pracy i tak uskuteczniam Javę 5, bo serwery naszych kluczowych klientów nie uciągną nic nowszego :sad:

Skomentuj


UWAGA - Możesz używać HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

CommentLuv badge