JShell to nowa funkcja w Javie 9 ułatwiająca uruchamianie fragmentów kodu. Fragmenty kodu JShell są dokładnie takie same, jak kod źródłowy Java w pliku aplikacji. Jak omówiono we wcześniejszym artykule „Using JShell in Java 9 in NetBeans 9.0, Part 3”, JShell nie zezwala na kilka modyfikatorów — w tym domyślny, dostępowy, zsynchronizowany, publiczny, prywatny i chroniony — które są obsługiwane w pliku kodu źródłowego . JShell jest przeznaczony głównie do testowania i debugowania kodu Java, a nie do uruchamiania kompletnych aplikacji. W tym dalszym artykule będziemy uruchamiać fragmenty dla klas, interfejsów i tablic. Użyliśmy NetBeans 9 tak jak we wcześniejszych artykułach. Omówimy również niesprawdzone wyjątki. Ten artykuł ma następujące sekcje:
- Korzystanie z klas
- Modyfikowanie klasy
- Klasy aukcji
- Korzystanie z konstruktorów klas
- Rozszerzanie klasy
- Zastępowanie metody
- Korzystanie z interfejsów
- Korzystanie z domyślnej implementacji metody
- Deklarowanie metody interfejsu jako statycznej
- Korzystanie z tablic
- Korzystanie z niesprawdzonych wyjątków
- Wniosek
Korzystanie z klas
W tej sekcji omówimy uruchamianie fragmentów kodu dla klas. Zadeklaruj prostą klasę C w następujący sposób.
[1]-> class C { } | created class C
Klasa C zostaje utworzony. W przeciwieństwie do metody, która może być wywoływana bezpośrednio, klasa musi najpierw zostać utworzona w następujący sposób.
[3]-> new C() | $1 ==> [email protected]
Nowa instancja klasy C, $1 zostaje utworzony. Podobnie jak w przypadku deklaracji metod, deklaracje klas można modyfikować poprzez ponowne zadeklarowanie klasy. Klasa może implementować interfejs za pomocą implementów . Jako przykład zadeklaruj interfejs I .
[1]-> interface I{} | created interface I
Utwórz klasę C zaimplementować interfejs I .
[3]-> class C implements I{} | replaced class C [4]->
Klasa C , utworzony wcześniej, zostanie zastąpiony.
Deklaracja klasy w JShell nie zawiera koncepcji aplikacji, jaką miałaby klasa Java zadeklarowana w pliku. Klasa Java w pliku z publiczną statyczną void main(String[] argv) metoda jest aplikacją Java. publiczny statyczny void main(String[] argv) Metoda może zostać dodana w JShell, ale jest to tylko kolejny fragment kodu. Utwórz zajęcia Cześć która zawiera metodę public static void main(String[] argv) .
[1]-> class Hello{ public static void main(String[] argv){System.out.println (argv[0]+argv[1]);} } | created class Hello [2]->
główny(Ciąg[]) metoda jest statyczna metoda i jest zdefiniowana dla klasy, a nie dla instancji klasy. Utwórz Ciąg[] tablica do dostarczenia do main(String[]) metoda.
String[] strArray={"Hello"," JShell"};
Wywołaj main(String[]) metoda z String[] jako argument.
Hello.main(strArray)
Komunikat Hello JShell zostaje wypisany, jak pokazano na rysunku 1.
Rysunek 1: Wywołanie metody statycznej w klasie
Modyfikowanie klasy
W razie potrzeby klasę można modyfikować, modyfikując lub usuwając dowolne jej deklaracje metod lub dodając nowe metody. Ponownie zadeklaruj klasę Cześć bez main(String[]) metoda i klasa zostają zastąpione.
[4]-> class Hello{ } | replaced class Hello [5]->
Ponownie dodaj main(String[]) metoda, ale z nieco inną System.out.println oświadczenie. Klasa Cześć ponownie zostaje zastąpiony.
[5]-> class Hello{ public static void main(String[] argv) {System.out.println(argv[0]);} } | replaced class Hello [5]->
Wywołaj statyczny metoda main(String[]) z Hello.main(strArray) dla innego wyjścia, jak pokazano na rysunku 2.
Rysunek 2: Wywoływanie wariacji metody głównej
Przepis dotyczący zastąpienia klasy jest przydatny podczas tworzenia klasy. Jedna metoda może być dodawana na raz i testowana w klasie. Jako przykład dodaj drugą metodę hello(String) . Ponownie, klasa Cześć zostanie wymieniony.
[9]-> class Hello{ void main(String[] argv){System.out.println(argv[0]);} String hello(String name){return name;} } | replaced class Hello
Metoda hello(String) dodane, jako metoda instancji, wymagałoby wywołania instancji klasy. Utwórz instancję klasy.
[10]-> new Hello() | $2 ==> [email protected]
Wywołaj metodę hello(String) przy użyciu instancji klasy $2 .
[11]-> $2.hello("John") | $6 ==> "John"
Klasy aukcji
Klasa Java to typ. Interfejs to także typ. Wszystkie typy zdefiniowane w sesji JShell są wymienione w /types Komenda. Zdefiniuj kilka klas i interfejsów.
[4]-> [1]-> class C{} | created class C [2]-> class D{} | created class D [3]-> class B{} | created class B [4]-> interface I{} | created interface I [5]-> interface J{} | created interface J
Uruchom /types polecenie i wszystkie klasy i interfejsy zostaną wyświetlone.
[6]-> /types | class C | class D | class B | interface I | interface J
Korzystanie z konstruktorów klas
Klasa no-arg jest niejawnie zdefiniowana w klasie, jeśli nie definiuje żadnych konstruktorów z argumentami. Wcześniej stworzyliśmy instancję klasy C który nie zadeklarował jawnie żadnych konstruktorów z nowym C() . Konstruktor bezargumentowy może być zdefiniowany jawnie.
Następnie utwórz klasę Witaj który deklaruje konstruktor klasy. Konstruktor ma jeden parametr typu String . Konstruktor może być zadeklarowany z public modyfikator i jest domyślnie publiczny jeśli nie jest ustawiony na publiczny .
[6]-> class Hello{ String name; public Hello(String name){this.name=name;} void hello(){System.out.println("Hello "+name);} }
Utwórz instancję klasy Witaj .
Hello hello=new Hello("John")
Wywołaj metodę instancji hello() aby wysłać wiadomość, jak pokazano na rysunku 3.
Rysunek 3: Używanie klasy z konstruktorem
Rozszerzanie klasy
Klasę można rozszerzyć za pomocą rozszerzeń, tak jak w pliku kodu źródłowego Java. Jako przykład utwórz klasę D która deklaruje nazwę zmiennej typu tt>String, konstruktora bezargumentowego i metodę hello(String) . Witaj(Ciąg) metoda wypisuje "Cześć" wiadomość używając nazwy arg dostarczony.
class D{ String name="Michael"; public D(){} void hello(String name){System.out.println("Hello "+name);} }
Utwórz klasę C która rozszerza klasę C i deklaruje hello() metoda, która nie nadpisuje klasy D 's cześć(Ciąg) metoda i parametry są różne. Witaj() metoda wywołuje nazwę pola, która jest dziedziczona z klasy D .
class C extends D{ void hello(){System.out.println("Hello "+name);} }
Utwórz wystąpienie klasy C i wywołaj hello() metoda.
new C().hello()
Komunikat „Hello” zostanie wyświetlony, jak pokazano na rysunku 4. Nazwa wartość pola ustawiona w klasie D jest używany.
Rysunek 4: Rozszerzanie klasy
Jeśli wywołaliśmy hello(String) metoda klasy C dziedziczy z klasy D , otrzymalibyśmy inny wynik, jak pokazano na rysunku 5.
Rysunek 5: Wywoływanie metody dziedziczonej z klasy rozszerzonej
Zastępowanie metody
Klasa może przesłonić metodę odziedziczoną z klasy rozszerzonej, dostarczając własną definicję metody. Utwórz klasę D który deklaruje pole nazwa i metoda hello() .
class D{ String name="Michael"; void hello(){System.out.println("Hello "+name);} }
Zadeklaruj klasę C która rozszerza klasę D i nadpisuje hello() metoda. Klasa C ukrywa również pole nazwa .
class C extends D{ String name="John"; void hello(){System.out.println("Hello "+name); }
Utwórz instancję klasy C i wywołaj metodę hello() .
new C().hello()
Witaj() metoda z klasy C jest wywoływany, ponieważ nadpisuje metodę z klasy D . Pole nazwa w klasie C ukrywa pole nazwa w klasie D . Wyjście wiadomości pokazano na rysunku 6.
Rysunek 6: Zastępowanie metody
Jeśli klasa C nie ukrywa pola nazwa z klasy D , nazwa pole w klasie D jest używany, jak pokazano na rysunku 7.
Rysunek 7: Dostęp do pola z klasy rozszerzonej
Klasa C obiekt jest instancją klasy D ponieważ rozszerza klasę D . Uruchom następującą instrukcję, aby sprawdzić, czy instancja klasy C jest również instancją klasy D .
new C() instanceof D
Wartość prawda weryfikuje instancję klasy C jest również instancją klasy D , jak pokazano na rysunku 8.
Rysunek 8: Weryfikowanie, czy instancja klasy C jest również instancją klasy D
Ponieważ instancja klasy C jest również instancją klasy D , może być rzutowany na D w następujący sposób:
D d=(D)(new C());
Następnie uzyskaj dostęp do pola nazwa dla obiektu d typu D .
d.name;
I wywołaj metodę hello() dla obiektu d typu D .
d.hello();
Dane wyjściowe wartości pola pochodzą z klasy D ponieważ d jest obiektem typu D , jak pokazano na rysunku 9. Metoda hello() wywoływany jest z klasy C .
Rysunek 9: Przesyłanie obiektu typu C do D
Korzystanie z interfejsów
W tej sekcji uruchomimy kilka fragmentów dla interfejsów w JShell. Istniejąca klasa może zostać zmodyfikowana w celu zaimplementowania interfejsu. Utwórz klasę C .
[1]-> class C{} | created class C
Utwórz interfejs I która definiuje metodę hello() .
[2]-> interface I { String hello(); } | created interface I
Ponownie zadeklaruj klasę C zaimplementować interfejs I . Klasa C zapewnia implementację metody hello() .
[3]-> class C implements I{ public String hello(){ return "Hello JShell"; } } | replaced class C
Utwórz instancję klasy C .
[4]-> new C() | $1 ==> [email protected]
Używając zmiennej instancji klasy, wywołaj metodę hello() a wynik metody zostanie wyświetlony.
[5]-> $1.hello() | $2 ==> "Hello JShell" [6]->
Ponieważ metody w interfejsie są domyślnie publiczne podczas gdy metody w klasie nie są metodą, implementacja w klasie C musi być zadeklarowany z publicznym modyfikator dostępu. Jeśli nie jest zadeklarowany jako publiczny , wyświetlany jest komunikat o błędzie, ponieważ nie określono publicznego modyfikator dostępu domyślnie przyjmuje słabszy modyfikator dostępu, co nie jest dozwolone podczas implementacji interfejsu.
[3]-> class C implements I{ String hello(){ return "Hello JShell"; } } | Error: | hello() in C cannot implement hello() in I | attempting to assign weaker access privileges; was public | String hello(){ | ^--------------...
Korzystanie z domyślnej implementacji metody
Od wersji Java 8 metoda interfejsu może zapewnić domyślną implementację metody za pomocą słowa kluczowego default . Zadeklaruj interfejs, który zapewnia domyślną implementację metody hello() używając domyślnego słowo kluczowe.
[1]-> interface I { default String hello(){ return "Hello JShell"; } } | created interface I
Zadeklaruj klasę C który implementuje interfejs I .
[2]-> class C implements I{ } | created class C
Utwórz instancję klasy C i wywołaj metodę hello() . Metoda z domyślnej implementacji w interfejsie I pobiera dane wyjściowe.
[3]-> new C().hello(); | $1 ==> "Hello JShell"
Deklarowanie metody interfejsu jako statycznej
Od Javy 8 metody interfejsu mogą być deklarowane statyczne . Utwórz interfejs I który deklaruje statyczny metoda.
[1]-> interface I { static String hello(){ return "Hello JShell"; } } | created interface I
Wywołaj metodę statyczną za pomocą interfejsu I .
[2]-> I.hello() | $1 ==> "Hello JShell"
Klasa nie może być zadeklarowana jako ostateczna, a jeśli ostateczna używany jest modyfikator, jest ignorowany.
[5]-> [1]-> final class C{} | Warning: | Modifier 'final' not permitted in top-level declarations, | ignored | final class C{} | ^---^ | created class C
Korzystanie z tablic
W tej sekcji uruchomimy kilka fragmentów kodu dla tablic. Deklarowanie, tworzenie instancji i uzyskiwanie dostępu do tablic nie różni się od aplikacji opartych na plikach kodu źródłowego Java. Jako przykład zadeklaruj tablicę typu String[] . Tablica jest inicjowana na null .
[1]-> String[] strArray; | strArray ==> null
Przydziel pamięć do tablicy. Po ustawieniu rozmiaru tablicy nie można modyfikować. Elementy tablicy są inicjowane na null .
[2]-> strArray =new String[3]; | strArray ==> String[3] { null, null, null }
Zainicjuj elementy tablicy za pomocą indeksów tablicy.
[3]-> strArray[0]="A"; strArray[1]="B"; strArray[2]="C"; | $4 ==> "A" | $5 ==> "B" | $6 ==> "C"
Wypisz długość tablicy i element o indeksie 1.
[6]-> strArray.length; strArray[1]; | $9 ==> 3 | $10 ==> "B"
Długość tablicy jest wyprowadzana jako 3. Element o indeksie 1 to „B”. Tablica może zostać zainicjowana, jeśli zostanie zadeklarowana w następujący sposób.
[1]-> String[] strArray={"A","B","C"}; | strArray ==> String[3] { "A", "B", "C" }
Wypisz długość tablicy.
[2]-> strArray.length; | $1 ==> 3
Wypisz element o indeksie 0.
[3]-> strArray[0]; | $4 ==> "A" [4]->
Tablicę wielowymiarową można zadeklarować tak samo jak w aplikacji Java. Utwórz trójwymiarową tablicę typu String[][][] i zainicjuj tablicę.
[1]-> String[][][] strArray={{{"A","B","C"},{"AA","AB","AC"}}, {{"B","C","A"},{"BB","BC","BA"}},{{"C","A","B"}, {"CC","CA","CB"}}}; | strArray ==> String[3][][] { String[2][] { String[3] | { "A", "B", "C" }, String[3] { "AA", ...
Wypisz długość tablicy.
[2]-> strArray.length; | $1 ==> 3
Wypisz długość tablicy o indeksie 0.
[3]-> strArray[0].length; | $4 ==> 2
Wypisuje długość tablicy o indeksie 1 wewnątrz tablicy o indeksie 0.
[4]-> strArray[0][1].length; | $6 ==> 3
Wyprowadź tablicę z indeksem 0.
[5]-> strArray[0] | $10 ==> String[2][] { String[3] { "A", "B", "C" }, | String[3] { "AA", "AB", "AC" } }
Wypisz tablicę o indeksie 1 wewnątrz tablicy o indeksie 0.
strArray[0][1] | $11 ==> String[3] { "AA", "AB", "AC" }
Wypisz element o indeksie 0 w tablicy o indeksie 1 w tablicy o indeksie 0.
strArray[0][1][0] | $12 ==> "AA" [8]->
Korzystanie z niesprawdzonych wyjątków
JShell zgłasza niesprawdzone wyjątki w czasie wykonywania. Na przykład, jeśli zmienna typu String który został zainicjowany do wartości domyślnej null jest dostępny. java.lang.NullPointerException jest rzucany.
[1]-> String str; | str ==> null [2]-> str.length(); | java.lang.NullPointerException thrown: | at (#2:1) [3]->
Jako inny przykład, jeśli uzyskano dostęp do indeksu tablicy spoza rozmiaru tablicy, java.lang.ArrayIndexOutOfBoundsException jest rzucany.
[4]-> String[] str={"A","B","C"}; | str ==> String[3] { "A", "B", "C" } [5]-> str[3]; | java.lang.ArrayIndexOutOfBoundsException thrown: 3 | at (
Jeśli wywoływana jest metoda definiująca dzielenie przez zero, java.lang.ArithmeticException jest rzucany.
[1]-> int average(int i,int j){ return (i+j)/0; } | created method average(int,int) [2]-> average(2,4) | java.lang.ArithmeticException thrown: / by zero | at average (#1:2) | at (#2:1) [3]->
Wniosek
W pierwszych czterech artykułach omówiliśmy uruchamianie fragmentów kodu dla zmiennych, instrukcji, metod, klas, interfejsów i tablic. JShell jest przeznaczony do uruchamiania tylko fragmentów kodu i dlatego niektóre funkcje są inne niż podczas uruchamiania kompletnej aplikacji Java z pliku kodu źródłowego. W dwóch kolejnych artykułach omówimy kilka innych funkcji JShell.