JShell is een nieuwe functie in Java 9 om het uitvoeren van codefragmenten te vergemakkelijken. JShell-codefragmenten zijn precies hetzelfde als Java-broncode in een bestand voor een toepassing. Zoals besproken in een eerder artikel, "JShell gebruiken in Java 9 in NetBeans 9.0, deel 3", staat JShell verschillende modifiers niet toe, waaronder standaard, toegang, gesynchroniseerd, openbaar, privé en beveiligd, die worden ondersteund in een broncodebestand . JShell is voornamelijk ontworpen voor het testen en debuggen van Java-code en niet voor het uitvoeren van complete applicaties. In dit vervolgartikel zullen we fragmenten uitvoeren voor klassen, interfaces en arrays. We hebben NetBeans 9 gebruikt zoals in de eerdere artikelen. We zullen ook ongecontroleerde uitzonderingen bespreken. Dit artikel heeft de volgende secties:
- Klassen gebruiken
- Een klas wijzigen
- Lessen aanbieden
- Klassenconstructors gebruiken
- Een les verlengen
- Een methode overschrijven
- Interfaces gebruiken
- Een standaardimplementatie gebruiken voor een methode
- Een interfacemethode als statisch verklaren
- Arrays gebruiken
- Niet-aangevinkte uitzonderingen gebruiken
- Conclusie
Klassen gebruiken
In deze sectie bespreken we het uitvoeren van codefragmenten voor klassen. Declareer een eenvoudige klasse C als volgt.
[1]-> class C { } | created class C
Klasse C wordt gecreëerd. In tegenstelling tot een methode die direct kan worden aangeroepen, moet een klasse eerst als volgt worden geïnstantieerd.
[3]-> new C() | $1 ==> [email protected]
Een nieuwe instantie van klasse C, $1 wordt gecreëerd. Net als bij methodedeclaraties, kunnen klassedeclaraties worden gewijzigd door de klasse opnieuw te declareren. Een klasse kan een interface implementeren met behulp van implements . Declareer bijvoorbeeld een interface I .
[1]-> interface I{} | created interface I
Maak klasse C om interface I te implementeren .
[3]-> class C implements I{} | replaced class C [4]->
Klasse C , eerder gemaakt, wordt vervangen.
Een klassedeclaratie in JShell heeft niet het concept van een toepassing zoals een Java-klasse die in een bestand is gedeclareerd zou hebben. Een Java-klasse in een bestand met de public static void main(String[] argv) methode is een Java-toepassing. De public static void main(String[] argv) methode kan worden toegevoegd in JShell, maar is gewoon een ander codefragment. Maak een klas Hallo die de methode bevat 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]->
De main(String[]) methode is een statisch methode en is gedefinieerd voor de klasse in plaats van een instantie van een klasse. Maak een String[] array om te leveren aan de main(String[]) methode.
String[] strArray={"Hello"," JShell"};
Roep de main(String[]) . op methode met de String[] als een argument.
Hello.main(strArray)
Een Hello JShell-bericht wordt uitgevoerd, zoals weergegeven in afbeelding 1.
Figuur 1: Statische methode aanroepen in een klasse
Een klas wijzigen
Een klasse kan naar behoefte worden gewijzigd door een van zijn methodedeclaraties te wijzigen of te verwijderen of door nieuwe methoden toe te voegen. Klas opnieuw declareren Hallo zonder de main(String[]) methode en de klasse wordt vervangen.
[4]-> class Hello{ } | replaced class Hello [5]->
Voeg de main(String[]) opnieuw toe methode maar met een iets andere System.out.println uitspraak. Klas Hallo opnieuw wordt vervangen.
[5]-> class Hello{ public static void main(String[] argv) {System.out.println(argv[0]);} } | replaced class Hello [5]->
Roep de statische . op methode main(String[]) met Hallo.main(strArray) voor een andere uitgang, zoals weergegeven in afbeelding 2.
Figuur 2: Een variatie op de methode main aanroepen
De bepaling om een klasse te vervangen is handig bij het ontwikkelen van een klasse. Er kan één methode tegelijk worden toegevoegd en de klasse wordt getest. Voeg als voorbeeld een tweede methode toe hello(String) . Nogmaals, klas Hallo wordt vervangen.
[9]-> class Hello{ void main(String[] argv){System.out.println(argv[0]);} String hello(String name){return name;} } | replaced class Hello
De methode hallo(String) toegevoegd, omdat het een instantiemethode is, zou een klasse-instantie nodig zijn om aan te roepen. Maak een klasse-instantie.
[10]-> new Hello() | $2 ==> [email protected]
Methode aanroepen hallo(String) klasse-instantie $2 . gebruiken .
[11]-> $2.hello("John") | $6 ==> "John"
Lessen weergeven
Een Java-klasse is een type. Een interface is ook een type. Alle typen die in de JShell-sessie zijn gedefinieerd, worden weergegeven met de /types opdracht. Definieer een paar klassen en interfaces.
[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
Voer de /types . uit commando en alle klassen en interfaces worden weergegeven.
[6]-> /types | class C | class D | class B | interface I | interface J
Klassenconstructors gebruiken
De klasse no-arg is impliciet gedefinieerd in een klasse als deze geen constructors met args definieert. We hadden eerder een klasse C . gemaakt die geen constructeurs expliciet heeft aangegeven met new C() . De no-arg constructor kan expliciet worden gedefinieerd.
Maak vervolgens een klas Hallo die een klassenconstructor declareert. De constructor heeft één parameter van het type String . De constructor kan worden gedeclareerd met de public modifier en is impliciet openbaar indien niet ingesteld op openbaar .
[6]-> class Hello{ String name; public Hello(String name){this.name=name;} void hello(){System.out.println("Hello "+name);} }
Maak een instantie van klasse Hallo .
Hello hello=new Hello("John")
Roep de instantiemethode hello() op om een bericht uit te voeren, zoals weergegeven in Afbeelding 3.
Figuur 3: Een klasse gebruiken met een constructor
Een klas verlengen
Een klasse kan worden uitgebreid met extends, net als in een Java-broncodebestand. Maak bijvoorbeeld klasse D die een variabelenaam van het type tt>String declareert, een no-arg-constructor en een methode hello(String) . De hallo(String) methode geeft een "Hallo" bericht met de naam arg geleverd.
class D{ String name="Michael"; public D(){} void hello(String name){System.out.println("Hello "+name);} }
Maak een klas C dat breidt klasse C uit en verklaart de hallo() methode, die klasse D . niet opheft ‘s hallo(String) methode en parameters zijn verschillend. De hallo() methode roept een veldnaam op, die is overgenomen van klasse D .
class C extends D{ void hello(){System.out.println("Hello "+name);} }uit
Instantie van klasse C en roep de hallo() . op methode.
new C().hello()
Er wordt een "Hallo"-bericht weergegeven, zoals weergegeven in Afbeelding 4. De naam veldwaarde ingesteld in klasse D wordt gebruikt.
Figuur 4: Een klas verlengen
Als we de hallo(String) . aanroepen methode die klasse C erft van klasse D , zouden we een andere uitvoer krijgen, zoals weergegeven in figuur 5.
Figuur 5: Een overgenomen methode van een uitgebreide klasse aanroepen
Een methode overschrijven
Een klasse kan een methode overschrijven die is geërfd van een uitgebreide klasse door zijn eigen methodedefinitie op te geven. Maak een klas D die een veld naam . declareert en een methode hallo() .
class D{ String name="Michael"; void hello(){System.out.println("Hello "+name);} }
Declareer een klasse C dat breidt klasse D uit en heft de hallo() . op methode. Klasse C verbergt ook het veld naam .
class C extends D{ String name="John"; void hello(){System.out.println("Hello "+name); }
Maak een instantie van klasse C en roep de methode hallo() op .
new C().hello()
De hallo() methode uit klasse C wordt aangeroepen omdat het de methode van klasse D . overschrijft . Het veld naam in de klas C verbergt het veld naam in de klas D . De berichtuitvoer wordt weergegeven in Afbeelding 6.
Figuur 6: Een methode overschrijven
Als klasse C verbergt niet veld naam uit klas D , de naam veld in klasse D wordt gebruikt, zoals weergegeven in Afbeelding 7.
Figuur 7: Veld openen vanuit uitgebreide klas
Een klasse C object is een instantie van klasse D omdat het klasse D . uitbreidt . Voer de volgende instructie uit om te zien of een instantie van klasse C is ook een instantie van klasse D .
new C() instanceof D
Een waarde van true verifieert een instantie van klasse C is ook een instantie van klasse D , zoals weergegeven in afbeelding 8.
Figuur 8: Controleren of een instantie van klasse C ook een instantie van klasse D is
Omdat een instantie van klasse C is ook een instantie van klasse D , het kan worden gecast naar D als volgt:
D d=(D)(new C());
Ga vervolgens naar veld naam voor object d van het type D .
d.name;
En roep de methode hallo() op voor object d van het type D .
d.hello();
De uitvoer van de veldwaarde is van klasse D omdat d is een object van het type D , zoals weergegeven in figuur 9. De methode hello() aangeroepen is van klasse C .
Figuur 9: Een object van type C naar D casten
Interfaces gebruiken
In deze sectie zullen we enkele fragmenten uitvoeren voor interfaces in JShell. Een bestaande klasse kan worden aangepast om een interface te implementeren. Maak klasse C .
[1]-> class C{} | created class C
Maak een interface I die een methode definieert hallo() .
[2]-> interface I { String hello(); } | created interface I
Klasse C opnieuw declareren om interface I te implementeren . Klasse C biedt implementatie voor methode hallo() .
[3]-> class C implements I{ public String hello(){ return "Hello JShell"; } } | replaced class C
Maak een instantie van klasse C .
[4]-> new C() | $1 ==> [email protected]
Roep de methode hello() . op met behulp van de instantievariabele klasse en de uitvoer van de methode wordt weergegeven.
[5]-> $1.hello() | $2 ==> "Hello JShell" [6]->
Omdat methoden in een interface impliciet openbaar zijn terwijl methoden in een klasse geen methode zijn, implementatie in klasse C moet worden aangegeven met de public toegangsmodificatie. Indien niet openbaar verklaard , wordt er een foutmelding weergegeven omdat er geen public is opgegeven access modifier is standaard een zwakkere access modifier, wat niet is toegestaan bij het implementeren van een interface.
[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(){ | ^--------------...
Een standaardimplementatie gebruiken voor een methode
Vanaf Java 8 kan een interfacemethode een standaardimplementatie voor een methode bieden door het trefwoord default te gebruiken . Declareer een interface die een standaardimplementatie biedt voor de methode hello() met de standaard zoekwoord.
[1]-> interface I { default String hello(){ return "Hello JShell"; } } | created interface I
Declareer een klasse C die interface I . implementeert .
[2]-> class C implements I{ } | created class C
Maak een instantie van klasse C en roep de methode hallo() op . De methode van de standaardimplementatie in interface I krijgt uitvoer.
[3]-> new C().hello(); | $1 ==> "Hello JShell"
Een interfacemethode als statisch verklaren
Sinds Java 8 kunnen interfacemethoden statisch worden verklaard . Maak een interface I dat verklaart een statische methode.
[1]-> interface I { static String hello(){ return "Hello JShell"; } } | created interface I
Roep de statische methode op met behulp van interface I .
[2]-> I.hello() | $1 ==> "Hello JShell"
Een klasse kan niet definitief worden verklaard en, als de finale modifier wordt gebruikt, wordt deze genegeerd.
[5]-> [1]-> final class C{} | Warning: | Modifier 'final' not permitted in top-level declarations, | ignored | final class C{} | ^---^ | created class C
Arrays gebruiken
In deze sectie zullen we enkele codefragmenten voor arrays uitvoeren. Het declareren, instantiëren en openen van arrays is niet anders dan in een op Java-broncode gebaseerde applicatie. Declareer bijvoorbeeld een array van het type String[] . Array is geïnitialiseerd op null .
[1]-> String[] strArray; | strArray ==> null
Wijs geheugen toe aan de array. De arraygrootte kan, eenmaal ingesteld, niet worden gewijzigd. Array-elementen worden geïnitialiseerd op null .
[2]-> strArray =new String[3]; | strArray ==> String[3] { null, null, null }
Initialiseer de array-elementen met behulp van de array-indexen.
[3]-> strArray[0]="A"; strArray[1]="B"; strArray[2]="C"; | $4 ==> "A" | $5 ==> "B" | $6 ==> "C"
Voer de arraylengte en het element uit op index 1.
[6]-> strArray.length; strArray[1]; | $9 ==> 3 | $10 ==> "B"
De arraylengte wordt uitgevoerd als 3. Element bij index 1 is "B". Een array kan worden geïnitialiseerd als het als volgt wordt gedeclareerd.
[1]-> String[] strArray={"A","B","C"}; | strArray ==> String[3] { "A", "B", "C" }
Voer de arraylengte uit.
[2]-> strArray.length; | $1 ==> 3
Voer het element uit op index 0.
[3]-> strArray[0]; | $4 ==> "A" [4]->
Een multidimensionale array kan net als in een Java-toepassing worden gedeclareerd. Maak een driedimensionale array van het type String[][][] en initialiseer de array.
[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", ...
Voer de arraylengte uit.
[2]-> strArray.length; | $1 ==> 3
Voer de lengte van de array uit op index 0.
[3]-> strArray[0].length; | $4 ==> 2
Voer de lengte van de array uit op index 1 binnen array op index 0.
[4]-> strArray[0][1].length; | $6 ==> 3
Voer de array uit op index 0.
[5]-> strArray[0] | $10 ==> String[2][] { String[3] { "A", "B", "C" }, | String[3] { "AA", "AB", "AC" } }
Voer de array uit op index 1 binnen array op index 0.
strArray[0][1] | $11 ==> String[3] { "AA", "AB", "AC" }
Voer het element uit op index 0 in array op index 1 binnen array op index 0.
strArray[0][1][0] | $12 ==> "AA" [8]->
Niet-aangevinkte uitzonderingen gebruiken
JShell gooit ongecontroleerde uitzonderingen tijdens runtime. Als bijvoorbeeld een variabele van het type String die is geïnitialiseerd naar de standaardwaarde null wordt benaderd. java.lang.NullPointerException wordt gegooid.
[1]-> String str; | str ==> null [2]-> str.length(); | java.lang.NullPointerException thrown: | at (#2:1) [3]->
Als een ander voorbeeld, als een array-index buiten de grootte van een array wordt geopend, java.lang.ArrayIndexOutOfBoundsException wordt gegooid.
[4]-> String[] str={"A","B","C"}; | str ==> String[3] { "A", "B", "C" } [5]-> str[3]; | java.lang.ArrayIndexOutOfBoundsException thrown: 3 | at (.)
Als een methode wordt aangeroepen die deling door nul definieert, java.lang.ArithmeticException wordt gegooid.
[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]->
Conclusie
In deze eerste vier artikelen bespraken we het uitvoeren van codefragmenten voor variabelen, instructies, methoden, klassen, interfaces en arrays. JShell is ontworpen om alleen codefragmenten uit te voeren en als zodanig zijn sommige functies anders dan bij het uitvoeren van een volledige Java-toepassing vanuit een broncodebestand. In nog twee artikelen zullen we enkele andere functies van JShell onderzoeken.