{"id":335910,"date":"2023-03-24T12:16:02","date_gmt":"2023-03-24T11:16:02","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=335910"},"modified":"2023-03-24T12:16:05","modified_gmt":"2023-03-24T11:16:05","slug":"correspondencia-de-padroes-em-java-5-exemplos-para-desenvolvedores-ocupados","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/pt-br\/idea\/2023\/03\/correspondencia-de-padroes-em-java-5-exemplos-para-desenvolvedores-ocupados\/","title":{"rendered":"Correspond\u00eancia de padr\u00f5es em Java \u2014 5 exemplos para desenvolvedores ocupados"},"content":{"rendered":"<p>\u00c9 dif\u00edcil para um desenvolvedor ocupado acompanhar os novos recursos e compreender em profundidade onde e como se pode us\u00e1-los.<\/p>\n<p>Nesta postagem do blog, abordarei 5 lugares onde se pode usar correspond\u00eancia de padr\u00f5es no Java, sem me aprofundar nos detalhes mais espec\u00edficos. Quando voc\u00ea achar que j\u00e1 est\u00e1 pronto para explorar este assunto mais a fundo, confira os links inclu\u00eddos nesta postagem.<\/p>\n<p>Vamos come\u00e7ar!<\/p>\n<p>\u00a0<\/p>\n<h2>1. Melhore a legibilidade do c\u00f3digo convertendo longas constru\u00e7\u00f5es &#8220;if-else&#8221; para &#8220;switch&#8221;<\/h2>\n<p>Primeiro, vamos abordar a pergunta mais importante: por que se importar com esta convers\u00e3o?<\/p>\n<p>Um dos principais benef\u00edcios \u00e9 que o c\u00f3digo fica mais conciso e mais f\u00e1cil de ler e compreender. Como longas declara\u00e7\u00f5es &#8220;if-else&#8221; geralmente n\u00e3o cabem numa s\u00f3 tela e podem envolver rolagem vertical, \u00e9 dif\u00edcil compreender o c\u00f3digo executado para todas as compara\u00e7\u00f5es do &#8220;if&#8221;. Al\u00e9m disso, a sintaxe das condi\u00e7\u00f5es &#8220;if&#8221; pode ser obscura, porque cada condi\u00e7\u00e3o &#8220;if&#8221; pode conter outro conjunto de condi\u00e7\u00f5es.<\/p>\n<p>Ao navegar por uma base de c\u00f3digo, \u00e9 comum observar c\u00f3digo semelhante ao mostrado abaixo, de uma longa constru\u00e7\u00e3o &#8220;if-else&#8221; que atribui valores condicionalmente a uma vari\u00e1vel local. D\u00ea uma olhada no c\u00f3digo abaixo. Ajudarei voc\u00ea a navegar por ele real\u00e7ando algumas partes daqui a pouco:<\/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>Vamos real\u00e7ar o c\u00f3digo no qual devemos nos concentrar. Na imagem a seguir, observe que o m\u00e9todo <code>getValueText<\/code> verifica se o valor da vari\u00e1vel <code>value<\/code> \u00e9 de um certo tipo de dados, como <code>String<\/code>, <code>Character<\/code>, <code>Long<\/code>, <code>Double<\/code> ou outro:<\/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 compreendermos as outras partes desta constru\u00e7\u00e3o &#8220;if-else&#8221;, vamos nos concentrar na vari\u00e1vel <\/span><code>newExpression<\/code>. Observe que est\u00e1 sendo atribu\u00eddo um valor a esta vari\u00e1vel correspondendo a cada tipo poss\u00edvel da vari\u00e1vel <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;\">\u00c9 interessante notar que dois blocos correspondentes \u00e0s condi\u00e7\u00f5es &#8220;if&#8221; s\u00e3o mais longos que os outros, que geralmente cont\u00eam apenas uma linha 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 extrair estes dois blocos mais longos de c\u00f3digo, para separar os m\u00e9todos, e depois vamos proceder com a convers\u00e3o da constru\u00e7\u00e3o &#8220;if-else&#8221; em &#8220;switch&#8221;.<\/p>\n<p>Para extrair c\u00f3digo para outro m\u00e9todo, selecione o c\u00f3digo, invoque a\u00e7\u00f5es de contexto usando Alt+Enter (ou Option+Enter no macOS) e selecione a op\u00e7\u00e3o &#8220;Extract method&#8221;. Voc\u00ea pode escolher um dos nomes sugeridos para o novo m\u00e9todo ou digitar um nome da sua escolha. Para selecionar trechos l\u00f3gicos de c\u00f3digo, meu atalho favorito \u00e9 Ctrl+W (ou Ctrl+Shift+W para encolher a sele\u00e7\u00e3o). Depois da extra\u00e7\u00e3o do m\u00e9todo, siga as indica\u00e7\u00f5es do IntelliJ IDEA observando as palavras-chave com fundo amarelo e invocando a\u00e7\u00f5es de contexto (Alt+Enter). Para converter esta estrutura &#8220;if-else&#8221; para &#8220;switch&#8221;, invoque a\u00e7\u00f5es de contexto no &#8220;if&#8221; e selecione &#8220;Replace &#8216;if&#8217; with &#8216;switch&#8217; &#8220;:<\/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>Aqui est\u00e1 a constru\u00e7\u00e3o &#8220;switch&#8221; no m\u00e9todo <code>getValueText<\/code>, mais concisa e mais f\u00e1cil de compreender:<\/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>Isso faz voc\u00ea pensar por que voc\u00ea n\u00e3o usou express\u00f5es &#8220;switch&#8221; no seu c\u00f3digo tanto quanto constru\u00e7\u00f5es &#8220;if-else&#8221;? H\u00e1 v\u00e1rias raz\u00f5es para isso. A constru\u00e7\u00e3o &#8220;switch&#8221; foi aperfei\u00e7oada nas vers\u00f5es recentes do Java. Elas podem retornar valores (express\u00f5es &#8220;switch&#8221;) e n\u00e3o se limitam mais a comparar valores de um tipo primitivo e limitado de dados, classes &#8220;wrapper&#8221; e outras como <code>String<\/code> ou &#8220;enum&#8221;. Al\u00e9m disso, os valores declarados nas suas cl\u00e1usulas &#8220;case&#8221; tamb\u00e9m podem incluir padr\u00f5es e condi\u00e7\u00f5es.<\/p>\n<p>Com correspond\u00eancia de padr\u00f5es e &#8220;switch&#8221;, voc\u00ea tamb\u00e9m pode manipular valores nulos, usando &#8220;null&#8221; como condi\u00e7\u00e3o de um &#8220;case&#8221;. Al\u00e9m disso, cada valor declarado no &#8220;case&#8221; declara uma vari\u00e1vel de padr\u00e3o, n\u00e3o importando se \u00e9 usada ou n\u00e3o no bloco correspondente do c\u00f3digo. Se voc\u00ea estiver preocupado com a falta de cl\u00e1usulas break, saiba que elas n\u00e3o s\u00e3o necess\u00e1rias quando voc\u00ea usa os estilos de seta com &#8220;switch&#8221;.<\/p>\n<p>Por\u00e9m, este recurso ainda est\u00e1 em est\u00e1gio de demonstra\u00e7\u00e3o, o que significa que voc\u00ea n\u00e3o deve us\u00e1-lo no seu c\u00f3digo de produ\u00e7\u00e3o, pois poder\u00e1 mudar numa vers\u00e3o futura do Java. Visite <a href=\"https:\/\/blog.jetbrains.com\/idea\/2022\/11\/java-19-and-intellij-idea\/#IntelliJ_IDEA_Configuration\">este link<\/a> para verificar as configura\u00e7\u00f5es, se voc\u00ea n\u00e3o estiver familiarizado com elas.<\/p>\n<p><span style=\"font-weight: 400;\">Nem todas as declara\u00e7\u00f5es &#8220;if-else&#8221; podem ser convertidas em constru\u00e7\u00f5es com &#8220;switch&#8221;. Voc\u00ea pode usar as constru\u00e7\u00f5es &#8220;if-else&#8221; para definir condi\u00e7\u00f5es complexas, que talvez usem uma combina\u00e7\u00e3o de vari\u00e1veis, constantes e chamadas a m\u00e9todos. Essas compara\u00e7\u00f5es complexas ainda n\u00e3o t\u00eam suporte em constru\u00e7\u00f5es com &#8220;switch&#8221;.\u00a0<\/span><\/p>\n<p>Para ver uma abordagem detalhada da correspond\u00eancia de padr\u00f5es, confira <a href=\"https:\/\/blog.jetbrains.com\/idea\/2021\/09\/java-17-and-intellij-idea\/#What_is_pattern_matching\">esta postagem de blog<\/a>.<\/p>\n<h4>Execu\u00e7\u00e3o da inspe\u00e7\u00e3o \u201cif can be replaced with switch\u201d na sua base de c\u00f3digo<\/h4>\n<p>Pode ser demorado procurar constru\u00e7\u00f5es &#8220;if-else&#8221; no seu c\u00f3digo e verificar se elas podem ser substitu\u00eddas por &#8220;switch&#8221;. Voc\u00ea pode executar a inspe\u00e7\u00e3o &#8220;if can be replaced with switch&#8221; em todas as classes da sua base de c\u00f3digo ou em um subconjunto delas, como mostrado <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\">nesta postagem do blog<\/a>.<\/p>\n<p>Vamos trabalhar com nosso pr\u00f3ximo exemplo, que usa correspond\u00eancia de padr\u00f5es no &#8220;instanceof&#8221;. Este j\u00e1 \u00e9 um recurso de produ\u00e7\u00e3o em Java.<\/p>\n<h2>2. Escreva c\u00f3digo conciso usando correspond\u00eancia de padr\u00f5es com &#8220;instanceof&#8221;<\/h2>\n<p>A correspond\u00eancia de padr\u00f5es no operador <code>instanceof<\/code> j\u00e1 est\u00e1 dispon\u00edvel como recurso de produ\u00e7\u00e3o desde a vers\u00e3o 16 do Java e pode ser usada em c\u00f3digo de produ\u00e7\u00e3o.<\/p>\n<p>Para usar este recurso, apenas seguirei as indica\u00e7\u00f5es do IntelliJ IDEA e invocarei a\u00e7\u00f5es de contexto na palavra-chave <code>if<\/code>, que estar\u00e1 real\u00e7ada com um fundo amarelo.<\/p>\n<p>Imagine que voc\u00ea tenha uma classe, digamos, <code>Monitor<\/code>. Aqui est\u00e1 um dos exemplos comuns que voc\u00ea encontrar\u00e1 em v\u00e1rias bases de c\u00f3digo para implementar o 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>O GIF a seguir mostra como usar a correspond\u00eancia de padr\u00f5es invocando a\u00e7\u00f5es de contexto na vari\u00e1vel <code>other<\/code>, real\u00e7ada com fundo amarelo, e depois selecionando a op\u00e7\u00e3o &#8220;Replace &#8216;other&#8217; with pattern variable&#8221;. Esse c\u00f3digo pode ficar ainda mais conciso se o c\u00f3digo resultante for refatorado invocando a\u00e7\u00f5es de contexto na declara\u00e7\u00e3o &#8220;if&#8221;. O c\u00f3digo final \u00e9 mais f\u00e1cil de ler e compreender \u2013 ele retorna true se todas as tr\u00eas condi\u00e7\u00f5es mencionadas forem verdadeiras.<\/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>O que acontece se, em vez de uma classe normal, voc\u00ea estiver trabalhando com uma inst\u00e2ncia de Record? No caso de Records, a correspond\u00eancia de padr\u00f5es em &#8220;instanceof&#8221; pode desconstruir uma inst\u00e2ncia de Record definindo vari\u00e1veis de padr\u00e3o para os componentes do Record. No exemplo a seguir, <code>Citizen(String name, int age)<\/code> usado com o operador <code>instanceof<\/code> \u00e9 um padr\u00e3o 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>\u00c9 f\u00e1cil deixar de perceber o poder desses recursos quando se come\u00e7a com exemplos simples de c\u00f3digo, como os dois anteriores. Vamos dar uma olhada r\u00e1pida em outro exemplo do uso da correspond\u00eancia de padr\u00f5es com o operador &#8220;instanceof&#8221;, no qual remover a declara\u00e7\u00e3o de uma vari\u00e1vel local leva a outras possibilidades de refatora\u00e7\u00e3o ou aperfei\u00e7oamento. Em resumo, a combina\u00e7\u00e3o deste recurso com outras t\u00e9cnicas de refatora\u00e7\u00e3o ou aperfei\u00e7oamento de c\u00f3digo pode ajudar voc\u00ea a escrever c\u00f3digo melhor (basta seguir as indica\u00e7\u00f5es do 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. Ignore estados que n\u00e3o fazem sentido<\/h2>\n<p><span style=\"font-size: revert;\">Uma constru\u00e7\u00e3o &#8220;if-else&#8221; pode n\u00e3o ser a melhor escolha para iterar sobre os valores de um tipo com um conjunto completo de valores, como um &#8220;enum&#8221; ou os subtipos de uma classe selada. Por exemplo, imagine que voc\u00ea tenha um &#8220;enum&#8221; que defina um conjunto fixo de valores, como abaixo:<\/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;\">Embora voc\u00ea saiba que uma inst\u00e2ncia do tipo <code>SingleUsePlastic<\/code> pode ter qualquer um dentre tr\u00eas valores \u2014 ou seja, <code>BOTTLE<\/code>, <code>SPOON<\/code> e <code>CARRY_BAG<\/code> \u2014, o c\u00f3digo a seguir falharia na compila\u00e7\u00e3o para a vari\u00e1vel local final <code>replacement<\/code>:<\/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 fazer esse c\u00f3digo compilar, voc\u00ea precisar\u00e1 adicionar uma declara\u00e7\u00e3o &#8220;else&#8221; ao final, que n\u00e3o far\u00e1 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;\">Com uma constru\u00e7\u00e3o &#8220;switch&#8221;, voc\u00ea n\u00e3o precisa incluir uma cl\u00e1usula <code>default<\/code> para valores que n\u00e3o existem:<\/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>De forma semelhante, se voc\u00ea definir uma classe selada, voc\u00ea poder\u00e1 usar uma constru\u00e7\u00e3o &#8220;switch&#8221; para iterar sobre sua lista completa de subclasses sem definir uma cl\u00e1usula &#8220;default&#8221;:<\/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>Se voc\u00ea n\u00e3o estiver familiarizado com classes seladas e desejar mergulhar a fundo nesse t\u00f3pico, acesse <a href=\"https:\/\/blog.jetbrains.com\/idea\/2021\/09\/java-17-and-intellij-idea\/#Need_for_creating_restricted_hierarchies\">esta postagem do blog<\/a>.<\/p>\n<h2>4. Processamento poderoso e conciso de dados<\/h2>\n<p>Voc\u00ea pode criar um c\u00f3digo poderoso, mas conciso e expressivo, para processar os seus dados, usando uma combina\u00e7\u00e3o de padr\u00f5es Record, express\u00f5es &#8220;switch&#8221; e classes seladas. Aqui est\u00e1 um exemplo de uma interface selada <code>TwoDimensional<\/code>, que \u00e9 implementada pelos Records <code>Point<\/code>, <code>Line<\/code>, <code>Triangle<\/code> e <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>O m\u00e9todo a seguir define um processo de m\u00e9todo recursivo que usa uma constru\u00e7\u00e3o &#8220;switch&#8221; para retornar a soma das coordenadas x e y de todos os pontos de uma figura bidimensional, como <code>Line<\/code>, <code>Triangle<\/code> ou <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>O IntelliJ IDEA tamb\u00e9m mostra o \u00edcone de chamada recursiva para este m\u00e9todo na medianiz:<\/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. Separa\u00e7\u00e3o entre computa\u00e7\u00e3o e efeitos colaterais<\/h2>\n<p>\u00c9 comum encontrar c\u00f3digo que combina uma computa\u00e7\u00e3o e um efeito colateral (como imprimir em um console) no mesmo bloco de c\u00f3digo. Por exemplo, o c\u00f3digo a seguir usa um bloco &#8220;if-else&#8221; e um operador <code>instanceof<\/code> para determinar o tipo de uma vari\u00e1vel e depois imprime um valor condicional em cada bloco de c\u00f3digo.<\/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>O GIF a seguir mostra como converter aquele bloco &#8220;if-else&#8221; em uma constru\u00e7\u00e3o &#8220;switch&#8221; e depois usar uma nova inspe\u00e7\u00e3o no &#8220;switch&#8221; \u2014 &#8220;Push down \u2018switch\u2019 expression&#8221; \u2014, seguida da extra\u00e7\u00e3o de uma vari\u00e1vel para separar a computa\u00e7\u00e3o dos seus efeitos colaterais:<\/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>Resumo<\/h2>\n<p>Nesta postagem de blog, abordamos 5 situa\u00e7\u00f5es em que desenvolvedores ocupados podem usar a correspond\u00eancia de padr\u00f5es no Java. Se voc\u00ea tiver interesse em aprender mais sobre estes recursos ou sobre como o IntelliJ IDEA ajuda voc\u00ea a us\u00e1-los, consulte os links que inclu\u00ed ao abordar estes exemplos.<\/p>\n<p>Diga para mim quais outros t\u00f3picos voc\u00ea gostaria que eu abordasse na minha pr\u00f3xima postagem no blog.<\/p>\n<p>At\u00e9 l\u00e1, boa programa\u00e7\u00e3o!<\/p>\n<p><em>Artigo original em ingl\u00eas por:<\/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\/pt-br\/wp-json\/wp\/v2\/idea\/335910"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/users\/1086"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/comments?post=335910"}],"version-history":[{"count":4,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea\/335910\/revisions"}],"predecessor-version":[{"id":335947,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea\/335910\/revisions\/335947"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media\/320082"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media?parent=335910"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/categories?post=335910"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/tags?post=335910"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/cross-post-tag?post=335910"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}