JShell е нова функция в Java 9 за улесняване на изпълнението на кодови фрагменти. Кодовите фрагменти на JShell са точно същите като изходния код на Java във файл за приложение. Както беше обсъдено в по-ранна статия, „Използване на JShell в Java 9 в NetBeans 9.0, част 3“, JShell не позволява няколко модификатора – включително по подразбиране, достъп, синхронизиран, публичен, частен и защитен – които се поддържат във файл с изходен код . JShell е предназначен главно за тестване и отстраняване на грешки в Java код, а не за изпълнение на пълни приложения. В тази статия-продължение ще стартираме фрагменти за класове, интерфейси и масиви. Използвахме NetBeans 9, както в предишните статии. Ще обсъдим и непроверените изключения. Тази статия има следните раздели:
- Използване на класове
- Промяна на клас
- Изброяване на класове
- Използване на конструктори на класове
- Разширяване на клас
- Отмяна на метод
- Използване на интерфейси
- Използване на изпълнение по подразбиране за метод
- Обявяване на метод на интерфейса за статичен
- Използване на масиви
- Използване на непроверени изключения
- Заключение
Използване на класове
В този раздел ще обсъдим работещи кодови фрагменти за класове. Декларирайте прост клас C както следва.
[1]-> class C { } | created class C
Клас C се създава. За разлика от метод, който може да бъде извикан директно, класът първо трябва да бъде инстанциран, както следва.
[3]-> new C() | $1 ==> [email protected]
Нов екземпляр от клас C, $1 се създава. Както при декларациите на метод, декларациите на клас могат да се променят чрез повторно деклариране на класа. Един клас може да реализира интерфейс, използвайки приложения . Като пример, декларирайте интерфейс I .
[1]-> interface I{} | created interface I
Създайте клас C за внедряване на интерфейс I .
[3]-> class C implements I{} | replaced class C [4]->
Клас C , създаден по-рано, се заменя.
Декларацията на клас в JShell няма концепцията за приложение, както би имал Java клас, деклариран във файл. Java клас във файл с public static void main(String[] argv) методът е Java приложение. Общественият статичен void main(String[] argv) методът може да бъде добавен в JShell, но е просто друг кодов фрагмент. Създайте клас Здравей който включва метода 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]->
main(String[]) методът е статичен метод и се дефинира за класа, а не за екземпляр на клас. Създайте String[] масив за доставка на main(String[]) метод.
String[] strArray={"Hello"," JShell"};
Извикайте main(String[]) метод с String[] като аргумент.
Hello.main(strArray)
Получава се съобщение Hello JShell, както е показано на фигура 1.
Фигура 1: Извикване на статичен метод в клас
Промяна на клас
Един клас може да бъде модифициран според нуждите чрез модифициране или изтриване на която и да е от неговите декларации за метод или добавяне на нови методи. Повторно деклариране на клас Здравей без main(String[]) метод и класът се заменя.
[4]-> class Hello{ } | replaced class Hello [5]->
Добавете отново main(String[]) метод, но с малко по-различен System.out.println изявление. Клас Здравейте отново се заменя.
[5]-> class Hello{ public static void main(String[] argv) {System.out.println(argv[0]);} } | replaced class Hello [5]->
Извикайте статичния метод main(String[]) с Hello.main(strArray) за различен изход, както е показано на фигура 2.
Фигура 2: Извикване на вариация на метод main
Разпоредбата за замяна на клас е полезна при разработването на клас. Може да се добавя по един метод и да се тества клас. Като пример добавете втори метод hello(String) . Отново, клас Здравей се заменя.
[9]-> class Hello{ void main(String[] argv){System.out.println(argv[0]);} String hello(String name){return name;} } | replaced class Hello
Методът hello(String) add, тъй като е метод на екземпляр, ще се нуждае от екземпляр на клас за извикване. Създайте екземпляр на клас.
[10]-> new Hello() | $2 ==> [email protected]
Извикване на метод hello(String) използвайки екземпляр на клас $2 .
[11]-> $2.hello("John") | $6 ==> "John"
Изброяване на класове
Java класът е тип. Интерфейсът също е тип. Всички типове, дефинирани в сесията на JShell, са изброени с /types команда. Дефинирайте няколко класа и интерфейса.
[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
Стартирайте /types команда и всички класове и интерфейси се изброяват.
[6]-> /types | class C | class D | class B | interface I | interface J
Използване на конструктори на клас
Класът без аргумент се дефинира имплицитно в клас, ако не дефинира никакви конструктори с аргументи. Преди това бяхме инстанцирали клас C които не са декларирали никакви конструктори изрично с нов C() . Конструкторът без аргумент може да бъде дефиниран изрично.
След това създайте клас Здравей който декларира конструктор на клас. Конструкторът има един параметър от тип String . Конструкторът може да бъде деклариран с public модификатор и е имплицитно публичен ако не е зададено на public .
[6]-> class Hello{ String name; public Hello(String name){this.name=name;} void hello(){System.out.println("Hello "+name);} }
Създайте екземпляр на клас Здравей .
Hello hello=new Hello("John")
Извикайте метода на екземпляра hello() за да изведете съобщение, както е показано на фигура 3.
Фигура 3: Използване на клас с конструктор
Разширяване на клас
Класът може да бъде разширен с разширения точно както във файл с изходен код на Java. Като пример създайте клас D който декларира име на променлива от тип tt>String, конструктор без аргумент и метод hello(String) . hello(String) метод извежда "Здравей" съобщение, използващо име arg е предоставен.
class D{ String name="Michael"; public D(){} void hello(String name){System.out.println("Hello "+name);} }
Създайте клас C който разширява клас C и декларира hello() метод, който не отменя клас D s здравей(низ) методът и параметрите са различни. здравей() методът извиква име на поле, което е наследено от клас D .
class C extends D{ void hello(){System.out.println("Hello "+name);} }
Създаване на клас C и извикайте hello() метод.
new C().hello()
Извежда се съобщение „Здравей“, както е показано на Фигура 4. име стойност на полето, зададена в клас D се използва.
Фигура 4: Разширяване на клас
Ако извикахме hello(String) метод, който клас C наследява от клас D , ще получим различен изход, както е показано на фигура 5.
Фигура 5: Извикване на наследен метод от разширен клас
Отмяна на метод
Един клас може да отмени метод, наследен от разширен клас, като предостави своя собствена дефиниция на метод. Създайте клас D което декларира поле name и метод hello() .
class D{ String name="Michael"; void hello(){System.out.println("Hello "+name);} }
Декларирайте клас C което разширява клас D и отменя hello() метод. Клас C също така скрива полето name .
class C extends D{ String name="John"; void hello(){System.out.println("Hello "+name); }
Създайте екземпляр от клас C и извикайте метод hello() .
new C().hello()
здравей() метод от клас C се извиква, защото отменя метода от клас D . Полето име в клас C скрива полето name в клас D . Изходът на съобщението е показан на фигура 6.
Фигура 6: Отмяна на метод
Ако клас C не скрива полето name от клас D , име поле в клас D се използва, както е показано на фигура 7.
Фигура 7: Достъп до поле от разширен клас
А клас C обектът е екземпляр на клас D защото разширява клас D . Изпълнете следния оператор, за да откриете дали екземпляр от клас C също е екземпляр на клас D .
new C() instanceof D
Стойност true проверява екземпляр от клас C също е екземпляр на клас D , както е показано на фигура 8.
Фигура 8: Проверка дали екземпляр от клас C също е екземпляр от клас D
Тъй като екземпляр от клас C също е екземпляр на клас D , може да се прехвърли към D както следва:
D d=(D)(new C());
Впоследствие полето за достъп име за обект d от тип D .
d.name;
И извикайте метод hello() за обект d от тип D .
d.hello();
Изходната стойност на полето е от клас D защото d е обект от тип D , както е показано на Фигура 9. Методът hello() извиканият е от клас C .
Фигура 9: Прехвърляне на обект от тип C към D
Използване на интерфейси
В този раздел ще изпълним някои фрагменти за интерфейси в JShell. Съществуващ клас може да бъде модифициран, за да имплементира интерфейс. Създайте клас C .
[1]-> class C{} | created class C
Създайте интерфейс I който дефинира метод hello() .
[2]-> interface I { String hello(); } | created interface I
Повторно деклариране на клас C за внедряване на интерфейс I . Клас C осигурява реализация на метода hello() .
[3]-> class C implements I{ public String hello(){ return "Hello JShell"; } } | replaced class C
Създайте екземпляр от клас C .
[4]-> new C() | $1 ==> [email protected]
Използвайки променливата на екземпляра на класа, извикайте метода hello() и изходът на метода се показва.
[5]-> $1.hello() | $2 ==> "Hello JShell" [6]->
Тъй като методите в интерфейса са имплицитно публични докато методите в клас не са метод, реализацията в клас C трябва да бъде деклариран пред публично модификатор на достъп. Ако не е обявен за публичен , се извежда съобщение за грешка, тъй като не се посочва public модификаторът за достъп има по подразбиране по-слаб модификатор на достъп, което не е разрешено при внедряване на интерфейс.
[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(){ | ^--------------...
Използване на изпълнение по подразбиране за метод
От Java 8 интерфейсният метод може да осигури реализация по подразбиране за метод, като използва ключова дума default . Декларирайте интерфейс, който предоставя реализация по подразбиране за метод hello() като използвате по подразбиране ключова дума.
[1]-> interface I { default String hello(){ return "Hello JShell"; } } | created interface I
Декларирайте клас C който имплементира интерфейс I .
[2]-> class C implements I{ } | created class C
Създайте екземпляр от клас C и извикайте метод hello() . Методът от реализацията по подразбиране в интерфейс I получава изход.
[3]-> new C().hello(); | $1 ==> "Hello JShell"
Обявяване на интерфейсен метод за статичен
От Java 8, интерфейсните методи могат да бъдат декларирани статични . Създайте интерфейс I който декларира статичен метод.
[1]-> interface I { static String hello(){ return "Hello JShell"; } } | created interface I
Извикайте статичния метод, като използвате интерфейс I .
[2]-> I.hello() | $1 ==> "Hello JShell"
Един клас не може да бъде обявен за окончателен и, ако final се използва модификатор, той се игнорира.
[5]-> [1]-> final class C{} | Warning: | Modifier 'final' not permitted in top-level declarations, | ignored | final class C{} | ^---^ | created class C
Използване на масиви
В този раздел ще изпълним някои кодови фрагменти за масиви. Декларирането, инстанцирането и достъпът до масиви не се различава от това в приложение, базирано на файл с изходен код на Java. Като пример, декларирайте масив от тип String[] . Масивът се инициализира на null .
[1]-> String[] strArray; | strArray ==> null
Разпределете памет към масива. Размерът на масива, веднъж зададен, не може да бъде променен. Елементите на масива се инициализират на null .
[2]-> strArray =new String[3]; | strArray ==> String[3] { null, null, null }
Инициализирайте елементите на масива с помощта на индексите на масива.
[3]-> strArray[0]="A"; strArray[1]="B"; strArray[2]="C"; | $4 ==> "A" | $5 ==> "B" | $6 ==> "C"
Изведете дължината на масива и елемента с индекс 1.
[6]-> strArray.length; strArray[1]; | $9 ==> 3 | $10 ==> "B"
Дължината на масива се извежда като 3. Елементът с индекс 1 е “B”. Масив може да бъде инициализиран, когато е деклариран, както следва.
[1]-> String[] strArray={"A","B","C"}; | strArray ==> String[3] { "A", "B", "C" }
Изведете дължината на масива.
[2]-> strArray.length; | $1 ==> 3
Изведете елемента с индекс 0.
[3]-> strArray[0]; | $4 ==> "A" [4]->
Многоизмерен масив може да бъде деклариран точно както в Java приложение. Създайте триизмерен масив от тип String[][][] и инициализирайте масива.
[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", ...
Изведете дължината на масива.
[2]-> strArray.length; | $1 ==> 3
Извежда дължината на масива с индекс 0.
[3]-> strArray[0].length; | $4 ==> 2
Извежда дължината на масива с индекс 1 в рамките на масива с индекс 0.
[4]-> strArray[0][1].length; | $6 ==> 3
Изведете масива с индекс 0.
[5]-> strArray[0] | $10 ==> String[2][] { String[3] { "A", "B", "C" }, | String[3] { "AA", "AB", "AC" } }
Изведете масива с индекс 1 в рамките на масива с индекс 0.
strArray[0][1] | $11 ==> String[3] { "AA", "AB", "AC" }
Изведете елемента с индекс 0 в масив с индекс 1 в масив с индекс 0.
strArray[0][1][0] | $12 ==> "AA" [8]->
Използване на непроверени изключения
JShell хвърля непроверени изключения по време на изпълнение. Като пример, ако променлива от тип String която е инициализирана до стойността по подразбиране null е достъпен. java.lang.NullPointerException се хвърля.
[1]-> String str; | str ==> null [2]-> str.length(); | java.lang.NullPointerException thrown: | at (#2:1) [3]->
Като друг пример, ако се осъществи достъп до индекс на масив извън размера на масива, java.lang.ArrayIndexOutOfBoundsException се хвърля.
[4]-> String[] str={"A","B","C"}; | str ==> String[3] { "A", "B", "C" } [5]-> str[3]; | java.lang.ArrayIndexOutOfBoundsException thrown: 3 | at (
Ако се извика метод, който дефинира деление на нула, java.lang.ArithmeticException се хвърля.
[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]->
Заключение
В тези първи четири статии обсъдихме изпълнение на кодови фрагменти за променливи, изрази, методи, класове, интерфейси и масиви. JShell е проектиран да изпълнява само кодови фрагменти и като такива някои от функциите са различни, отколкото при стартиране на пълно Java приложение от файл с изходен код. В още две статии ще разгледаме някои други характеристики на JShell.