JShell è una nuova funzionalità di Java 9 per facilitare l'esecuzione di frammenti di codice. I frammenti di codice JShell sono esattamente gli stessi del codice sorgente Java in un file per un'applicazione. Come discusso in un articolo precedente, "Utilizzo di JShell in Java 9 in NetBeans 9.0, parte 3", JShell non consente diversi modificatori, inclusi predefinito, accesso, sincronizzato, pubblico, privato e protetto, che sono supportati in un file di codice sorgente . JShell è progettato principalmente per il test e il debug del codice Java e non per l'esecuzione di applicazioni complete. In questo articolo di continuazione, eseguiremo snippet per classi, interfacce e array. Abbiamo usato NetBeans 9 come negli articoli precedenti. Discuteremo anche le eccezioni non controllate. Questo articolo ha le seguenti sezioni:
- Utilizzo delle classi
- Modifica di una classe
- Corsi di quotazione
- Utilizzo dei Costruttori di classi
- Estensione di una classe
- Sostituzione di un metodo
- Utilizzo delle interfacce
- Utilizzo di un'implementazione predefinita per un metodo
- Dichiarazione di un metodo di interfaccia statico
- Utilizzo degli array
- Utilizzo delle eccezioni non selezionate
- Conclusione
Utilizzo delle classi
In questa sezione, discuteremo dell'esecuzione di frammenti di codice per le classi. Dichiara una classe semplice C come segue.
[1]-> class C { } | created class C
Classe C viene creato. A differenza di un metodo che può essere invocato direttamente, una classe deve prima essere istanziata come segue.
[3]-> new C() | $1 ==> [email protected]
Una nuova istanza della classe C, $1 viene creato. Come per le dichiarazioni di metodo, le dichiarazioni di classe sono modificabili ri-dichiarando la classe. Una classe può implementare un'interfaccia usando implement . Ad esempio, dichiara un'interfaccia I .
[1]-> interface I{} | created interface I
Crea classe C per implementare l'interfaccia I .
[3]-> class C implements I{} | replaced class C [4]->
Classe C , creato in precedenza, viene sostituito.
Una dichiarazione di classe in JShell non ha il concetto di applicazione come avrebbe una classe Java dichiarata in un file. Una classe Java in un file con public static void main(String[] argv) metodo è un'applicazione Java. Il main void statico pubblico(String[] argv) il metodo può essere aggiunto in JShell ma è solo un altro frammento di codice. Crea una classe Ciao che include il metodo 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]->
Il principale(Stringa[]) il metodo è un statico metodo ed è definito per la classe anziché per un'istanza di una classe. Crea una Stringa[] array da fornire a main(String[]) metodo.
String[] strArray={"Hello"," JShell"};
Richiama il main(String[]) metodo con la Stringa[] come argomento.
Hello.main(strArray)
Viene visualizzato un messaggio Hello JShell, come mostrato nella Figura 1.
Figura 1: Invocare il metodo statico in una classe
Modifica di una classe
Una classe può essere modificata secondo necessità modificando o eliminando una qualsiasi delle sue dichiarazioni di metodo o aggiungendo nuovi metodi. Ri-dichiara la classe Ciao senza main(String[]) metodo e la classe viene sostituita.
[4]-> class Hello{ } | replaced class Hello [5]->
Aggiungi nuovamente il main(String[]) metodo ma con un System.out.println leggermente diverso dichiarazione. Classe Ciao viene nuovamente sostituito.
[5]-> class Hello{ public static void main(String[] argv) {System.out.println(argv[0]);} } | replaced class Hello [5]->
Richiama il statico metodo main(String[]) con Hello.main(strArray) per un output diverso, come mostrato nella Figura 2.
Figura 2: Invocare una variazione del metodo main
La disposizione per sostituire una classe è utile quando si sviluppa una classe. È possibile aggiungere un metodo alla volta e testare la classe. Ad esempio, aggiungi un secondo metodo hello(String) . Di nuovo, classe Ciao viene sostituito.
[9]-> class Hello{ void main(String[] argv){System.out.println(argv[0]);} String hello(String name){return name;} } | replaced class Hello
Il metodo ciao(Stringa) aggiunto, essendo un metodo di istanza, avrebbe bisogno di un'istanza di classe da invocare. Crea un'istanza di classe.
[10]-> new Hello() | $2 ==> [email protected]
Richiama il metodo hello(String) utilizzando l'istanza di classe $2 .
[11]-> $2.hello("John") | $6 ==> "John"
Classi di quotazione
Una classe Java è un tipo. Anche un'interfaccia è un tipo. Tutti i tipi definiti nella sessione di JShell sono elencati con /types comando. Definisci alcune classi e interfacce.
[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
Esegui /types comando e tutte le classi e le interfacce vengono elencate.
[6]-> /types | class C | class D | class B | interface I | interface J
Utilizzo dei Costruttori di classi
La classe no-arg è definita implicitamente in una classe se non definisce alcun costruttore con args. In precedenza avevamo istanziato una classe C che non ha dichiarato alcun costruttore esplicitamente con new C() . Il costruttore no-arg può essere definito in modo esplicito.
Quindi, crea una classe Ciao che dichiara un costruttore di classe. Il costruttore ha un parametro di tipo String . Il costruttore può essere dichiarato con public modificatore ed è implicitamente pubblico se non è impostato su pubblico .
[6]-> class Hello{ String name; public Hello(String name){this.name=name;} void hello(){System.out.println("Hello "+name);} }
Crea un'istanza della classe Hello .
Hello hello=new Hello("John")
Richiama il metodo di istanza hello() per emettere un messaggio, come mostrato nella Figura 3.
Figura 3: Utilizzo di una classe con un costruttore
Estensione di una classe
Una classe può essere estesa con extends proprio come in un file di codice sorgente Java. Ad esempio, crea la classe D che dichiara un nome di variabile di tipo tt>String, un costruttore no-arg e un metodo hello(String) . Il ciao(Stringa) il metodo restituisce un "Ciao" messaggio utilizzando il nome arg fornito.
class D{ String name="Michael"; public D(){} void hello(String name){System.out.println("Hello "+name);} }
Crea una classe C che estende la classe C e dichiara ciao() metodo, che non sovrascrive la classe D 's ciao(Stringa) metodo e parametri sono diversi. Il ciao() il metodo richiama un nome di campo, che viene ereditato dalla classe D .
class C extends D{ void hello(){System.out.println("Hello "+name);} }
Istanziare la classe C e invocare ciao() metodo.
new C().hello()
Viene visualizzato un messaggio "Hello", come mostrato nella Figura 4. Il nome valore del campo impostato nella classe D viene utilizzato.
Figura 4: Estendere una classe
Se abbiamo invocato hello(String) metodo che classe C eredita dalla classe D , otterremmo un output diverso, come mostrato nella Figura 5.
Figura 5: Invocare un metodo ereditato da una classe estesa
Sostituzione di un metodo
Una classe può sovrascrivere un metodo ereditato da una classe estesa fornendo la propria definizione di metodo. Crea una classe D che dichiara un campo nome e un metodo ciao() .
class D{ String name="Michael"; void hello(){System.out.println("Hello "+name);} }
Dichiara una classe C che estende la classe D e sovrascrive ciao() metodo. Classe C nasconde anche il campo nome .
class C extends D{ String name="John"; void hello(){System.out.println("Hello "+name); }
Crea un'istanza della classe C e invoca il metodo ciao() .
new C().hello()
Il ciao() metodo dalla classe C viene invocato perché sovrascrive il metodo dalla classe D . Il campo nome in classe C nasconde il campo nome nella classe D . L'output del messaggio è mostrato nella Figura 6.
Figura 6: Sovrascrivere un metodo
Se la classe C non nasconde il campo nome dalla classe D , il nome campo nella classe D viene utilizzato, come mostrato nella Figura 7.
Figura 7: Accesso al campo dalla classe estesa
Una classe C oggetto è un'istanza della classe D perché estende la classe D . Esegui la seguente istruzione per trovare un'istanza della classe C è anche un'istanza della classe D .
new C() instanceof D
Un valore di vero verifica un'istanza della classe C è anche un'istanza della classe D , come mostrato nella Figura 8.
Figura 8: Verifica se un'istanza di Classe C è anche un'istanza di classe D
Perché un'istanza della classe C è anche un'istanza della classe D , può essere lanciato su D come segue:
D d=(D)(new C());
Successivamente, accedi al campo nome per l'oggetto d di tipo D .
d.name;
E, invoca il metodo ciao() per l'oggetto d di tipo D .
d.hello();
L'output del valore del campo proviene dalla classe D perché d è un oggetto di tipo D , come mostrato nella Figura 9. Il metodo hello() invocato proviene dalla classe C .
Figura 9: Lanciare un Oggetto di tipo C in D
Utilizzo delle interfacce
In questa sezione, eseguiremo alcuni snippet per le interfacce in JShell. Una classe esistente può essere modificata per implementare un'interfaccia. Crea classe C .
[1]-> class C{} | created class C
Crea un'interfaccia Io che definisce un metodo ciao() .
[2]-> interface I { String hello(); } | created interface I
Ri-dichiarare la classe C per implementare l'interfaccia I . Classe C fornisce l'implementazione per il metodo ciao() .
[3]-> class C implements I{ public String hello(){ return "Hello JShell"; } } | replaced class C
Crea un'istanza della classe C .
[4]-> new C() | $1 ==> [email protected]
Usando la variabile di istanza della classe, invoca il metodo ciao() e l'output del metodo viene visualizzato.
[5]-> $1.hello() | $2 ==> "Hello JShell" [6]->
Perché i metodi in un'interfaccia sono implicitamente pubblici mentre i metodi in una classe non sono un metodo, l'implementazione nella classe C deve essere dichiarato al pubblico modificatore di accesso. Se non dichiarato pubblico , viene emesso un messaggio di errore perché non si specifica un pubblico modificatore di accesso predefinito su un modificatore di accesso più debole, che non è consentito quando si implementa un'interfaccia.
[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(){ | ^--------------...
Utilizzo di un'implementazione predefinita per un metodo
A partire da Java 8, un metodo di interfaccia può fornire un'implementazione predefinita per un metodo utilizzando la parola chiave default . Dichiara un'interfaccia che fornisce un'implementazione predefinita per il metodo hello() utilizzando il predefinito parola chiave.
[1]-> interface I { default String hello(){ return "Hello JShell"; } } | created interface I
Dichiara una classe C che implementa l'interfaccia I .
[2]-> class C implements I{ } | created class C
Crea un'istanza della classe C e invoca il metodo ciao() . Il metodo dall'implementazione predefinita nell'interfaccia I ottiene l'output.
[3]-> new C().hello(); | $1 ==> "Hello JShell"
Dichiarazione di un metodo di interfaccia statico
Da Java 8, i metodi Interface possono essere dichiarati static . Crea un'interfaccia Io che dichiara un statico metodo.
[1]-> interface I { static String hello(){ return "Hello JShell"; } } | created interface I
Richiama il metodo statico usando l'interfaccia I .
[2]-> I.hello() | $1 ==> "Hello JShell"
Una classe non può essere dichiarata finale e, se finale modificatore viene utilizzato, viene ignorato.
[5]-> [1]-> final class C{} | Warning: | Modifier 'final' not permitted in top-level declarations, | ignored | final class C{} | ^---^ | created class C
Utilizzo degli array
In questa sezione, eseguiremo alcuni frammenti di codice per gli array. Dichiarare, creare un'istanza e accedere agli array non è diverso da un'applicazione basata su file di codice sorgente Java. Ad esempio, dichiara un array di tipo String[] . L'array è inizializzato su null .
[1]-> String[] strArray; | strArray ==> null
Allocare memoria all'array. La dimensione dell'array, una volta impostata, non può essere modificata. Gli elementi dell'array vengono inizializzati su null .
[2]-> strArray =new String[3]; | strArray ==> String[3] { null, null, null }
Inizializza gli elementi dell'array utilizzando gli indici dell'array.
[3]-> strArray[0]="A"; strArray[1]="B"; strArray[2]="C"; | $4 ==> "A" | $5 ==> "B" | $6 ==> "C"
Emetti la lunghezza dell'array e l'elemento all'indice 1.
[6]-> strArray.length; strArray[1]; | $9 ==> 3 | $10 ==> "B"
La lunghezza dell'array viene emessa come 3. L'elemento all'indice 1 è "B". Un array può essere inizializzato quando dichiarato come segue.
[1]-> String[] strArray={"A","B","C"}; | strArray ==> String[3] { "A", "B", "C" }
Emetti la lunghezza dell'array.
[2]-> strArray.length; | $1 ==> 3
Emetti l'elemento all'indice 0.
[3]-> strArray[0]; | $4 ==> "A" [4]->
Un array multidimensionale può essere dichiarato proprio come in un'applicazione Java. Crea un array tridimensionale di tipo String[][][] e inizializzare l'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", ...
Emetti la lunghezza dell'array.
[2]-> strArray.length; | $1 ==> 3
Emetti la lunghezza dell'array all'indice 0.
[3]-> strArray[0].length; | $4 ==> 2
Emetti la lunghezza dell'array all'indice 1 all'interno dell'array all'indice 0.
[4]-> strArray[0][1].length; | $6 ==> 3
Emetti l'array all'indice 0.
[5]-> strArray[0] | $10 ==> String[2][] { String[3] { "A", "B", "C" }, | String[3] { "AA", "AB", "AC" } }
Emetti l'array all'indice 1 all'interno dell'array all'indice 0.
strArray[0][1] | $11 ==> String[3] { "AA", "AB", "AC" }
Emetti l'elemento all'indice 0 nell'array all'indice 1 all'interno dell'array all'indice 0.
strArray[0][1][0] | $12 ==> "AA" [8]->
Utilizzo delle eccezioni non selezionate
JShell genera eccezioni non controllate in fase di esecuzione. Ad esempio, se una variabile di tipo String che è stato inizializzato al suo valore predefinito null si accede. java.lang.NullPointerException viene lanciato.
[1]-> String str; | str ==> null [2]-> str.length(); | java.lang.NullPointerException thrown: | at (#2:1) [3]->
Come altro esempio, se si accede a un indice di array al di fuori delle dimensioni di un array, java.lang.ArrayIndexOutOfBoundsException viene lanciato.
[4]-> String[] str={"A","B","C"}; | str ==> String[3] { "A", "B", "C" } [5]-> str[3]; | java.lang.ArrayIndexOutOfBoundsException thrown: 3 | at (
Se viene invocato un metodo che definisce la divisione per zero, java.lang.ArithmeticException viene lanciato.
[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]->
Conclusione
In questi primi quattro articoli, abbiamo discusso dell'esecuzione di frammenti di codice per variabili, istruzioni, metodi, classi, interfacce e array. JShell è progettato per eseguire solo frammenti di codice e come tali alcune delle funzionalità sono diverse rispetto a quando si esegue un'applicazione Java completa da un file di codice sorgente. In altri due articoli esploreremo alcune altre caratteristiche di JShell.