Introducción a JShell con Ejemplos

Fundamentos

A partir de JDK 9, Java ha incluido una herramienta llamada JShell. Proporciona un entorno interactivo que le permite experimentar rápida y fácilmente con código Java. JShell implementa lo que se conoce como ejecución del bucle Read-Eval-Print-Loop (REPL). Usando este mecanismo, se le pedirá que ingrese un fragmento de código. Este fragmento se lee y se evalúa. A continuación, JShell muestra la salida relacionada con el código, como la salida producida por una sentencia println(), el resultado de una expresión, o el valor actual de una variable. JShell entonces pide la siguiente pieza de código, y el proceso continúa (es decir, bucles). En el lenguaje de JShell, cada secuencia de código que se introduce se denomina fragmento (snippet).

Un punto clave para entender acerca de JShell es que no necesita ingresar un programa Java completo para usarlo. Cada fragmento que ingresas es simplemente evaluado a medida que lo ingresas. Esto es posible porque JShell maneja automáticamente muchos de los detalles asociados con un programa Java. Esto le permite concentrarse en una característica específica sin tener que escribir un programa completo, lo que hace que JShell sea especialmente útil cuando está aprendiendo Java por primera vez.

Como es de esperar, JShell también puede ser útil para programadores experimentados. Debido a que JShell almacena información de estado, es posible introducir secuencias de código multilínea y ejecutarlas dentro de JShell. Esto hace que JShell sea muy útil cuando se necesita hacer un prototipo de un concepto porque le permite experimentar interactivamente con su código sin tener que desarrollar y compilar un programa completo.

1. Conceptos básicos de JShell

JShell es una herramienta de línea de comandos. Por lo tanto, se ejecuta en una ventana de símbolo del sistema. Para iniciar una sesión de JShell, ejecute jshell desde la línea de comando. Después de hacerlo, verá el mensaje de JShell:

jshell
jshell en Windows
jshell en Windows 10

Cuando aparece este aviso, puede ingresar un fragmento de código o un comando JShell

En su forma más simple, JShell le permite ingresar una declaración individual e inmediatamente ver el resultado. Para comenzar, piense en el primer ejemplo de programa Java en este libro. Se muestra de nuevo aquí:

class Ejemplo{
     public static void main(String args[]){
     System.out.println("Aprende con JavadesdeCero.es");
      }
}

En este programa, solo la instrucción println() en realidad realiza una acción, que muestra un mensaje en la pantalla. El resto del código simplemente proporciona las declaraciones de clase y método requeridas. En JShell, no es necesario especificar explícitamente la clase o el método para ejecutar la instrucción println(). JShell puede ejecutarlo directamente por sí mismo. Para ver cómo, ingrese la siguiente línea en el indicador de JShell:

System.out.println("Aprende con JavadesdeCero.es");

Luego, presiona la tecla Intro. Este resultado se muestra:

Aprende con JavadesdeCero.es
jshell>

Como puede ver, la llamada a println() se evalúa y se emite su argumento de cadena. Luego, se vuelve a mostrar el mensaje. Antes de continuar, es útil explicar por qué JShell puede ejecutar una declaración única, como la llamada a println(), cuando el compilador de Java, javac, requiere un programa completo. JShell puede evaluar una declaración única porque JShell proporciona automáticamente el framework de programa necesario para usted, detrás de escena.

Esto consiste en una clase sintética (clases en tiempo de ejecución) y un método sintético. Por lo tanto, en este caso, la instrucción println() está incrustada en un método sintético que es parte de una clase sintética. Como resultado, el código anterior aún forma parte de un programa Java válido aunque no se ve todos los detalles. Este enfoque proporciona una forma muy rápida y conveniente de experimentar con código Java.

2. Variables con JShell

A continuación, veamos cómo se admiten las variables. En JShell, puede declarar una variable, asignar un valor a la variable y usarla en cualquier expresión válida. Por ejemplo, ingrese la siguiente línea en la consola:

int contar;

Después de hacerlo, verá la siguiente respuesta:

contar ==> 0

Esto indica que el contar se ha agregado a la clase sintética y se inicializó a cero. Además, se ha agregado como una variable static de la clase sintética. Luego,de el valor 10 a contar ingresando esta declaración:

contar=10;

Verás esta respuesta:

contar=10;

Como puede ver, el valor de contar ahora es 10. Debido a que contar es static, se puede usar sin referencia a un objeto.

Ahora que se ha declarado contar, se puede usar en una expresión. Por ejemplo, ingrese esta instrucción println():

System.out.println("El recíproco de 10 es: "+1.0/contar);

JShell responde con:

El recφproco de 10 es: 0.1

Aquí, el resultado de la expresión 1.0/contar es 0.1 porque contar fue previamente asignado el valor 10. Además de demostrar el uso de una variable, el ejemplo anterior ilustra otro aspecto importante de JShell: mantiene información de estado. En este caso, count se le asigna el valor 10 en una declaración y luego este valor se usa en la expresión 1.0/contar en la llamada subsiguiente a println().

3. Bucles con JShell

En general, JShell mantiene el estado actual y el efecto de los fragmentos de código que ingresa. Esto le permite experimentar con fragmentos de código más grandes que abarcan múltiples líneas. Antes de continuar, intentemos con un ejemplo más. En este caso, crearemos un bucle for que usa la variable contar. Comience por ingresar a esta línea en el prompt:

for(contar=0;contar<5;contar++)

En este punto, JShell responde con el siguiente mensaje:

 ...>

Esto indica que se requiere código adicional para finalizar la declaración. En este caso, debe proporcionarse el objetivo del bucle for. Introduzca la siguiente:

System.out.println(contar);

Después de ingresar a esta línea, la instrucción for está completa y ambas líneas se ejecutan. Verá el siguiente resultado:

0
1
2
3
4

Además de sentencias y declaraciones variables, JShell le permite declarar clases y métodos, y usar instrucciones import. Otro punto: cualquier código que sea válido para JShell también será válido para la compilación de javac, suponiendo que se proporciona el framework necesario para crear un programa completo. Por lo tanto, si un fragmento de código puede ser ejecutado por JShell, entonces ese fragmento representa un código válido de Java. En otras palabras, el código JShell es código Java.

4. Listar, editar y volver a ejecutar el código

JShell admite una gran cantidad de comandos que le permiten controlar el funcionamiento de JShell. En este punto, tres son de particular interés porque le permiten listar el código que ha ingresado, editar una línea de código y volver a ejecutar un fragmento de código.

4.1. Lista código

En JShell, todos los comandos comienzan con un / seguido del comando. Tal vez el comando más utilizado es /list, que enumera el código que ha ingresado. Suponiendo que ha seguido junto con los ejemplos que se muestran en la sección anterior, puede listar su código ingresando /list en este momento. Su sesión de JShell responderá con una lista numerada de los fragmentos que ingresó. Preste especial atención a la entrada que muestra el bucle for. Aunque se compone de dos líneas, constituye una declaración. Por lo tanto, solo se usa un número de fragmento.

Listar, editar y volver a ejecutar código JShell
Listar, editar y volver a ejecutar código en JShell

4.2. Editar Fragmento

Puede editar un fragmento utilizando el comando /edit. Este comando hace que se abra una ventana de edición en la que puede modificar su código. El comando /edit tiene tres formas.

  1. Primero, si especifica /edit por sí mismo, la ventana de edición contiene todas las líneas que ha ingresado y le permite editar cualquier parte de la misma.
  2. En segundo lugar, puede especificar un fragmento específico para editar usando /edit n, donde n especifica el número del fragmento. Por ejemplo, para editar el fragmento 3, use /edit 3.
  3. Finalmente, puede especificar un elemento con nombre, como una variable. Por ejemplo, para cambiar el valor del contar, use /edit contar.

4.3. Ejecutar código

Como has visto, JShell ejecuta el código cuando lo ingresas. Sin embargo, también puede volver a ejecutar lo que ingresó.

  • Para volver a ejecutar el último fragmento que ingresó, use /!.
  • Para volver a ejecutar un fragmento específico, especifique el número con esta forma: /n, donde n especifica el fragmento para ejecutar. Por ejemplo, para volver a ejecutar el segundo fragmento, ingrese /2.
  • Puede volver a ejecutar un fragmento especificando su posición relativa al fragmento actual mediante el uso de un desplazamiento negativo. Por ejemplo, para volver a ejecutar un fragmento que es tres fragmentos antes del actual, use /-3.

Hay otro comando importante que necesita saber ahora: /exit. Esto finaliza JShell.

5. Agregar un método

Como se explicó en el curso de Java Intermedio, los métodos ocurren dentro de las clases. Sin embargo, al usar JShell, es posible experimentar con un método sin tener que declararlo explícitamente dentro de una clase. Como se mencionó anteriormente, esto se debe a que JShell automáticamente envuelve fragmentos de código dentro de una clase sintética. Como resultado, puede escribir un método fácil y rápidamente sin tener que proporcionar un marco de clase.

También puede llamar al método sin tener que crear un objeto. Esta característica de JShell es especialmente beneficiosa al aprender los principios básicos de los métodos en Java o al crear prototipos de nuevos códigos. Para comprender el proceso, vamos a trabajar a través de un ejemplo. Para comenzar, inicie una nueva sesión de JShell e ingrese el siguiente método en la consola:

double reciproco(double val){
...> return 1.0/val;
...> }

Esto crea un método que devuelve el recíproco de su argumento. Después de ingresar esto, JShell responde con lo siguiente:

created method reciproco(double)

Esto indica que el método se ha agregado a la clase sintética de JShell y está listo para su uso.

Para llamar a reciproco(), simplemente especifique su nombre, sin ningún objeto o referencia de clase. Por ejemplo, prueba esto:

 System.out.println(reciproco(2.0));

JShell responde mostrando 0.5.

5.1. Métodos Estáticos

Es posible que se pregunte por qué puede llamar a reciproco() sin utilizar el operador de punto y una referencia de objeto. Aquí está la respuesta. Cuando crea un método independiente en JShell, como reciproco(), JShell automáticamente convierte ese método en un miembro estático de la clase sintética. Como debe saber, los métodos estáticos se llaman relativos a su clase, no a un objeto específico. Por lo tanto, no se requiere ningún objeto.

Esto es similar a la forma en que las variables independientes se convierten en variables estáticas de la clase sintética, como se describió anteriormente.

Otro aspecto importante de JShell es su soporte para una referencia directa dentro de un método. Esta función permite que un método llame a otro método, incluso si el segundo método aún no se ha definido. Esto le permite ingresar un método que depende de otro método sin tener que preocuparse por cuál ingresa primero. Aquí hay un ejemplo simple. Ingrese esta línea en JShell:

void miMetodo() { miMetodo2();}

JShell responde con lo siguiente:

| created method miMetodo(), however, 
it cannot be invoked until method miMetodo2() is declared

Como puede ver, JShell sabe que miMetodo2() aún no se ha declarado, pero aún le permite definir miMetodo(). Como es de esperar, si intenta llamar a miMetodo() en este momento, verá un mensaje de error ya que miMetodo2() aún no está definido, pero aún puede ingresar el código de miMetodo().

Luego, defina miMetodo2() de esta manera.

void miMetodo2(){ System.out.println("JShell es increible!");}

Ahora que se ha definido miMetodo2(), puede llamar a miMetodo().

6. Crear una clase

Aunque JShell proporciona automáticamente una clase sintética que envuelve fragmentos de código, también puede crear su propia clase en JShell. Además, puedes crear instancias de objetos de tu clase. Esto le permite experimentar con clases dentro del entorno interactivo de JShell. El siguiente ejemplo ilustra el proceso.

Inicie una nueva sesión de JShell e ingrese la siguiente clase, línea por línea:

class MiClase{
...> double v;
...> MiClase(double d) { v = d; }
...> double reciproco(){return 1.0/v; }
...> }

Cuando termine de ingresar el código, JShell responderá con

created class MiClase

Ahora que ha agregado MiClase, puede usarlo. Por ejemplo, puede crear un objeto MiClase con la siguiente línea:

MiClase obj= new MiClase(10.0);

JShell responderá diciéndole que agregó obj como una variable de tipo MiClase. A continuación, pruebe la siguiente línea:

System.out.println(obj.reciproco());

JShell responde mostrando el valor 0.1.

Como punto de interés, cuando agrega una clase a JShell, se convierte en un miembro anidado estático de una clase sintética.

7. Usa una interfaz

Las interfaces son compatibles con JShell de la misma manera que las clases. Por lo tanto, puede declarar una interfaz e implementarla por una clase dentro de JShell. Vamos a trabajar a través de un simple ejemplo. Antes de comenzar, inicie una nueva sesión de JShell.

La interfaz que utilizaremos declara un método llamado esValido() que se usa para determinar si un valor es válido para algún propósito. Devuelve true si el valor es legal y false de lo contrario. Por supuesto, lo que constituye un valor legal será determinado por cada clase que implemente la interfaz. Comience ingresando la siguiente interfaz en JShell:

 interface MiInterfaz{
...> boolean esValido(double v);
...> }

JShell responde con:

created interface MiInterfaz

Luego, ingrese la siguiente clase, que implementa MiInterfaz:

 class MiClase2 implements MiInterfaz{
...> double inicio;
...> double fin;
...> MiClase2 (double a, double b){ inicio=a;fin=b; }
...> public boolean esValido(double v){
...> if((v>=inicio)&&(v<=fin)) return true;
...> return false;
...> }
...> }

Observe que MiClase2 implementa esValido() determinando si el valor v está dentro del rango (inclusive) de los valores en las variables de instancia MiClase2 de inicio y fin.

Ahora que se han agregado tanto MiInterfaz como MiClase2, puede crear un objeto MiClase2 y llamar a esValido() en él, como se muestra aquí:

MiClase2 obj2 = new MiClase2(0.0,10.0);
jshell> System.out.println(obj2.esValido(5.0));
true

En este caso, se muestra el valor true porque 5 está dentro del rango de 0 a 10. Debido a que MiInterfaz se ha agregado a JShell, también puede crear una referencia a un objeto de tipo MiInterfaz. Por ejemplo, el siguiente es también un código válido:

MiInterfaz obj3 = new MiClase2(1.0,4.0);
jshell> boolean resultado= obj3.esValido(1.1);
resultado ==> true

En este caso, el valor del resultado será true y será informado como tal por JShell. Otro punto: las enumeraciones y anotaciones son compatibles en JShell de la misma manera que las clases y las interfaces.

8. Evaluar expresiones y usar variables incorporadas

JShell incluye la capacidad de evaluar directamente una expresión sin que sea necesario formar parte de una declaración completa de Java. Esto es especialmente útil cuando está experimentando con código y no necesita ejecutar la expresión en un contexto más amplio.

Aquí hay un ejemplo simple. Usando una nueva sesión de JShell, ingrese lo siguiente en el mensaje:

4.0/20.0

JShell responde con:

$25 ==> 0.2

Como puede ver, el resultado de la expresión se calcula y se muestra. Sin embargo, tenga en cuenta que este valor también se asigna a una variable temporal llamada $25. En general, cada vez que una expresión se evalúa directamente, su resultado se almacena en una variable temporal del tipo apropiado.

Los nombres temporales de las variables comienzan con un $ seguido de un número, que se incrementa cada vez que se necesita una nueva variable temporal. 

Puede usar estas variables temporales como cualquier otra variable. Por ejemplo, lo siguiente muestra el valor de $25, que es 0.2 en este caso.

System.out.println($25);

Aquí hay otro ejemplo:

double v=$25*2;

Aquí, el valor $25 por 2 se asigna a v. Por lo tanto, v contendrá 0.4.

Puede cambiar el valor de una variable temporal. Por ejemplo, esto invierte el signo de $25:

jshell> $25=-$25;
$25 ==> -0.2

Las expresiones no están limitadas a valores numéricos. Por ejemplo, aquí hay uno que concatena un String con el valor devuelto por Math.abs($25).

jshell> "El valor absoluto de $25 es " + Math.abs($25)
$29 ==> "El valor absoluto de $25 es 0.2"

Esto da como resultado una variable temporal que contiene el String… ¡Si te ha gustado, comparte!

Java Shell
  • Primeros pasos con JShell
Sending
User Review
5 (2 votes)

Sobre el Autor:

Hey hola! Yo soy Alex Walton y tengo el placer de compartir conocimientos hacía ti sobre el tema de Programación en Java, desde cero, Online y Gratis.

Deja una Respuesta

*

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.