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.

Você vai aprender
  • 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, /edit e /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 como ls nã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:

ComandoO que faz
/varsLista as variáveis com tipo e valor.
/methodsLista os métodos criados.
/listMostra tudo o que você digitou (que deu certo), numerado.
/save arquivo.jshGrava o que você digitou num arquivo.
/open arquivo.jshExecuta de novo as linhas de um arquivo.
/resetApaga tudo e recomeça a sessão do zero.
/edit nomeAbre um editor para mudar uma variável ou método.
/importsLista as bibliotecas já importadas.
/helpA ajuda (em inglês); /help vars explica um comando.
/exitSai 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.toU e aperte Tab, e o JShell completa para nome.toUpperCase(. Se houver várias opções, ele lista todas. Digitar Math. e Tab mostra tudo o que a classe Math oferece. 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á"); }.

Digitei 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çãoUsePor quê
Testar uma conta, um método de String, uma ideiaJShellResposta na hora, sem arquivo nem compilação.
Descobrir o que um método faz ou devolveJShellTab mostra as opções; o ==> mostra o valor e o tipo (/vars).
Um programa de verdade, para rodar de novo amanhãArquivo .javaO código fica guardado e organizado numa classe.
Programa que lê o teclado, recebe argumentos ou tem várias classesArquivo .javaÉ como os programas Java são feitos e distribuídos.
Aprender um recurso novo deste guiaOs doisExperimente 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

  • jshell abre; /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 nem main; 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 do javac); | Exception = quebrou ao rodar. A sessão continua.
  • JShell para experimentar; arquivo .java para programas de verdade.