Java JShell
Para testar uma conta ou ver o que um método faz, escrever uma classe inteira, compilar e rodar é trabalho demais. O JShell resolve: você digita uma linha de Java, aperta Enter e a resposta aparece na hora. Ele vem no JDK desde o Java 9 e é o lugar ideal para experimentar. Nesta aula você aprende a usá-lo e a ler as respostas dele.
- Abrir e fechar o JShell.
- Calcular expressões e entender o
$1 ==> 15. - Criar variáveis e métodos, sem classe e sem
main. - Os comandos
/vars,/methods,/list,/save,/open,/reset,/edite/exit. - Completar com Tab e repetir com as setas.
- Ler as mensagens
| Error:e| Exception. - Quando usar o JShell e quando escrever um arquivo
.java.
A ideia: uma calculadora que entende Java
Um programa em arquivo é como uma carta: você escreve tudo, envia e só depois vê a resposta. O JShell é uma conversa: você fala uma frase, ele responde, você fala outra. Esse tipo de ferramenta se chama REPL, de Read–Eval–Print Loop: "lê, avalia, mostra, repete". O nome JShell vem de Java shell, "concha" ou "console" do Java.
No JShell você não precisa de public class, nem de main, nem de compilar. E, na maioria das linhas, nem do ; no fim.
Abrir e sair
No terminal, digite jshell (ele vem no JDK, junto com o javac; se der "comando não encontrado", veja JDK, JRE e JVM):
$ jshell | Welcome to JShell -- Version 25.0.4.1 | For an introduction type: /help intro jshell> /exit | Goodbye $
- | Welcome to JShell
- "Bem-vindo ao JShell", com a versão do Java. O JShell só fala inglês. As linhas que começam com
|são mensagens do próprio JShell. - /help intro
- Sugestão: digite isso para ler uma introdução (em inglês).
- jshell>
- O prompt do JShell: ele está esperando você digitar. Não confunda com o prompt do terminal (
ana@notebook:~$): dentro do JShell, comandos do terminal comolsnão funcionam. - /exit
- Sai do JShell e volta ao terminal. As palavras que começam com
/são comandos do JShell, não Java. Também dá para sair com Ctrl+D.
Na primeira vez que o JShell abre, pode aparecer uma linha extra, como INFO: Created user preferences directory. ("criei a pasta de preferências do usuário"). É só um aviso de primeira vez.
Expressões: o $1 ==> 15
Uma expressão é qualquer pedaço de código que produz um valor: uma conta, um texto, uma comparação. Digite uma e aperte Enter:
$ jshell | Welcome to JShell -- Version 25.0.4.1 | For an introduction type: /help intro jshell> 7 + 8 $1 ==> 15 jshell> 10 / 3 $2 ==> 3 « divisão entre inteiros: a parte decimal é descartada jshell> 10.0 / 3 $3 ==> 3.3333333333333335 « com um número decimal, a divisão é decimal jshell> "Olá, " + "Ana" $4 ==> "Olá, Ana" « texto + texto = texto emendado jshell> $1 * 2 $5 ==> 30 « dá para usar um resultado anterior
Cada resposta tem o formato NOME ==> VALOR:
- $1
- O JShell guardou o resultado numa variável criada por ele, chamada
$1(a primeira; depois$2,$3…). O número é a ordem da linha na sessão. Você pode usar essa variável depois, como no$1 * 2. - ==>
- Uma seta que quer dizer "vale".
- 15
- O valor. Textos aparecem entre aspas (
"Olá, Ana") para você ver onde começam e terminam.
Os resultados desta sessão já mostram duas lições que voltam em Operadores Aritméticos e double e float: 10 / 3 dá 3 (inteiro dividido por inteiro dá inteiro), e 10.0 / 3 dá 3.3333333333333335, com um 5 "estranho" no fim, porque o computador guarda decimais de forma aproximada.
Missão: calcule a média de 3 e 4 (some e divida por 2). Se o resultado der 3, você caiu na divisão inteira: use 2.0 no lugar de 2.
(3 + 4) / 2.0
Variáveis
Você pode criar suas próprias variáveis (caixas com nome que guardam um valor; a aula Variáveis explica com calma). O JShell responde com o nome e o valor guardado:
jshell> int idade = 29
idade ==> 29 « a caixa idade foi criada com 29
jshell> idade + 1
$7 ==> 30 « uma conta com a variável (ela continua 29)
jshell> idade = idade + 1
idade ==> 30 « agora sim: idade passou a valer 30
jshell> String nome = "Ana"
nome ==> "Ana"
jshell> nome.length()
$10 ==> 3 « quantas letras tem "Ana"
jshell> nome.toUpperCase()
$11 ==> "ANA" « o texto em maiúsculas
jshell> System.out.println("Oi, " + nome)
Oi, Ana « o println escreve; não há valor para mostrar
Repare na última linha: o println não produz um valor, só escreve na tela. Por isso não aparece $12 ==>, só o texto escrito. E nenhuma das linhas levou ;: o JShell aceita sem, quando a linha é uma instrução só. (Se você puser, tudo bem também.)
Para ver todas as variáveis da sessão, use /vars:
jshell> /vars | int $1 = 15 | int $2 = 3 | double $3 = 3.3333333333333335 | String $4 = "Olá, Ana" | int $5 = 30 | int idade = 30 | int $7 = 30 | String nome = "Ana" | int $10 = 3 | String $11 = "ANA"
Cada linha mostra o tipo (int = inteiro, double = decimal, String = texto), o nome e o valor atual. O JShell escolheu sozinho o tipo das variáveis $.
Missão: crie String nome = "Ana" e depois mostre o nome em maiúsculas com nome.toUpperCase().
String nome = "Ana" nome.toUpperCase()
Métodos
Também dá para criar métodos (blocos de código com nome, que recebem valores e devolvem um resultado; assunto de Métodos). Quando a linha termina com {, o JShell entende que o código continua e muda o prompt para ...> até você fechar a chave. Numa sessão nova:
jshell> double media(double a, double b) {
...> return (a + b) / 2;
...> }
| created method media(double,double) « "criei o método media, que recebe dois double"
jshell> media(7, 8)
$2 ==> 7.5
jshell> media(6.5, 9)
$3 ==> 7.75
jshell> String saudacao(String nome) { return "Olá, " + nome + "!"; }
| created method saudacao(String)
jshell> saudacao("Ana")
$5 ==> "Olá, Ana!"
jshell> /methods
| double media(double,double)
| String saudacao(String)
Dentro do método, o ; volta a ser obrigatório, como num arquivo. O comando /methods lista os métodos criados. Para corrigir um método, basta escrevê-lo de novo com o mesmo nome; o JShell avisa que o modificou:
jshell> String saudacao(String nome) { return "Oi, " + nome + "!"; }
| modified method saudacao(String)
jshell> saudacao("Ana")
$7 ==> "Oi, Ana!"
Os comandos do JShell
Tudo o que começa com / é um comando do próprio JShell. Os mais úteis:
| Comando | O que faz |
|---|---|
/vars | Lista as variáveis com tipo e valor. |
/methods | Lista os métodos criados. |
/list | Mostra tudo o que você digitou (que deu certo), numerado. |
/save arquivo.jsh | Grava o que você digitou num arquivo. |
/open arquivo.jsh | Executa de novo as linhas de um arquivo. |
/reset | Apaga tudo e recomeça a sessão do zero. |
/edit nome | Abre um editor para mudar uma variável ou método. |
/imports | Lista as bibliotecas já importadas. |
/help | A ajuda (em inglês); /help vars explica um comando. |
/exit | Sai do JShell. |
/list, /save, /reset e /open
Numa sessão nova, a Ana fez algumas contas e um método, e depois pediu a lista:
jshell> /list
1 : 7 + 8
2 : int idade = 29; « o JShell completou o ; nas declarações
3 : idade + 1
4 : String nome = "Ana";
5 : double media(double a, double b) { return (a + b) / 2; }
6 : media(7, 8)
jshell> /save contas.jsh « grava tudo em ~/contas.jsh
jshell> /reset
| Resetting state. « "reiniciando": tudo foi apagado
jshell> idade
| Error:
| cannot find symbol
| symbol: variable idade
| idade
| ^---^ « a variável não existe mais
jshell> /open contas.jsh « roda de novo as linhas gravadas
jshell> idade
idade ==> 29 « voltou
O arquivo .jsh é texto comum, com uma linha por trecho. Ele é útil para guardar experiências e retomá-las outro dia: jshell contas.jsh já abre carregando o arquivo.
/edit
/edit media abre uma pequena janela de edição com o código do método media; você muda, clica em Accept ("aceitar") e o JShell recria o método. Sem nome, /edit abre todos os trechos de uma vez. Num terminal sem interface gráfica, dá para escolher o editor do terminal com /set editor nano. (Ilustrativo: a janela não pôde ser mostrada na máquina do guia.)
Tab e as setas
Duas teclas tornam o JShell muito mais rápido:
- Tab completa: digite
nome.toUe aperte Tab, e o JShell completa paranome.toUpperCase(. Se houver várias opções, ele lista todas. DigitarMath.e Tab mostra tudo o que a classeMathoferece. Apertar Tab de novo depois de um nome de método mostra a documentação dele (em inglês). - ↑ e ↓ percorrem as linhas já digitadas, como no terminal. Para corrigir um erro, aperte ↑, conserte e Enter.
(A lista exata que o Tab mostra depende do que você digitou; experimente no seu computador.)
Quando dá errado: | Error: e | Exception
O JShell mostra os mesmos dois tipos de problema de um programa normal (veja O Editor do Guia): erros de compilação e exceções. A diferença é o formato, com a barra | na frente e um sublinhado ^--^ no lugar do ^ sozinho do javac.
| Error: — o código não compila
jshell> int x = "oi" | Error: | incompatible types: java.lang.String cannot be converted to int | int x = "oi"; | ^--^ jshell> idadee | Error: | cannot find symbol | symbol: variable idadee | idadee | ^----^
O que aconteceu: no primeiro, um texto (String) numa caixa de inteiros (int): "tipos incompatíveis: String não pode ser convertido em int". No segundo, um nome que não existe (erro de digitação): "não encontrei o símbolo". O ^----^ sublinha exatamente o trecho com problema. As mensagens são as mesmas do javac; a aula Lendo Erros do javac explica cada uma.
Como resolver: aperte ↑, corrija e Enter. A linha com erro não é guardada: nada foi criado.
| Exception — o código rodou e quebrou
jshell> 10 / 0 | Exception java.lang.ArithmeticException: / by zero | at (#1:1)
O que aconteceu: a conta compila, mas dividir um inteiro por zero é impossível, e o Java lança uma exceção. O at (#1:1) diz onde: no trecho número 1, linha 1. Num programa normal, a mesma exceção apareceria como Exception in thread "main" java.lang.ArithmeticException: / by zero (veja O que são Exceções). No JShell, a sessão continua normalmente depois do erro.
';' expected dentro de um método
jshell> void ola() { System.out.println("olá") }
| Error:
| ';' expected
| void ola() { System.out.println("olá") }
| ^
O que aconteceu: o JShell dispensa o ; só no fim de uma linha solta. Dentro das chaves de um método, as regras são as do Java normal. Como resolver: void ola() { System.out.println("olá"); }.
ls ou javac e deu erro
O que aconteceu: você ainda está dentro do JShell (o prompt é jshell>), e ele tenta entender ls como código Java. Como resolver: /exit para voltar ao terminal.
JShell ou arquivo .java?
| Situação | Use | Por quê |
|---|---|---|
Testar uma conta, um método de String, uma ideia | JShell | Resposta na hora, sem arquivo nem compilação. |
| Descobrir o que um método faz ou devolve | JShell | Tab mostra as opções; o ==> mostra o valor e o tipo (/vars). |
| Um programa de verdade, para rodar de novo amanhã | Arquivo .java | O código fica guardado e organizado numa classe. |
| Programa que lê o teclado, recebe argumentos ou tem várias classes | Arquivo .java | É como os programas Java são feitos e distribuídos. |
| Aprender um recurso novo deste guia | Os dois | Experimente as partes no JShell; junte tudo num arquivo. |
Uma terceira opção, para programas curtos: o main simplificado do Java 25 com java Main.java (veja Olá, Mundo e javac e java).
Missão: crie um método double media(double a, double b) que devolve a média dos dois números, e chame media(7, 8). O resultado deve ser 7.5. Lembre do ; dentro das chaves.
double media(double a, double b) { return (a + b) / 2; }
media(7, 8)
Exercícios
1. Sair
Qual comando sai do JShell?
2. Listar variáveis
Qual comando lista todas as variáveis da sessão, com tipo e valor?
3. Você digitou 5 * 4 e o JShell respondeu $3 ==> 20. O que é $3?
4. O que o JShell responde para 10 / 4?
5. O prompt mudou para ...> depois que você digitou uma linha terminada em {. O que o JShell espera?
Resumo
jshellabre;/exit(ou Ctrl+D) sai. O prompt éjshell>.- Expressões respondem com
$N ==> valor; o$Né uma variável que você pode reusar. - Variáveis (
int idade = 29) e métodos funcionam sem classe nemmain; fora das chaves, o;é opcional. /vars,/methods,/list,/save,/open,/reset,/edit: os comandos começam com/.- Tab completa; ↑ repete e corrige.
| Error:= não compilou (mensagens dojavac);| Exception= quebrou ao rodar. A sessão continua.- JShell para experimentar; arquivo
.javapara programas de verdade.