JShell é um novo recurso no Java 9 para facilitar a execução de trechos de código. Os trechos de código JShell são exatamente os mesmos que o código-fonte Java em um arquivo para um aplicativo. Conforme discutido em um artigo anterior, “Using JShell in Java 9 in NetBeans 9.0, Part 3”, o JShell não permite vários modificadores—incluindo default, access, synchronized, public, private e protected—que são suportados em um arquivo de código-fonte . O JShell foi projetado principalmente para testar e depurar código Java e não para executar aplicativos completos. Neste artigo de continuação, executaremos snippets para classes, interfaces e arrays. Usamos o NetBeans 9 como nos artigos anteriores. Também discutiremos exceções não verificadas. Este artigo tem as seguintes seções:
- Usando aulas
- Modificando uma classe
- Como listar turmas
- Usando construtores de classe
- Extensão de uma turma
- Substituindo um método
- Usando interfaces
- Usando uma implementação padrão para um método
- Declarando um método de interface como estático
- Usando matrizes
- Usando exceções não verificadas
- Conclusão
Usando aulas
Nesta seção, discutiremos a execução de trechos de código para classes. Declare uma classe simples C do seguinte modo.
[1]-> class C { } | created class C
Classe C é criado. Ao contrário de um método que pode ser invocado diretamente, uma classe deve primeiro ser instanciada da seguinte forma.
[3]-> new C() | $1 ==> [email protected]
Uma nova instância da classe C, $1 é criado. Assim como as declarações de método, as declarações de classe são modificáveis ao declarar novamente a classe. Uma classe pode implementar uma interface usando implements . Como exemplo, declare uma interface I .
[1]-> interface I{} | created interface I
Criar classe C para implementar a interface I .
[3]-> class C implements I{} | replaced class C [4]->
Classe C , criado anteriormente, é substituído.
Uma declaração de classe no JShell não tem o conceito de um aplicativo como uma classe Java declarada em um arquivo teria. Uma classe Java em um arquivo com o public static void main(String[] argv) método é um aplicativo Java. O public static void main(String[] argv) pode ser adicionado no JShell, mas é apenas outro trecho de código. Crie uma turma Olá que inclui o método 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]->
O main(String[]) método é um estático e é definido para a classe em vez de uma instância de uma classe. Crie uma String[] array para fornecer ao main(String[]) método.
String[] strArray={"Hello"," JShell"};
Invoque o main(String[]) método com a String[] como um arg.
Hello.main(strArray)
Uma mensagem Hello JShell obtém saída, conforme mostrado na Figura 1.
Figura 1: Invocando o método estático em uma classe
Modificando uma classe
Uma classe pode ser modificada conforme necessário modificando ou excluindo qualquer uma de suas declarações de método ou adicionando novos métodos. Redeclare a classe Olá sem o main(String[]) e a classe é substituída.
[4]-> class Hello{ } | replaced class Hello [5]->
Adicione novamente o main(String[]) mas com um System.out.println ligeiramente diferente demonstração. Turma Olá novamente é substituído.
[5]-> class Hello{ public static void main(String[] argv) {System.out.println(argv[0]);} } | replaced class Hello [5]->
Invoque o estático método main(String[]) com Hello.main(strArray) para uma saída diferente, como mostrado na Figura 2.
Figura 2: Invocando uma variação do método main
A provisão para substituir uma classe é útil ao desenvolver uma classe. Um método pode ser adicionado por vez e a classe testada. Como exemplo, adicione um segundo método hello(String) . Novamente, classe Olá é substituído.
[9]-> class Hello{ void main(String[] argv){System.out.println(argv[0]);} String hello(String name){return name;} } | replaced class Hello
O método hello(String) adicionado, sendo um método de instância, precisaria de uma instância de classe para invocar. Crie uma instância de classe.
[10]-> new Hello() | $2 ==> [email protected]
Invoca o método hello(String) usando instância de classe $2 .
[11]-> $2.hello("John") | $6 ==> "John"
Listar classes
Uma classe Java é um tipo. Uma interface também é um tipo. Todos os tipos definidos na sessão JShell são listados com o /types comando. Defina algumas classes e 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
Execute o /types comando e todas as classes e interfaces são listadas.
[6]-> /types | class C | class D | class B | interface I | interface J
Usando construtores de classe
A classe no-arg é definida implicitamente em uma classe se não definir nenhum construtor com args. Anteriormente, instanciamos uma classe C que não declarou nenhum construtor explicitamente com new C() . O construtor no-arg pode ser definido explicitamente.
Em seguida, crie uma classe Olá que declara um construtor de classe. O construtor tem um parâmetro do tipo String . O construtor pode ser declarado com o public modificador e é implicitamente público se não estiver definido como público .
[6]-> class Hello{ String name; public Hello(String name){this.name=name;} void hello(){System.out.println("Hello "+name);} }
Crie uma instância da classe Hello .
Hello hello=new Hello("John")
Invoque o método de instância hello() para emitir uma mensagem, conforme mostrado na Figura 3.
Figura 3: Usando uma classe com um construtor
Extensão de uma classe
Uma classe pode ser estendida com extensões assim como em um arquivo de código-fonte Java. Como exemplo, crie a classe D que declara um nome de variável do tipo tt>String, um construtor no-arg e um método hello(String) . O olá(String) O método gera um "Olá" mensagem usando o nome arg fornecido.
class D{ String name="Michael"; public D(){} void hello(String name){System.out.println("Hello "+name);} }
Crie uma classe C que estende a classe C e declara o hello() método, que não substitui a classe D 's olá(String) método e parâmetros são diferentes. O olá() método invoca um nome de campo, que é herdado da classe D .
class C extends D{ void hello(){System.out.println("Hello "+name);} }
Instanciar a classe C e invoque o hello() método.
new C().hello()
Uma mensagem “Hello” obtém a saída, conforme mostrado na Figura 4. O name valor do campo definido na classe D é usado.
Figura 4: Estendendo uma classe
Se invocarmos o hello(String) método que classe C herda da classe D , obteríamos uma saída diferente, conforme mostrado na Figura 5.
Figura 5: Invocando um método herdado de uma classe estendida
Substituindo um método
Uma classe pode substituir um método herdado de uma classe estendida fornecendo sua própria definição de método. Crie uma classe D que declara um campo nome e um método hello() .
class D{ String name="Michael"; void hello(){System.out.println("Hello "+name);} }
Declare uma classe C que estende a classe D e substitui o hello() método. Classe C também oculta o campo nome .
class C extends D{ String name="John"; void hello(){System.out.println("Hello "+name); }
Crie uma instância da classe C e invoque o método hello() .
new C().hello()
O olá() método da classe C é invocado porque substitui o método da classe D . O campo nome na classe C oculta o campo nome na classe D . A saída da mensagem é mostrada na Figura 6.
Figura 6: Substituindo um método
Se a classe C não oculta o campo nome da classe D , o nome campo na classe D é usado, como mostrado na Figura 7.
Figura 7: Acessando o campo da classe estendida
Uma classe C objeto é uma instância da classe D porque estende a classe D . Execute a seguinte instrução para descobrir se uma instância da classe C também é uma instância da classe D .
new C() instanceof D
Um valor de true verifica uma instância da classe C também é uma instância da classe D , como mostrado na Figura 8.
Figura 8: Verificando se uma instância da classe C também é uma instância da classe D
Porque uma instância da classe C também é uma instância da classe D , ele pode ser convertido em D do seguinte modo:
D d=(D)(new C());
Em seguida, acesse o campo nome para objeto d do tipo D .
d.name;
E, invoque o método hello() para objeto d do tipo D .
d.hello();
A saída do valor do campo é da classe D porque d é um objeto do tipo D , conforme mostrado na Figura 9. O método hello() invocado é da classe C .
Figura 9: Lançando um objeto do tipo C para D
Usando interfaces
Nesta seção, executaremos alguns trechos de interfaces no JShell. Uma classe existente pode ser modificada para implementar uma interface. Criar classe C .
[1]-> class C{} | created class C
Crie uma interface I que define um método hello() .
[2]-> interface I { String hello(); } | created interface I
Re-declarar a classe C para implementar a interface I . Classe C fornece implementação para o método hello() .
[3]-> class C implements I{ public String hello(){ return "Hello JShell"; } } | replaced class C
Crie uma instância da classe C .
[4]-> new C() | $1 ==> [email protected]
Usando a variável de instância de classe, invoque o método hello() e a saída do método é exibida.
[5]-> $1.hello() | $2 ==> "Hello JShell" [6]->
Como os métodos em uma interface são implicitamente públicos enquanto os métodos em uma classe não são um método, a implementação na classe C deve ser declarado com o public modificador de acesso. Se não for declarado público , uma mensagem de erro é gerada porque não especificando um public modificador de acesso padrão para um modificador de acesso mais fraco, que não é permitido ao implementar uma 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(){ | ^--------------...
Usando uma implementação padrão para um método
A partir do Java 8, um método de interface pode fornecer uma implementação padrão para um método usando a palavra-chave default . Declare uma interface que fornece uma implementação padrão para o método hello() usando o padrão palavra-chave.
[1]-> interface I { default String hello(){ return "Hello JShell"; } } | created interface I
Declare uma classe C que implementa a interface I .
[2]-> class C implements I{ } | created class C
Crie uma instância da classe C e invoque o método hello() . O método da implementação padrão na interface I obtém saída.
[3]-> new C().hello(); | $1 ==> "Hello JShell"
Declarando um método de interface como estático
Desde o Java 8, os métodos de interface podem ser declarados static . Crie uma interface I que declara um estático método.
[1]-> interface I { static String hello(){ return "Hello JShell"; } } | created interface I
Invoque o método estático usando a interface I .
[2]-> I.hello() | $1 ==> "Hello JShell"
Uma classe não pode ser declarada final e, se a classe final modificador é usado, ele é ignorado.
[5]-> [1]-> final class C{} | Warning: | Modifier 'final' not permitted in top-level declarations, | ignored | final class C{} | ^---^ | created class C
Usando matrizes
Nesta seção, executaremos alguns trechos de código para arrays. Declarar, instanciar e acessar arrays não é diferente de um aplicativo baseado em arquivo de código-fonte Java. Como exemplo, declare um array do tipo String[] . A matriz é inicializada para null .
[1]-> String[] strArray; | strArray ==> null
Aloque memória para a matriz. O tamanho do array, uma vez definido, não pode ser modificado. Os elementos do array são inicializados com null .
[2]-> strArray =new String[3]; | strArray ==> String[3] { null, null, null }
Inicialize os elementos do array usando os índices do array.
[3]-> strArray[0]="A"; strArray[1]="B"; strArray[2]="C"; | $4 ==> "A" | $5 ==> "B" | $6 ==> "C"
Emita o comprimento da matriz e o elemento no índice 1.
[6]-> strArray.length; strArray[1]; | $9 ==> 3 | $10 ==> "B"
O comprimento do array é gerado como 3. O elemento no índice 1 é “B”. Um array pode ser inicializado quando declarado da seguinte forma.
[1]-> String[] strArray={"A","B","C"}; | strArray ==> String[3] { "A", "B", "C" }
Emita o comprimento da matriz.
[2]-> strArray.length; | $1 ==> 3
Emita o elemento no índice 0.
[3]-> strArray[0]; | $4 ==> "A" [4]->
Um array multidimensional pode ser declarado como em um aplicativo Java. Crie um array tridimensional do tipo String[][][] e inicialize a matriz.
[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", ...
Emita o comprimento da matriz.
[2]-> strArray.length; | $1 ==> 3
Emita o comprimento do array no índice 0.
[3]-> strArray[0].length; | $4 ==> 2
Emita o comprimento do array no índice 1 dentro do array no índice 0.
[4]-> strArray[0][1].length; | $6 ==> 3
Gere a matriz no índice 0.
[5]-> strArray[0] | $10 ==> String[2][] { String[3] { "A", "B", "C" }, | String[3] { "AA", "AB", "AC" } }
Gere a matriz no índice 1 dentro da matriz no índice 0.
strArray[0][1] | $11 ==> String[3] { "AA", "AB", "AC" }
Emita o elemento no índice 0 no array no índice 1 dentro do array no índice 0.
strArray[0][1][0] | $12 ==> "AA" [8]->
Usando exceções não verificadas
JShell lança exceções não verificadas em tempo de execução. Por exemplo, se uma variável do tipo String que foi inicializado com seu valor padrão null é acessado. java.lang.NullPointerException é lançado.
[1]-> String str; | str ==> null [2]-> str.length(); | java.lang.NullPointerException thrown: | at (#2:1) [3]->
Como outro exemplo, se um índice de array fora do tamanho de um array for acessado, java.lang.ArrayIndexOutOfBoundsException é lançado.
[4]-> String[] str={"A","B","C"}; | str ==> String[3] { "A", "B", "C" } [5]-> str[3]; | java.lang.ArrayIndexOutOfBoundsException thrown: 3 | at (
Se um método que define a divisão por zero for invocado, java.lang.ArithmeticException é lançado.
[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]->
Conclusão
Nestes primeiros quatro artigos, discutimos a execução de trechos de código para variáveis, instruções, métodos, classes, interfaces e arrays. O JShell foi projetado para executar apenas trechos de código e, como tal, alguns dos recursos são diferentes de executar um aplicativo Java completo a partir de um arquivo de código-fonte. Em mais dois artigos, exploraremos alguns outros recursos do JShell.