{"id":335948,"date":"2023-03-24T12:18:16","date_gmt":"2023-03-24T11:18:16","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=335948"},"modified":"2023-03-24T12:18:20","modified_gmt":"2023-03-24T11:18:20","slug":"concordancia-de-patrones-en-java-cinco-ejemplos-para-desarrolladores-con-poco-tiempo-libre","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/es\/idea\/2023\/03\/concordancia-de-patrones-en-java-cinco-ejemplos-para-desarrolladores-con-poco-tiempo-libre\/","title":{"rendered":"Concordancia de patrones en Java: cinco ejemplos para desarrolladores con poco tiempo libre"},"content":{"rendered":"<p>Dado que sabemos que tiene poco tiempo libre, no siempre es f\u00e1cil estar al d\u00eda de las nuevas funcionalidades y entender bien d\u00f3nde y c\u00f3mo se pueden utilizar.<\/p>\n<p>En este art\u00edculo del blog, repasaremos cinco entornos en los que utilizar la concordancia de patrones en Java sin entrar en demasiados detalles. Cuando tenga un rato, eche un vistazo a los enlaces que encontrar\u00e1 a lo largo de este art\u00edculo.<\/p>\n<p>\u00a1Vamos all\u00e1!<\/p>\n<p>\u00a0<\/p>\n<h2>1. Mejorar la legibilidad del c\u00f3digo convirtiendo las construcciones largas \u00abif-else\u00bb en expresiones \u00abswitch\u00bb<\/h2>\n<p>En primer lugar, una pregunta clave: \u00bfpor qu\u00e9 es importante esta conversi\u00f3n?<\/p>\n<p>Una de las principales ventajas es que el c\u00f3digo ser\u00e1 m\u00e1s conciso y f\u00e1cil de leer y entender. Dado que, normalmente, las declaraciones largas \u00abif-else\u00bb no caben en una sola pantalla y es posible que tenga que desplazarse de forma vertical, no siempre es f\u00e1cil entender el c\u00f3digo que se ejecuta para todas las comparaciones \u00abif\u00bb. Adem\u00e1s, la sintaxis de las condiciones \u00abif\u00bb puede ser poco clara, porque cada una de ellas podr\u00eda estar formada por otro conjunto de condiciones.<\/p>\n<p>A menudo, al navegar por una base de c\u00f3digo, observamos c\u00f3digo similar al que se muestra a continuaci\u00f3n para una construcci\u00f3n \u00abif-else\u00bb larga, que asigna un valor a una variable local de forma condicional. Eche un vistazo al c\u00f3digo de la siguiente imagen. Le ayudaremos a navegar por este resaltando ciertas secciones un poco m\u00e1s adelante:<\/p>\n<p>\u00a0<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">    \nprivate static String getValueText(Object value) {\n    final String newExpression;\n    if (value instanceof String) {\n        final String string = (String)value;\n        newExpression = '\"' + StringUtil.escapeStringCharacters(string) + '\"';\n    }\n    else if (value instanceof Character) {\n        newExpression = ''' + StringUtil.escapeStringCharacters(value.toString()) + ''';\n    }\n    else if (value instanceof Long) {\n        newExpression = value.toString() + 'L';\n    }\n    else if (value instanceof Double) {\n        final double v = (Double)value;\n        if (Double.isNaN(v)) {\n            newExpression = \"java.lang.Double.NaN\";\n        }\n        else if (Double.isInfinite(v)) {\n            if (v &gt; 0.0) {\n                newExpression = \"java.lang.Double.POSITIVE_INFINITY\";\n            }\n            else {\n                newExpression = \"java.lang.Double.NEGATIVE_INFINITY\";\n            }\n        }\n        else {\n            newExpression = Double.toString(v);\n        }\n    }\n    else if (value instanceof Float) {\n        final float v = (Float) value;\n        if (Float.isNaN(v)) {\n            newExpression = \"java.lang.Float.NaN\";\n        }\n        else if (Float.isInfinite(v)) {\n            if (v &gt; 0.0F) {\n                newExpression = \"java.lang.Float.POSITIVE_INFINITY\";\n            }\n            else {\n                newExpression = \"java.lang.Float.NEGATIVE_INFINITY\";\n            }\n        }\n        else {\n            newExpression = Float.toString(v) + 'f';\n        }\n    }\n    else if (value == null) {\n        newExpression = \"null\";\n    }\n    else {\n        newExpression = String.valueOf(value);\n    }\n    return newExpression;\n}\n<\/pre>\n<p>Resaltemos el c\u00f3digo que nos interesa. En la siguiente imagen, ver\u00e1 que el m\u00e9todo <code>getValueText<\/code> compara si el valor de la variable <code>value<\/code> es de un determinado tipo de datos, como <code>String<\/code>, <code>Character<\/code>, <code>Long<\/code>, <code>Double<\/code> u otro:<\/p>\n<p>\u00a0<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/long-if-else-1.png\" alt=\"\" \/><\/figure>\n<p>\u00a0<\/p>\n<p><span style=\"font-weight: 400;\">Para entender las otras partes de esta construcci\u00f3n \u00abif-else\u00bb, nos centraremos en la variable <\/span><code>newExpression<\/code>. Observe que a esta variable se le est\u00e1 asignando un valor para todos los valores posibles de la variable <code>value<\/code>:<\/p>\n<p>\u00a0<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/long-if-else-2.png\" alt=\"\" \/><\/figure>\n<p>\u00a0<\/p>\n<p><span style=\"font-weight: 400;\">Curiosamente, salvo dos, el resto de bloques de c\u00f3digo correspondientes a las condiciones \u00abif\u00bb son m\u00e1s largos que los dem\u00e1s, que suelen tener solo una l\u00ednea de c\u00f3digo:<\/span><\/p>\n<p>\u00a0<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/long-if-else-3.png\" alt=\"\" \/><\/figure>\n<p>\u00a0<\/p>\n<p>Vamos a extraer estos dos bloques de c\u00f3digo m\u00e1s largos en m\u00e9todos separados y, despu\u00e9s, convertiremos la construcci\u00f3n \u00abif-else\u00bb en una expresi\u00f3n \u00abswitch\u00bb.<\/p>\n<p>Para extraer c\u00f3digo a otro m\u00e9todo, seleccione el c\u00f3digo, invoque las acciones contextuales con Alt+Intro(Opci\u00f3n+Intro para macOS) y seleccione la opci\u00f3n \u00abExtract method\u00bb. Puede elegir uno de los nombres sugeridos para el nuevo m\u00e9todo o ponerle uno nuevo. Para seleccionar fragmentos l\u00f3gicos de c\u00f3digo, le recomendamos el atajo Ctrl+W (o Ctrl+May\u00fas+W para reducir la selecci\u00f3n). Tras extraer el m\u00e9todo, siga las indicaciones de IntelliJ IDEA fij\u00e1ndose en las palabras clave resaltadas en amarillo e invoque las acciones contextuales (Alt+Intro). Para convertir este \u00abif-else\u00bb en \u00abswitch\u00bb, hemos invocado las acciones contextuales sobre \u00abif\u00bb y seleccionado \u00abReplace &#8216;if&#8217; with &#8216;switch&#8217;\u00bb:<\/p>\n<p>\u00a0<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/1.gif\" alt=\"\" \/><\/figure>\n<p>\u00a0<\/p>\n<p>Esta es la construcci\u00f3n \u00abswitch\u00bb en el m\u00e9todo <code>getValueText<\/code>, que es concisa y m\u00e1s f\u00e1cil de entender:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">private static String getValueText(Object value) {\n    final String newExpression = switch (value) {\n        case String string -&gt; '\"' + StringUtil.escapeStringCharacters(string) + '\"';\n        case Character character -&gt; ''' + StringUtil.escapeStringCharacters(value.toString()) + ''';\n        case Long aLong -&gt; value.toString() + 'L';\n        case Double aDouble -&gt; getNewExpression(aDouble);\n        case Float aFloat -&gt; getNewExpression(aFloat);\n        case null -&gt; \"null\";\n        default -&gt; String.valueOf(value);\n    };\n    return newExpression;\n}\n<\/pre>\n<p>Llegados a este punto, quiz\u00e1s se est\u00e9 preguntando por qu\u00e9 no utiliza las expresiones \u00abswitch\u00bb tan a menudo en su c\u00f3digo como las construcciones \u00abif-else\u00bb. Los motivos son diversos. En las \u00faltimas versiones de Java, se ha mejorado la expresi\u00f3n \u00abswitch\u00bb, que ahora puede devolver valores (expresiones \u00abswitch\u00bb) y ya no se limita a comparar valores para un tipo de datos primitivo limitado, clases \u00abwrapper\u00bb y otros elementos como <code>String<\/code> o enumeraciones. Adem\u00e1s, las etiquetas \u00abcase\u00bb pueden incluir patrones y condiciones.<\/p>\n<p>Con la concordancia de patrones y \u00abswitch\u00bb, tambi\u00e9n es posible manejar valores nulos utilizando \u00abnull\u00bb como etiqueta \u00abcase\u00bb. Adem\u00e1s, cada etiqueta \u00abcase\u00bb declara una variable de patr\u00f3n, tanto si se utilizan en el bloque de c\u00f3digo correspondiente como si no. En cuanto a las etiquetas \u00abbreak\u00bb que faltan, no son necesarias cuando se utilizan los estilos de flecha con \u00abswitch\u00bb.<\/p>\n<p>Sin embargo, la versi\u00f3n de esta funcionalidad todav\u00eda es preliminar, por lo que no deber\u00eda utilizarla en el c\u00f3digo de producci\u00f3n, ya que podr\u00eda cambiar en las versiones posteriores de Java. Visite <a href=\"https:\/\/blog.jetbrains.com\/idea\/2022\/11\/java-19-and-intellij-idea\/#IntelliJ_IDEA_Configuration\">este enlace<\/a> para comprobar la configuraci\u00f3n si no est\u00e1 familiarizado con esta.<\/p>\n<p><span style=\"font-weight: 400;\">No todas las declaraciones \u00abif-else\u00bb pueden convertirse en construcciones \u00abswitch\u00bb. Puede utilizar las construcciones \u00abif-else\u00bb para definir condiciones complejas que podr\u00edan utilizar una combinaci\u00f3n de variables, constantes o llamadas a m\u00e9todos. Este tipo de comparaciones complejas a\u00fan no son compatibles con las construcciones \u00abswitch\u00bb.\u00a0<\/span><\/p>\n<p>Para obtener m\u00e1s informaci\u00f3n acerca de la concordancia de patrones, consulte <a href=\"https:\/\/blog.jetbrains.com\/idea\/2021\/09\/java-17-and-intellij-idea\/#What_is_pattern_matching\">este art\u00edculo del blog<\/a>.<\/p>\n<h4>Ejecutar la inspecci\u00f3n \u00abif can be replaced with switch\u00bb en el c\u00f3digo base<\/h4>\n<p>Buscar construcciones \u00abif-else\u00bb en el c\u00f3digo y comprobar si pueden sustituirse por \u00abswitch\u00bb lleva tiempo. As\u00ed pues, puede ejecutar la inspecci\u00f3n \u00abif can be replaced with switch\u00bb en todas las clases del c\u00f3digo base o en su subconjunto, tal como se explica en <a href=\"https:\/\/blog.jetbrains.com\/idea\/2021\/09\/java-17-and-intellij-idea\/#Running_the_if_can_be_replaced_with_switch_inspection_on_your_code_base\">este art\u00edculo del blog<\/a>.<\/p>\n<p>Ahora nos centraremos en el siguiente ejemplo, que utiliza la concordancia de patrones para \u00abinstanceof\u00bb, una funcionalidad de producci\u00f3n en Java.<\/p>\n<h2>2. Escribir c\u00f3digo conciso utilizando la concordancia de patrones con \u00abinstanceof\u00bb<\/h2>\n<p>El uso de la concordancia de patrones para el operador <code>instanceof<\/code> ha estado disponible como una funcionalidad de producci\u00f3n desde la versi\u00f3n 16 de Java y se puede utilizar en c\u00f3digo de producci\u00f3n.<\/p>\n<p>Para utilizar esta funci\u00f3n, seguiremos el ejemplo de IntelliJ IDEA e invocaremos las acciones contextuales sobre la palabra clave <code>if<\/code>,\u00a0que aparece resaltada en amarillo.<\/p>\n<p>Imagine que tiene una clase llamada <code>Monitor<\/code>. Este es uno de los muchos ejemplos que encontrar\u00e1 en bases de c\u00f3digo para implementar su m\u00e9todo <code>equals<\/code>:<\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class Monitor {\n    String model;\n    double price;\n\n    @Override\n    public boolean equals(Object object) {\n        if (object instanceof Monitor) {\n            Monitor other = (Monitor) object;\n            return model.equals(other.model) &amp;&amp; price == other.price;\n        }\n        return false;\n    }\n}\n<\/pre>\n<p>El siguiente gif muestra c\u00f3mo utilizar la concordancia de patrones invocando acciones contextuales sobre la variable llamada <code>other<\/code>, resaltada en amarillo, y seleccionando la opci\u00f3n \u00abReplace &#8216;other&#8217; with pattern variable\u00bb. Refactorizar el c\u00f3digo resultante invocando acciones contextuales sobre la sentencia \u00abif\u00bb puede hacer que este c\u00f3digo sea a\u00fan m\u00e1s conciso. El c\u00f3digo final es m\u00e1s f\u00e1cil de leer y entender, ya que devuelve \u00abtrue\u00bb si las tres condiciones mencionadas son verdaderas.<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/2.gif\" alt=\"\" \/><\/figure>\n<\/div>\n<p>\u00bfQu\u00e9 ocurre si, en lugar de una clase normal, trabaja con una instancia de Record? En el caso de Record, la concordancia de patrones para \u00abinstanceof\u00bb puede deconstruir una instancia de Record definiendo variables de patr\u00f3n para los componentes de Record. En el siguiente ejemplo, el uso de <code>Citizen(String name, int age)<\/code> con el operador <code>instanceof<\/code> es un patr\u00f3n Record:<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/4.gif\" alt=\"\" \/><\/figure>\n<p>\u00a0<\/p>\n<p>Es f\u00e1cil no reparar en el potencial de estas funcionalidades si nos limitamos a mostrar ejemplos de c\u00f3digo sencillos como los dos anteriores. Veamos r\u00e1pidamente otro ejemplo de uso de la concordancia de patrones con el operador \u00abinstanceof\u00bb, en el que la eliminaci\u00f3n de la declaraci\u00f3n de una variable local abre otras posibilidades de refactorizaci\u00f3n o mejora. En resumen, combinar esta funci\u00f3n con otras t\u00e9cnicas de refactorizaci\u00f3n o mejora del c\u00f3digo le ayudar\u00e1 a escribir mejor c\u00f3digo (\u00a1solo tiene que seguir las indicaciones de IntelliJ IDEA!):<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/3.gif\" alt=\"\" \/><\/figure>\n<p>\u00a0<\/p>\n<h2>3. Ignorar los estados que no tienen sentido<\/h2>\n<p><span style=\"font-size: revert;\">Una construcci\u00f3n \u00abif-else\u00bb puede no ser la mejor opci\u00f3n para iterar sobre los valores de un tipo que tiene un conjunto exhaustivo de valores, como las enumeraciones o los subtipos de una clase sellada. Por ejemplo, imagine que tiene una enumeraci\u00f3n que define un conjunto fijo de valores, como el siguiente:<\/span><\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">enum SingleUsePlastic {\n    BOTTLE, SPOON, CARRY_BAG;\n}<\/pre>\n<p><span style=\"font-size: revert;\">Aunque sepa que una instancia del tipo <code>SingleUsePlastic<\/code> puede tener cualquiera de los tres valores, es decir, <code>BOTTLE<\/code>, <code>SPOON<\/code> y <code>CARRY_BAG<\/code>, la variable local final <code>replacement<\/code> no compilar\u00eda el siguiente c\u00f3digo:<\/span><\/p>\n<\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class Citizen {\n    String getReplacements(SingleUsePlastic plastic) {\n        final String replacement;\n        if (plastic == SingleUsePlastic.BOTTLE) {\n            replacement = \"Booth 4: Pick up a glass bottle\";\n        } else if (plastic == SingleUsePlastic.SPOON) {\n            replacement = \"Pantry: Pick up a steel spoon\";\n        } else if (plastic == SingleUsePlastic.CARRY_BAG) {\n            replacement = \"Booth 5: Pick up a cloth bag\";\n        } \n        return replacement;\n    }\n}<\/pre>\n<p><span style=\"font-size: revert;\">Para que se compile, tendr\u00e1 que a\u00f1adir al final una cl\u00e1usula \u00abelse\u00bb que no tenga sentido.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class Citizen {\n    String getReplacements(SingleUsePlastic plastic) {\n        final String replacement;\n        if (plastic == SingleUsePlastic.BOTTLE) {\n            replacement = \"Booth 4: Pick up a glass bottle\";\n        } else if (plastic == SingleUsePlastic.SPOON) {\n            replacement = \"Pantry: Pick up a steel spoon\";\n        } else if (plastic == SingleUsePlastic.CARRY_BAG) {\n            replacement = \"Booth 5: Pick up a cloth bag\";\n        } else {\n            replacement = \"\";\n        }\n        return replacement;\n    }\n}<\/pre>\n<p><span style=\"font-size: revert;\">Con una construcci\u00f3n \u00abswitch\u00bb, no es necesario codificar una parte \u00abdefault\u00bb para valores que no existen:<\/span><\/p>\n<\/div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class Citizen {\n    String getReplacements(SingleUsePlastic plastic) {\n        final String replacement = switch (plastic) {\n            case BOTTLE -&gt; \"Booth 4: Pick up a glass bottle\";\n            case SPOON -&gt; \"Pantry: Pick up a steel spoon\";\n            case CARRY_BAG -&gt; \"Booth 5: Pick up a cloth bag\";\n        };\n        return replacement;\n    }\n}<\/pre>\n<p>Del mismo modo, si define una clase sellada, puede utilizar una construcci\u00f3n \u00abswitch\u00bb para iterar sobre su lista exhaustiva de subclases sin definir una cl\u00e1usula \u00abdefault\u00bb:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">sealed interface Lego {}\nfinal class SquareLego implements Lego {}\nnon-sealed class RectangleLogo implements Lego {}\nsealed class CharacterLego implements Lego permits PandaLego {}\nfinal class PandaLego extends CharacterLego {}\n\npublic class MyLegoGame {\n    int processLego(Lego lego) {\n        return switch (lego) {\n            case SquareLego squareLego -&gt; 100;\n            case RectangleLego rectangleLego-&gt; 200;\n            case CharacterLego characterLego -&gt; 300;\n        };\n    }\n}<\/pre>\n<p>Si no est\u00e1 familiarizado con las clases selladas y quiere obtener m\u00e1s informaci\u00f3n al respecto, <a href=\"https:\/\/blog.jetbrains.com\/idea\/2021\/09\/java-17-and-intellij-idea\/#Need_for_creating_restricted_hierarchies\">este art\u00edculo del blog<\/a> le ser\u00e1 de gran ayuda.<\/p>\n<h2>4. Procesamiento de datos potente y conciso<\/h2>\n<p>Puede crear c\u00f3digo potente, pero conciso y expresivo al mismo tiempo, para procesar los datos utilizando una combinaci\u00f3n de patrones Record, expresiones \u00abswitch\u00bb y clases selladas. Aqu\u00ed tiene un ejemplo de una interfaz sellada <code>TwoDimensional<\/code>, que se implementa con los Records <code>Point<\/code>, <code>Line<\/code>, <code>Triangle<\/code> y <code>Square<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">sealed interface TwoDimensional {}\nrecord Point    (int x, \n                 int y) implements TwoDimensional { }\nrecord Line     (Point start, \n                 Point end) implements TwoDimensional { }\nrecord Triangle (Point pointA, \n                 Point pointB, \n\t\t\t\t Point PointC) implements TwoDimensional { }\nrecord Square   (Point pointA, \n                 Point pointB, \n\t\t\t     Point PointC, \n\t\t\t     Point pointD) implements TwoDimensional { }\n<\/pre>\n<p>El siguiente m\u00e9todo define un proceso de m\u00e9todo recursivo que utiliza una construcci\u00f3n \u00abswitch\u00bb para devolver la suma de las coordenadas x e y de todos los puntos de una figura bidimensional, como en el caso de <code>Line<\/code>, <code>Triangle<\/code> o <code>Square<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">static int process(TwoDimensional twoDim) {\n    return switch (twoDim) {\n        case Point(int x, int y) -&gt; x + y;\n        case Line(Point a, Point b) -&gt; process(a) + process(b);\n        case Triangle(Point a, Point b, Point c) -&gt; process(a) + process(b) + process(c);\n        case Square(Point a, Point b, Point c, Point d) -&gt; process(a) + process(b) + process(c) + process(d);\n    };\n}\n<\/pre>\n<p>IntelliJ IDEA tambi\u00e9n muestra el icono de llamada recursiva en el medianil para este m\u00e9todo:<\/p>\n<p>\u00a0<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/recursion.png\" alt=\"\" \/><\/figure>\n<p>\u00a0<\/p>\n<h2>5. Separaci\u00f3n de c\u00e1lculo y efecto secundario<\/h2>\n<p>No es extra\u00f1o encontrarse con c\u00f3digo que combine un c\u00e1lculo y un efecto secundario (como imprimir en la consola) en el mismo bloque de c\u00f3digo. Por ejemplo, el siguiente c\u00f3digo utiliza un bloque \u00abif-else\u00bb y el operador <code>instanceof<\/code> para determinar el tipo de una variable y devuelve un valor condicional en cada bloque de c\u00f3digo \u00abif\u00bb.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void printObject(Object obj) {\n    if (obj instanceof String s) {\n        System.out.println(\"String: \"\" + s + \"\"\");\n    } else if (obj instanceof Collection&lt;?&gt; c) {\n        System.out.println(\"Collection (size = \" + c.size() + \")\");\n    } else {\n        System.out.println(\"Other object: \" + obj);\n    }\n}\n<\/pre>\n<p>El siguiente gif muestra c\u00f3mo se puede convertir este bloque \u00abif-else\u00bb en una construcci\u00f3n \u00abswitch\u00bb y, despu\u00e9s, utilizar una nueva inspecci\u00f3n en \u00abswitch\u00bb (\u00abPush down &#8216;switch&#8217; expression\u00bb), seguida de la extracci\u00f3n de una variable para separar el c\u00e1lculo y sus efectos secundarios:<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/5-1.gif\" alt=\"\" \/><\/figure>\n<p>\u00a0<\/p>\n<h2>Resumen<\/h2>\n<p>En este art\u00edculo del blog, hemos presentado cinco entornos en los que los desarrolladores con poco tiempo libre pueden utilizar la concordancia de patrones en Java. Si quiere obtener m\u00e1s informaci\u00f3n acerca de estas funcionalidades o c\u00f3mo ayuda IntelliJ IDEA a usarlas, consulte los enlaces que hemos incluido en los ejemplos.<\/p>\n<p>D\u00edganos sobre qu\u00e9 otros temas le gustar\u00eda leer en el pr\u00f3ximo art\u00edculo del blog.<\/p>\n<p>Hasta entonces, \u00a1feliz programaci\u00f3n!<\/p>\n<p><em>Art\u00edculo original en ingl\u00e9s de<\/em><\/p>\n\n    <div class=\"about-author \">\n        <div class=\"about-author__box\">\n            <div class=\"row\">\n                <div class=\"about-author__box-img\">\n                    <img decoding=\"async\" src=\"https:\/\/secure.gravatar.com\/avatar\/?s=200&#038;r=g\" width=\"200\" height=\"200\" alt=\"\" loading=\"lazy\"  class=\"avatar avatar-200 wp-user-avatar wp-user-avatar-200 photo avatar-default\">\n                <\/div>\n                <div class=\"about-author__box-text\">\n                                                        <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n","protected":false},"author":1086,"featured_media":320082,"comment_status":"closed","ping_status":"closed","template":"","categories":[4759,5088],"tags":[40,155],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/idea\/335948"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/users\/1086"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/comments?post=335948"}],"version-history":[{"count":6,"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/idea\/335948\/revisions"}],"predecessor-version":[{"id":335955,"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/idea\/335948\/revisions\/335955"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/media\/320082"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/media?parent=335948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/categories?post=335948"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/tags?post=335948"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/es\/wp-json\/wp\/v2\/cross-post-tag?post=335948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}