Java 8 Co nowego w Javie 8 SE Błażej Karwowski.

Slides:



Advertisements
Podobne prezentacje
Wstęp do strumieni danych
Advertisements

C++ wykład 4 ( ) Przeciążanie operatorów.
Programowanie obiektowe
Programowanie obiektowe Andrzej Ziółkowski Wykład 3.
Klasy i obiekty.
Tworzenie i obsługa programów – przykład 3 uwagi cd. Wykorzystując różne klasy biblioteki języka Java należy pamiętać w jakim pakiecie się znajdują. Wszystkie.
Implementacja ekstensji klasy
1 1 Przykład 1/3 main() { int i,j,k,m; /* i-m : $s0-$s3 */... i = mult(j,k);... m = mult(i,i);... } int mult (int mcand, int mlier){ int product; product.
Java applet (c.d.) Nguyen Hung Son Uniwersytet Warszawski.
Nguyen Hung Son Uniwersytet Warszawski
OBJECT PASCAL Marzena Szałas.
Plasterkowanie Leszek Mierzejewski.
OOPC++ - wstêp, klasy1 Klasy Do struktury można dołączyć operacje działające na jej polach. struct date { int day, month, year; void set (int d, int m,
Jędrzej Jajor Marcin Zienkowicz
Funkcje Modularyzacja : program główny , funkcje Funkcje :
Inżynieria oprogramowania Lecture XXX JavaTM – część IV: IO
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
Programowanie wielowątkowe
Java – technologie zaawansowane Wykład 8 (9 maja 2011)
Łukasz Monkiewicz.
Czytanie, pisanie i rysowanie – cd.. Jeszcze jeden strumyk PrintStream działa jak PrintWriter, ale: Używa domyślnego (systemowego) kodowania Nie wyrzuca.
Project made by Bartosz Rumiński Kl. III i rok 2007/2008.
dr Anna Kwiatkowska Instytut Informatyki
Tablice tablica jest sekwencją elementów tego samego typu (prostego lub obiektowego) w Javie tablice są obiektami, a zmienne tablicowe przechowują referencję
Obsługa systemu wejścia-wyjścia
Język Java Wielowątkowość.
Język SQL (Structured Query Language) DDL (Data Definition Language)
Techniki i języki programowania
Podstawy C# Grupa .NET PO.
Pakiety w Javie Łukasz Smyczyński (132834). Czym są pakiety? Klasy w Javie są grupowane w pewne zbiory zwane pakietami. Pakiety są więc pewnym podzbiorem.
Podstawy programowania II Wykład 2: Biblioteka stdio.h Zachodniopomorska Szkoła Biznesu.
A ctive S erver P ages Technologia dostępu do danych.
Java 3 MPDI Programowanie obiektowe W7. import java.io.*; public class X { // kontrukcja throws – określenie jakie wyjątki może dana metoda // sygnalizować
Czym jest JavaFX? Rich Internet Application
Tadeusz Ziębakowski Zachodniopomorski Uniwersytet Technologiczny.
Podstawy inżynierii oprogramowania Zofia Kruczkiewicz
PIO 3_2, Zofia Kruczkiewicz1 Wykład 3 – część druga Iteracyjno-rozwojowy cykl oprogramowania 3.
W większości języków programowania biblioteki wejścia/wyjścia ukrywają szczegóły obsługi poszczególnych mediów pod abstrakcją strumienia (ang. stream).
TECHNOLOGIE INTERNETOWE
Programowanie obiektowe III rok EiT
Obsługa systemu wejścia-wyjścia
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
Programowanie obiektowe – zastosowanie języka Java SE
JAVA.
JAVA c.d.. Instrukcji wyboru SWITCH używamy, jeśli chcemy w zależności od wartości pewnego wyrażenia wykonać jeden z kilku fragmentów kodu. Jest to w.
Andrzej Repak Nr albumu
Java – coś na temat Klas Piotr Rosik
Inicjalizacja i sprzątanie
Seminarium problemowe
Systemy wejścia i wyjścia Michał Wrona. Co to jest system wejścia i wyjścia? Pobierania informacji ze źródeł danych, zdolnych przesyłać sekwencje bajtów,
C# Platforma .NET CZ.3 Kuba Ostrowski.
Tworzenie Aplikacji Internetowych dr Wojciech M. Gańcza 8.
1 Strumienie Hierarchie klas strumieniowych, strumienie bajtowe - klasy InputStream i OutputStream i ich metody, klasa File, strumienie plikowe, strumienie.
  ELEMENTY JĘZYKA JAVA komentarze w Javie, słowa kluczowe i operatory, proste typy danych, tablice, podstawowy zestaw instrukcji.
Kurs języka C++ – wykład 13 ( )
Treści multimedialne - kodowanie, przetwarzanie, prezentacja Odtwarzanie treści multimedialnych Andrzej Majkowski informatyka +
Waldemar Bartyna 1 Programowanie zaawansowane LINQ to XML.
Elementy programowania funkcyjnego w Javie 8. Pragmatyczny przegląd. (c) Krzysztof Barteczko 2014.
Języki i technologie wytwarzania stron WWW Autor: Michał Walkowski Referat.
1 Kolekcje i tablice © Krzysztof Barteczko, PJWSTK 2009.
Implementacja asocjacji (z atrybutami i bez) przy użyciu: referencji (kolekcji referencji) tablic asocjacyjnych przygotował: Kamil Kowalczyk.
W pełni obiektowyInterpretowany i kompilowany Kompilowany do JVM Bytecode Umożliwia korzystanie z bibliotek Java Skonstruowany z myślą o wysokiej produktywności.
Strumienie, Wczytywanie, Zapisywanie, Operacje na plikach
Wątki, programowanie współbieżne
Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych
(c) Krzysztof Barteczko 2014
Programowanie obiektowe – zastosowanie języka Java SE
Aplikacje i usługi internetowe
Założenia projektowe Javy
Programowanie w Javie 1 Dr Robert Kowalczyk
Zapis prezentacji:

Java 8 Co nowego w Javie 8 SE Błażej Karwowski

λ Agenda Wyrażenia i inne nowości w języku Zmiany w kolekcjach =cześnie Kilka słów o bezpieczeństwie I18N oraz czas i data Java FX – lepszy Swing? Nosorożec czyli JavaScript w Javie λ TSL włączone domyślnie Większa dostępność algorytmów opartych o AES SecureRandom i getInstanceStrong() – najsilniejsza dostępna implementacja Z bardziej znanych zmiany w dostępie przez Kerberos 5

Wyrażenia λ i inne nowości w języku Zmiany w Javie .............................. ? Znowu? Wyrażenia λ Referencje do metod i metody domyślne Zmiany w adnotacjach Czy faktycznie zmiany w Javie są potrzebne? Można by powiedzieć – jeśli nie są ci potrzebne to ich po prostu nie używaj. Jednak faktycznym powodem największych zmian w Javie 8 jest programowanie współbieżne. Już wcześniej w Javie obsługa pisania programów wielowątkowych była całkiem niezła. Przy projektowaniu wcześniejszych wersji javy zdecydowano jednak na zastosowanie „niskopoziomowego” podejścia co wymagało od programistów szczególnej uwagi. Jednocześnie brakowało narzędzi do łatwego rozdzielania pracy pomiędzy wątki przy pracy z kolekcjami. Rozwiązaniem stały się wyrażenia Lambda, wymagają wprawdzie nauczenia pewnych elementów nowej składni jednak dają możliwość łatwego pisania bezpiecznego kodu wielowątkowego. Wraz z wprowadzeniem wyrażeń lambda stało się konieczne dodanie kilku innych elementów aby można było je obsługiwać: Referencje do metod skoro posiadamy już obsługę wyrażeń lambda warto w ich roli użyć zwykłych metod. Dostęp w taki sposób uzyskujemy przez operator :: . Wstawiając go w miejsce kropki pomiędzy nazwą obiektu lub klasy a nazwą metody (lub new – dla konstruktora) Zmiany w adnotacjach – dwie najważniejsze to: Możliwość dodania wielokrotnie tej samej adnotacji do jednej klasy/metody. W przypadku tworzenia takie adnotacji konieczne jest stworzenie dodatkowej adnotacji z polem value „zbierającym” użycia tejże adnotacji. Konieczne jest także opatrzenie wielokrotnie używanej adnotacji @Repetable(nazwa_zbierającej.class) Drugą jest możliwość użycia adnotacji wszędzie tam gdzie możliwe jest użycie typu. Np. @Immutable Date date = new Date(0); możliwe jest wykrywanie błędów już na etapie kompilacji. Ostatnią z w mojej opinii zmian jest umożliwienie poznania nazw parametrów w metodach. Niestety wymaga wywołania javac z parametrem -parameters Refleksja parametrów metod

Wyrażenia λ Runnable noArguments = () -> System.out.println("Hello World"); ActionListener oneArgument = event -> System.out.println("button clicked"); Runnable multiStatement = () -> { System.out.print("Hello"); System.out.println(" World"); }; BinaryOperator<Long> add = (x, y) -> x + y; BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y; Wyrażenia lambda to swego rodzaju funkcje anonimowe, które muszą być przypisywane do klas/interfejsów z adnotacją @FunctionalInterface. Interfejsów posiadających tylko jedną metodę abstrakcyjną. Możliwe jest kilka sposobów użycia wyrażeń Lambda: Interfejs Runnable posiada tylko jedną metodę bezparametrową run (nie zwracającą żadnej wartości – void) Z powodu użycia tylko jednego argumentu możemy opuścić nawiasy, tak samo w przypadku „ciała” metody/funkcji Przykład użycia bloku kodu – konieczne są nawiasy {} Możliwe jest stworzenie metod które posiadają więcej niż jeden parametr – konieczne jest zastosowanie nawiasów () Należy pamiętać, że w pomimo zapisu wyrażenia lambda, są one jednak typowane i możliwe jest określenie tych włąśnie typów.

Wyrażenia λ – przydatne interfejsy Argumenty Wartość zwracana Przykład Predicate<T> T Boolean Czy dziś jest czwartek? Consumer<T> Void Wypisywanie na ekran. Function<T,R> R Pobranie wartości z obiektu. Supplier<T> Brak () Metoda tworząca obiekty UnaryOperator<T> Logiczne not (!) BinaryOperator<T> (T , T) Np. dodawanie, mnożenie Przykłady użycia wyrażeń lambda w dalszej części.

Referencje do metod Rodzaj Przykład Referencja do metody statycznej NazwaKlasy::nazwaMetodyStatycznej Referencja do zwykłej metody Objekt::nazwaMetody Referencja do metody wywoływanej na rzecz obiektu danego typu NazwaTypu::nazwaMetody Referencja do konstruktora NazwaKlasy::new (NazwaKlasy[]::new)

Metody domyślne Dlaczego istnieją? Wielodziedziczenie Przykład: default void forEach(Consumer<? super T> action) { for (T t : this) { action.accept(t); } Ze względu na rozbudowę standardowych interfejsów o obsługę wyrażeń lambda konieczne było stworzenie mechanizmu który byłby w stanie zapobiec błędom w istniejącym kodzie który przestałby się kompilować/ładować. Z tego powodu interfejsy zostały wzbogacone o metody domyślne. Jednocześnie spowodowało to umożliwienie wielodziedziczenia, co wcześniej nie było możliwe w Javie. Przy czym trzeba pamiętać, że w przypadku istnienia metod o tej samej sygnaturze w dwóch interfejsach „wygrywa” ten bardziej zagnieżdżony, a jeśli istnieje implementacja w jakiejś klasie to właśnie ta implementacja zostanie wybrana. Przy czym należy pamiętać, że jeśli kompilator nie będzie w stanie dobrać implementacji na tej zasadzie to klasa musi zaimplementować tę metodę bądź też oznaczyć ją jako abstrakcyjną.

Zmiany w kolekcjach Obsługa λ, „strumieni” i „operacji agregujących” Poprawa wydajności Zmiany w kolekcjach w Javie 8 to głównie dodanie obsługi wyrażeń lambda, „strumieni” i „operacji agregujących”. O czym za chwilę. Jednak nie należy zapominać o zmianach w implementacji HashMap, LinkedHashMap oraz ConcurrentHashMap w przypadku gdy następuje duża ilość takich samych kluczy.

Zmiany w kolekcjach – zmienione pakiety Zmodyfikowane pakiety PAkiet Nowe klasy Zmodyfikowane klasy java.io UncheckedIOException BufferedReader java.lang -- AutoCloseable ThreadLocal String Iterable CharSequence Boolean Integer Long Float Double java.nio.file Files java.util PrimitiveIterator Arrays Spliterator BitSet DoubleSummaryStatistics Collection IntSummaryStatistics Comparator LongSummaryStatistics Iterator Optional List OptionalDouble Map OptionalInt Map.Entry OptionalLong LinkedHashMap Spliterators Random SplittableRandom TreeMap StringJoiner   java.util.concurrent ThreadLocalRandom java.util.jar JarFile java.util.zip ZipFile java.util.logging Logger java.util.regex Pattern Nowe pakiety java.util.function java.util.stream Pakiet java.util.function – zawiera interfejsy stanowiące ułatwienie przy tworzeniu wyrażeń lambda, z których kilka wymieniłem wcześniej. Z kolei java.util.stream – to klasy i interfejsy przeznaczone do obsługi strumieni i „operacji agregujących” . Po prawej widać listę pakietów i klas które zostały zmodyfikowane w celu współpracy z wyrażeniami lambda.

Zmiany w kolekcjach – strumienie Cechy: Brak przechowywanych danych Funkcyjne Leniące się :D Potencjalnie nieskończone Zużywalne Sposoby tworzenia: Na podstawie kolekcji za pomocą metod stream() i parallelStream() Z tablic za pomocą Arrays.stream(Object[]) Za pomocą metody wytwórczej np. Stream.of(Object[]), IntStream.range(int, int) Na podstawie linii z pliku za pomocą: BufferedReader.lines() Z klasy Random za pomocą metody ints() Za pomocą wielu innych metod z JDK. Brak przechowywanych danych – nie są strukturą danych, przeprowadzają natomiast operacje na danych pochodzących ze kolekcji, tablicy, kanału we-wy Funkcyjne – nie modyfikują źródła Leniące się :D – operacje na stream-ach mogą być wartościowane leniwe, czyli tylko wtedy kiedy zachodzi taka potrzeba Potencjalnie nieskończone – stream-y nie posiadają określonej wielkości, możliwe są operacje na nieskończonych stream-ach Zużywalne – w czasie istnienia obiektu stream każdy jego element może zostać „odwiedzony” tylko raz, w przypadku konieczności dostępu wielokrotnego trzeba tworzyć nowy stream foreach etc. Operacje agregujące to „coś” podobnego do Iteratorów, są jednak różnice: Używają wewnętrznej, sterowanej przez JDK iteracji Operują na strumieniach, nie bezpośrednio na kolekcjach Pozwalają zmieniać swoje zachowanie, na podstawie parametrów (λ)

=cześnie czyli współbieżność λ również tutaj Nowe klasy, metody i interfejsy Zmiany spowodowane wyrażeniami lambda dotarły również tutaj, jako przykład niech mi posłuży klasa java.util.concurrent.ConcurrentHashMap. Znalazło się w niej ponad 30 nowych metod takich jak różnego rodzaju: forEach (_,key,valu,entry), search(_,keys,values,entries), czy reduce(_,toDouble,toLong). Nowe klasy i interfejsy trafiły również do pakietów java.util.concurrent i java.util.concurrent.atomic. Do pierwszego z nich trafiły 2 interfejsy i 4 klasy. Do drugiego 4 nowe klasy, są to Long/DoubleAccumulator i Long/DoubleAdder – przeznaczone do sumowania w środowisku wielowątkowym, jako dużo szybsze od standardowych klas atomowych.

Przykłady – operacje na strumieniach collect(toList()) List<String> collected = Stream.of("a", "b", "c").collect(Collectors.toList()); map List<String> collected1 = Stream.of("a", "b", "hello") .map(string -> string.toUpperCase()) .collect(Collectors.toList()); filter List<String> beginningWithNumbers = Stream.of("a", "1abc", "abc1") .filter(value -> Character.isDigit(value.charAt(0))) Collect – zachłanna operacja tworząca listę z wartości pobranych ze strumienia

Przetwarzanie współbieżne a równoległe

Przetwarzanie równoległe oraz λ List<Pracownik> pracownicy = Arrays.asList( new Pracownik("Adam", "Kowalski", 1.5), new Pracownik("Maciej","Majewski", 2.0), new Pracownik("Jędrzej", "Kaczmarek", 0.5), new Pracownik("Zofia", "Szczepańska", 3.0)); double sumaCzasupracySzeregowo pracownicy.stream().mapToDouble(Pracownik::getStazPracy).sum(); double sumaCzasupracyRownloegle = pracownicy.parallelStream().mapToDouble(Pracownik::getStazPracy).sum(); double[] values = new double[100]; Arrays.parallelSetAll(values, i -> new Random().nextDouble());

Przetwarzanie równoległe oraz λ i [] double[] values = new double[100]; Arrays.parallelSetAll(values, i -> new Random().nextDouble()); Arrays.parallelSort(values); Arrays.parallelPrefix(values, Double::sum); Metoda Efekt parallelPrefix Podmienia wartość elementu na wartość funkcji parallelSetAll Ustawia wartości wg zadanego λ parallelSort Sortuje elementy w tablicy

I18N oraz czas i data I18N: Umiędzynarodowienie ThreeTen: Czas dla komputera i człowieka I18N – umiędzynarodowienie (trudne słowo) *Dodanie obsługi Unicode w wersji 6.2.0 – choć najnowsza to 6.3. *Umożliwiono użycie CLDR – największego repozytorium danych/ustawień regionalnych. *Ze względu na możliwość użycia CLDR nastąpiły zamiany w klasach Calendar i Locale Calendar obsługa kalendarzy po nazwie, nowe formaty dat Locale obsługa rozszerzeń SPI, znajdowanie najbardziej zbliżonego „locala” *SPI pozwala na zmiany w aplikacji bez rekompilacji kodu, w Javie 8 będzie można dodać resource bundle (.properties) jako rozszerzenie ThreeTen: Implementacja JSR 310 dla Javy 8. Zawiera się w pakiecie java.time pakiet opiera się na kalendarzu ISO, jednak inne popularne kalendarze również są dostępne. Implementacja czasu mogła by się wydawać prostą sprawą. Liczymy milisekundy od 1 stycznia 1970 i voila. Jednak istnieją pewne subtelności, jak na przykład różnica w uzyskanym efekcie po dodaniu do 31 stycznia jednego miesiąca w roku zwykłym i przestępnym. Często zdarza się, że nawet duże firmy popełniają błędy w obsłudze czasu. Np. w Hearts of Iron II mamy 30 lutego. A co jeśli nie będzie to „zabawna” pomyłka?

Prostota Płynność Niezmienność Rozszerzalność JSR 310: Date-Time API Prefix Use of Zazwyczaj walidacja from Konwersja do daty/czasu parse Konwersja z daty/czasu do docelowej klasy format Konwersja na string – w zadanym formacie get Pobranie części np. godziny z obiektu czasu is Sprawdzenie stanu with Utworzenie kopii z zmienioną jedną z „wartości” plus Dodanie czasu minus Odjęcie czasu to Konwersja na inny typ at Połączenie obiektów Prostota Płynność Niezmienność Rozszerzalność JSR 310 zostało zbudowane przy zachowaniu czterech zasad: Prostoty – metody są dokładnie zdefiniowane, a ich wyniki przewidywalne. Np. podanie do metody null zazwyczaj spowoduje wyrzucenie wyjątku NullPointerException. Płynności – API jest tak zbudowane by kod był łatwy do odczytania. Dzięki braku zwracania null-a, metody mogą być „łańcuchowane. Niezmienności – obiekty są tworzone tak aby po stworzeniu nie mogły zostać zmodyfikowane, więc w celu zmiany konieczne jest stworzenie nowego obiektu lub kopii aktualnego. Dodatkowo zapewnia to bezpieczeństwo stosowania w aplikacjach wielowątkowych oraz powoduje, że obiekty nie posiadają metod set. Rozszerzalności – większość klas/interfejsów jest zbudowana tak by w maksymalnym zakresie umożliwić dziedziczenie. Wartym wspomnienia elementem są prefixy: Nowe pakiety: java.time – pakiet bazowy dla obsługi daty i czasu. Zawiera klasy dla daty, czasu, data i czasu równocześnie, stref czasowych, interwałów. Oparty jest o standard ISO-8601. Tworzone obiekty są niemodyfikowalne i thread-safe. java.time.chrono – pakiet dodający obsługę kalendarzy innych niż oparte na ISO-8601. Możliwe jest zdefiniowanie własnego kalendarza. java.time.format – klasy obsługujące formatowanie i parsowanie daty i czasu. java.time.temporal – klasy na potrzeby autorów frameworków i twórców bibliotek. java.time.zone – obsługa stref czasowych.

JSR 310: Date-Time API – przykład I System.out.printf("Aktualna data i czas: %s%n", LocalDateTime.now()); System.out.printf("1 lutego 2001 21:10: %s%n", LocalDateTime.of(2001, Month.FEBRUARY, 1, 21, 10)); System.out.printf("Aktualna data i czas: (z Instant): %s%n", LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault())); System.out.printf("Za 6 miesiące będzie: %s%n", LocalDateTime.now().plusMonths(6)); DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM d yyyy HH:mm"); System.out.printf("6 miesięcy temu było: %s%n", LocalDateTime.now().minusMonths(6).format(format)); package java8new; import java.time.Instant; import java.time.LocalDateTime; import java.time.Month; import java.time.ZoneId; public class dateTimeExample1 { public static void main(String[] args) { System.out.printf("Aktualna data i czas: %s%n", LocalDateTime.now()); System.out.printf("1 lutego 2001 21:10: %s%n", LocalDateTime.of(2001, Month.FEBRUARY, 1, 21, 10)); System.out.printf("Aktualna data i czas: (z Instant): %s%n", LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault())); System.out.printf("Za 6 miesiące będzie: %s%n", LocalDateTime.now().plusMonths(6)); System.out.printf("6 miesięcy temu było: %s%n", LocalDateTime.now().minusMonths(6)); }

JSR 310: Date-Time API – przykład II Instant t1, t2; t1 = Instant.now(); System.in.read(); t2 = Instant.now(); Duration timeBeetwen = Duration.between(t1, t2); System.out.println("Zmierzony czas: " + timeBeetwen); long timeBeetwen2 = ChronoUnit.MILLIS.between(t1,t2); long timeBeetwen3 = ChronoUnit.SECONDS.between(t1,t2); long timeBeetwen4 = ChronoUnit.HOURS.between(t1,t2); System.out.println("Zmierzony czas: " + timeBeetwen2 + " milisekund."); System.out.println("Zmierzony czas: " + timeBeetwen3 + " sekund."); System.out.println("Zmierzony czas: " + timeBeetwen4 + " godzin.");

JSR 310: Date-Time API – przykład III LocalDate today = LocalDate.now(); LocalDate birthday = LocalDate.of(1983, Month.JANUARY, 29); LocalDate nextBirthday = birthday.withYear(today.getYear()); if (nextBirthday.isBefore(today) || nextBirthday.isEqual(today)) { nextBirthday = nextBirthday.plusYears(1); } Period toNextBirthday = Period.between(today, nextBirthday); System.out.printf("Do następnych urodzin pozostało: %s miesięcy %s dni %n", toNextBirthday.getMonths(),toNextBirthday.getDays());

Zapatrzenie w MacromediaAdobe Flash Java FX 2.x – Lepszy SWING? Zapatrzenie w MacromediaAdobe Flash FXML and Scene Builder WebKit – przeglądarka wewnątrz apletu? Grafika 2D i 3D SWING wewnątrz Java FX Canvas API Drukowanie Rich Text Akceleracja sprzętowa Stremowanie mediów CSS

Bardziej Java niż Script? JavaScript w Javie ? Java SE 6 – Rhino 1.6R2 Java SE 7 – Rhino 1.7R3 Java SE 8 – Nashorn 11 grudnia 2006 28 lipca 2011 Rhino – JavaScript 1.7 (ECMA 3) Nashorn - Nashorn 1.8.0 (ECMA 5.1) Firefox - JavaScript 1.8.5 (ECMA 5) 18 marca 2014

JavaFX & Nashorn - przykład var Button = javafx.scene.control.Button; var StackPane = javafx.scene.layout.StackPane; var Scene = javafx.scene.Scene; function start(primaryStage) { primaryStage.title = "Hello World!"; var button = new Button(); button.text = "'Hello World'"; button.onAction = function() print("Hello World!"); var root = new StackPane(); root.children.add(button); primaryStage.scene = new Scene(root, 300, 250); primaryStage.show(); } jjs -fx fxNashorn.js

Pytania ?

DZIĘKUJĘ ZA UWAGĘ