<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maximillian Arruda</title>
    <description>The latest articles on DEV Community by Maximillian Arruda (@dearrudam).</description>
    <link>https://dev.to/dearrudam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F467014%2F68b39c4a-55b4-4bf0-bee6-409281c8f061.jpg</url>
      <title>DEV Community: Maximillian Arruda</title>
      <link>https://dev.to/dearrudam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dearrudam"/>
    <language>en</language>
    <item>
      <title>Facilite a vida de quem utiliza seus códigos: construindo Builders inteligentes</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Mon, 06 Jan 2025 12:30:00 +0000</pubDate>
      <link>https://dev.to/dearrudam/facilite-a-vida-dos-desenvolvedores-implementando-construtores-de-objetos-inteligentes-1l2b</link>
      <guid>https://dev.to/dearrudam/facilite-a-vida-dos-desenvolvedores-implementando-construtores-de-objetos-inteligentes-1l2b</guid>
      <description>&lt;p&gt;Costumamos a ouvir "Facilite a vida do seu cliente". Mas, e quanto aos desenvolvedores que vão trabalhar com o código que você escreve? Com certeza é importante facilitar a vida deles também.&lt;/p&gt;

&lt;p&gt;Independente do cliente alvo da sua solução, você estará criando código que será mantido por outros desenvolvedores incluindo você também muitas vezes. Escolher boas abordagens e técnicas irá facilitar a vida deles ou a sua vida provavelmente. Ser um desenvolvedor eficaz não é apenas sobre escrever código que funcione, mas também sobre escrever código que seja fácil de ler, de entender e de manter.&lt;/p&gt;

&lt;p&gt;O tema sobre boas práticas e técnicas é muito extenso e, eu não estou aqui para dizer o que você deve ou não fazer. Eu acredito que a melhor abordagem depende do contexto.&lt;/p&gt;

&lt;p&gt;Neste conteúdo, vamos discutir como facilitar a vida dos desenvolvedores usando boas estratégias para construir objetos complexos.&lt;/p&gt;

&lt;h3&gt;
  
  
  O cenário: O objeto complexo
&lt;/h3&gt;

&lt;p&gt;Uma boa maneira de aprender coisas é através de exemplos. Então, aqui está o nosso desafio:&lt;/p&gt;

&lt;p&gt;Precisamos criar um objeto &lt;code&gt;Notification&lt;/code&gt; que tenha os seguintes atributos obrigatórios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt;: o título da notificação;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message&lt;/code&gt;: o conteúdo da notificação;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;recipient&lt;/code&gt;: a pessoa que receberá a notificação;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;e os atributos opcionais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;highPriority&lt;/code&gt;: uma flag para indicar se a notificação é de alta prioridade. O padrão é &lt;code&gt;false&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;: o tipo da notificação. Uma enumeração com os seguintes valores suportados: &lt;code&gt;GENERAL&lt;/code&gt;, &lt;code&gt;INFO&lt;/code&gt;, &lt;code&gt;WARNING&lt;/code&gt;, &lt;code&gt;ERROR&lt;/code&gt;. O padrão é &lt;code&gt;Type.GENERAL&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;attachment&lt;/code&gt;: um texto com o caminho para o arquivo de anexo. O padrão é &lt;code&gt;null&lt;/code&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Abaixo, segue mais requisitos que precisamos atender:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt;: é obrigatório e não pode ser nulo;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message&lt;/code&gt;: é obrigatório e não pode ser nulo;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;recipient&lt;/code&gt;: é obrigatório e não pode ser nulo;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;highPriority&lt;/code&gt;: é opcional, mas não pode ser nulo;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;: é opcional, mas não pode ser nulo;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Temos aqui uma inicial definição para nossa classe &lt;code&gt;Notification&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isHighPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// omitted getters&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alguns desenvolvedores poderiam argumentar: &lt;em&gt;"Podemos usar o construtor padrão e os setters para definir os atributos opcionais"&lt;/em&gt;. Bom, vamos tentar seguir este argumento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Optional&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setRecipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getRecipient&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setHighPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isHighPriority&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getType&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setAttachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt;  &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getAttachment&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// omitted hash and equals methods &lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Analisando o código acima, podemos ver que o desenvolvedor deve chamar os setters para definir os atributos. O código para criar um objeto &lt;code&gt;Notification&lt;/code&gt; provavelmente seria assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"New message"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setRecipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setHighPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAttachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/path/to/attachment.txt"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código acima, podemos destacar algumas desvantagens e problemas com essa abordagem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Objetos &lt;code&gt;Notification&lt;/code&gt; podem ser instanciados com estado inválido&lt;/strong&gt;: as restrições do nosso desafio estão sendo violadas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Objetos &lt;code&gt;Notification&lt;/code&gt; não são thread-safe&lt;/strong&gt;: os setters podem ser chamados por múltiplas threads ao mesmo tempo, causando problemas de condições de corrida (race conditions), um problema muito comum que podem ocorrer em aplicações multithreaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Os desenvolvedores devem chamar os setters para definir tanto os atributos obrigatórios quanto os opcionais&lt;/strong&gt;: é um processo um tanto verboso e &lt;strong&gt;propenso a erros&lt;/strong&gt; porque o desenvolvedor pode esquecer de definir algum de seus atributos, fazendo com que o objeto entre em um estado inválido;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Não está claro como o objeto deve ser criado&lt;/strong&gt;: o desenvolvedor deverá ler a documentação para saber quais atributos são obrigatórios e quais são opcionais para assim poder defini-los;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mas também, podemos destacar algumas coisas boas nesta abordagem: &lt;strong&gt;os desenvolvedores podem chamar os setters dos atributos opcionais conforme necessário, dando muita flexibilidade na utilização&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Dados os problemas acima, vamos tentar endereçá-los:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Objetos &lt;code&gt;Notification&lt;/code&gt; podem ser instanciados com estado inválido&lt;/strong&gt;: as restrições do nosso desafio estão sendo violadas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Okay, você poderia dizer: "&lt;em&gt;Não é um grande problema! Podemos usar o construtor para definir os atributos obrigatórios e os setters para definir os atributos opcionais&lt;/em&gt;". Vamos tentar seguir este argumento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;setTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;setMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;setRecipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setRecipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getRecipient&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setHighPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isHighPriority&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getType&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setAttachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt;  &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getAttachment&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// omitted hash and equals methods &lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos atualizar o &lt;code&gt;NotificationProgram&lt;/code&gt; que cria um objeto &lt;code&gt;Notification&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"New message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setHighPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAttachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/path/to/attachment.txt"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aparentemente resolvemos o primeiro problema, certo? Bem, vamos analisar o código novamente:&lt;/p&gt;

&lt;p&gt;Com as mudanças os objetos &lt;code&gt;Notification&lt;/code&gt; serão instanciados com referências não nulas para os atributos obrigatórios. Mas, ainda temos alguns problemas: &lt;strong&gt;o construtor &lt;code&gt;Notification&lt;/code&gt; com todos os atributos obrigatórios é propenso a erros!&lt;/strong&gt; Agora, os desenvolvedores podem definir os atributos na ordem errada. Por exemplo, o desenvolvedor pode definir o &lt;code&gt;recipient&lt;/code&gt; antes do &lt;code&gt;title&lt;/code&gt;, o que invalida o estado do objeto fazendo com que os campos contenham o valor errado. Tal problema só poderá ser detectado em um processo de depuração ou analisando a saída derivada desses objetos &lt;code&gt;Notification&lt;/code&gt; inválidos.&lt;/p&gt;

&lt;p&gt;Talvez dois ou três argumentos com o mesmo tipo não seja um grande problema, mas na perspectiva dos desenvolvedores que irão usar nossa classe, não é algo fácil de lidar, e se tivermos mais atributos? O construtor se tornará ainda mais complexo e propenso a erros.&lt;/p&gt;

&lt;p&gt;Vamos continuar, mas agora tentando resolver o segundo problema:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Objetos &lt;code&gt;Notification&lt;/code&gt; não são thread-safe&lt;/strong&gt;: os setters podem ser chamados por múltiplas threads ao mesmo tempo, causando problemas de condições de corrida (race conditions), um problema muito comum que podem ocorrer em aplicações multithreaded.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A forma mais fácil de tornar os objetos &lt;code&gt;Notification&lt;/code&gt; thread-safe é tornar os getters e setters &lt;code&gt;synchronized&lt;/code&gt; usando &lt;code&gt;Locks&lt;/code&gt; do pacote &lt;code&gt;java.util.concurrent.locks&lt;/code&gt;. Isso funcionaria, mas tem algumas desvantagens que precisamos considerar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Não é escalável e propenso a erros&lt;/strong&gt;: quando for necessário adicionar mais atributos, os desenvolvedores devem garantir que qualquer estado de escrita e leitura será &lt;code&gt;synchronized&lt;/code&gt;, o que pode levar a problemas de desempenho e deadlock de threads indesejados;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;É uma abordagem verbosa&lt;/strong&gt;: o desenvolvedor deve escrever muito código para tornar o objeto thread-safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Não é eficiente&lt;/strong&gt;: sincronizar o acesso para ler e escrever dados pode causar problemas de desempenho em aplicações multithreaded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Não temos clareza sobre como o objeto deve ser criado&lt;/strong&gt;: o desenvolvedor deve ler a documentação para saber quais atributos são obrigatórios e quais são opcionais para assim poder defini-los;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todas essas preocupações são necessárias apenas pelo fato que essa classe é base para instâncias de objetos mutáveis. Se o seu cenário requer objetos mutáveis, então faz sentido colocar esforço para lidar com todas essas preocupações. Caso contrário, se o seu cenário permitir que você use objetos imutáveis, então você pode evitar todas essas preocupações.&lt;/p&gt;

&lt;p&gt;Por esse motivo precisamos ter clareza sobre os requisitos da sua solução antes de começar a codificar. Isso ajudará você a escolher a melhor abordagem para resolver o problema. Vamos voltar para a nossa classe &lt;code&gt;Notification&lt;/code&gt; e tentar torná-la imutável.&lt;/p&gt;

&lt;p&gt;Objetos imutáveis são seguros para threads por natureza porque não podem ser modificados após a criação. É uma boa prática tornar seus objetos imutáveis sempre que possível.&lt;/p&gt;

&lt;p&gt;Podemos então usar construtores específicos para tornar o objeto &lt;code&gt;Notification&lt;/code&gt; imutável. Veja abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// mandatory&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// optional&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getRecipient&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isHighPriority&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getType&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt;  &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getAttachment&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// omitted hash and equals methods &lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos atualizar o &lt;code&gt;NotificationProgram&lt;/code&gt; que cria um objeto &lt;code&gt;Notification&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"New message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"/path/to/attachment.txt"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora os objetos &lt;code&gt;Notification&lt;/code&gt; são imutáveis e seguros para threads. O desenvolvedor pode instanciar o objeto com todos os atributos obrigatórios e opcionais em uma única linha de código. O objeto será criado em um estado válido, e o desenvolvedor não pode alterar seu estado após a criação.&lt;/p&gt;

&lt;p&gt;Desde o Java 16, podemos usar a palavra-chave &lt;code&gt;record&lt;/code&gt; para criar objetos imutáveis, é o que chamamos Java Records. Se você estiver usando o Java 16 ou superior, eu recomendo fortemente que você use Java Records para criar objetos imutáveis. Vamos ver como podemos refatorar a classe &lt;code&gt;Notification&lt;/code&gt; para se tornar um Java Record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Menos código, mais legibilidade e mais manutenível. Esse é o poder dos Java Records.&lt;/p&gt;

&lt;p&gt;Voltando para nosso desafio, algo ainda não está certo: se &lt;code&gt;highPriority&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt; e &lt;code&gt;attachment&lt;/code&gt; são atributos opcionais, por que é necessário fornecer cada valor no construtor?&lt;/p&gt;

&lt;p&gt;Podemos resolver esse problema usando uma abordagem tradicional chamada &lt;strong&gt;Telescoping constructors&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uma abordagem tradicional: Telescoping constructors
&lt;/h3&gt;

&lt;p&gt;A common approach to object creation is to provide multiple constructors with different numbers of parameters. Each constructor calls application constructor with the required parameters and sets the optional parameters to default values. It's called &lt;strong&gt;telescoping constructors&lt;/strong&gt;. You can use this approach on any java class, including Java Records.&lt;/p&gt;

&lt;p&gt;Uma abordagem comum para a criação de objetos é fornecer vários construtores com diferentes números ou tipos de parâmetros. Cada construtor chama o construtor de aplicação com os parâmetros obrigatórios e define os parâmetros opcionais com valores padrão. Isso é o que chamamos de &lt;strong&gt;telescoping constructors&lt;/strong&gt; (não encontrei nome em português aqui... se vc souber, mande nos comentários!). Você pode usar essa abordagem em qualquer classe Java, incluindo Java Records.&lt;/p&gt;

&lt;p&gt;Vamos ver como ficará nossa classe utilizando essa abordagem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, os desenvolvedores poderão criar objetos &lt;code&gt;Notification&lt;/code&gt; com apenas os atributos obrigatórios. Os atributos opcionais serão definidos com valores padrão. Lembrando que objetos &lt;code&gt;Notification&lt;/code&gt; continuam sendo imutáveis e seguros para threads.&lt;/p&gt;

&lt;p&gt;Vamos atualizar o &lt;code&gt;NotificationProgram&lt;/code&gt; que cria um objeto &lt;code&gt;Notification&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;notificationWithDefaultOptionalValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="s"&gt;"New message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
                        &lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
                        &lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;notificationWithCustomOptionalValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="s"&gt;"Another message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"Oh no! Something wrong happened"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"/path/to/attachment.txt"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ótimo! Vamos revisar os problemas que tivemos e como os resolvemos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Objetos &lt;code&gt;Notification&lt;/code&gt; somente podem ser instanciados com estado válido&lt;/strong&gt;: os construtores garantem que o objeto será criado em um estado válido;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Objetos &lt;code&gt;Notification&lt;/code&gt; são imutáveis e seguros para threads&lt;/strong&gt;: a imutabilidade garante que os objetos &lt;code&gt;Notification&lt;/code&gt; são seguros para threads;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bom, o terceiro problema sobre a verbosidade e propensão a erros dos construtores ainda existem. Quanto ao quarto item, podemos prover uma documentação que ajudará os desenvolvedores a saber qual construtor deve ser usado com a ordem dos argumentos. Mas nesse ponto, acredito que podemos fazer mais para facilitar a vida do desenvolvedor, não?&lt;/p&gt;

&lt;h3&gt;
  
  
  Favoreça Static Factory Methods ao invés de Construtores
&lt;/h3&gt;

&lt;p&gt;Para ajudar os desenvolvedores a saber qual construtor deve ser usado, podemos fornecer métodos fábrica estáticos (Static Factory Methods) para criar objetos.&lt;/p&gt;

&lt;p&gt;Static factory methods são métodos estáticos que retornam uma instância de uma determinada classe ou subclasse. Eles podem ter nomes que podém auxiliar quais os atributos que precisam ser fornecidos para criar um determinado objeto, facilitando assim a vida dos desenvolvedores a criar tais objetos.&lt;/p&gt;

&lt;p&gt;Talvez você já tenha ouvido falar sobre o padrão "Factory Method" do livro Design Pattern (Gang of Four) antes, mas o Static Factory Method não é uma implementação direta desse padrão. O propósito pode até ser o mesmo, mas não há um padrão equivalente no livro Gang of Four para os Static Factory Methods, na verdade.&lt;/p&gt;

&lt;p&gt;Algumas vantagens de usar métodos fábrica estáticos são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static factory methods tem nomes que descrevem o objeto que está sendo retornado&lt;/strong&gt;: o desenvolvedor pode saber qual construtor deve ser usado lendo o nome do método;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static factory methods não precisam criar um novo objeto em cada invocação&lt;/strong&gt;: eles podem retornar o mesmo objeto se o objeto for imutável, economizando memória e recursos da CPU;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static factory methods podem retornar qualquer objeto do tipo e/ou seus subtipos&lt;/strong&gt;: eles podem retornar um objeto de um subtipo da classe, facilitando a criação de objetos com diferentes configurações.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static factory methods podem retornar objetos tipo e seus subtipos dependendo dos argumentos de entrada fornecidos&lt;/strong&gt;: diferentes dos construtores de uma classe que apenas retornam uma instância do seu tipo criando uma nova instância toda vez que são chamados, os métodos fábrica estáticos podem aplicar lógicas específicas e retornar objetos do tipo solicitado ou seus subtipos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Antes de por nossos dedos no código, vamos pensar sobre como aplicar os métodos fábrica estáticos no nosso desafio. De acordo com o conceito de métodos fábrica estáticos, podemos criar um método fábrica estático para cada combinação de atributos. Isso até facilitará a vida do desenvolvedor, mas como devemos implementar esses métodos fábrica estáticos?&lt;/p&gt;

&lt;p&gt;De fato, para nosso desafio, se concentrarmos em fornecer métodos fábrica estáticos para todas as combinações possíveis, resultaríamos em uma classe grande com muitos métodos fábrica estáticos. São cerca de 16 variações de métodos fábrica estáticos! Talvez não seja uma boa ideia ter muitos métodos fábrica estáticos em uma classe. Possivelmente isso irá tornar a classe mais difícil de entender e consequentemente de manter. Vamos mudar nosso ponto de vista: em vez de cobrir estaticamente todas as combinações possíveis, podemos fornecer métodos fábrica estáticos com os atributos permitindo assim realizar as possíveis combinações. Vamos ver como ficaria.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@lombok&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="nf"&gt;createNotification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="nf"&gt;createHighPriorityNotification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="nf"&gt;createNotificationWithAttachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="nf"&gt;createHighPriorityNotificationWithAttachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, desenvolvedores podem criar objetos &lt;code&gt;Notification&lt;/code&gt; usando métodos fábrica estáticos. Os métodos fábrica estáticos têm nomes que descrevem quais os atributos que definiram o objeto que está sendo retornado, facilitando assim a vida dos desenvolvedores a saber qual construtor deve ser usado. E como estamos ainda utilizando Java Records, os objetos &lt;code&gt;Notification&lt;/code&gt; continuam sendo imutáveis e seguros para threads.&lt;/p&gt;

&lt;p&gt;Vamos atualizar o &lt;code&gt;NotificationProgram&lt;/code&gt; que cria um objeto &lt;code&gt;Notification&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;generalNotificationWithoutAttachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createNotification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"General Notification"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"This is a general notification"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;highPrioryInfoNotification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createHighPriorityNotification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"High Priority Info Notification"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"This is a high priority info notification"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Que legal! Estamos melhorando nosso código passo a passo. Talvez a forma como nossa classe foi implementada até o momento esteja okay para alguns casos, mas acredito que podemos fazer melhor!&lt;/p&gt;

&lt;p&gt;Em nossa implementação, cada método fábrica estático está exigindo quatro argumentos. Não é um grande problema, mas e se tivermos mais atributos? Os métodos fábrica estáticos se tornarão ainda mais complexos e propensos a erros. Vamos ver como podemos resolver esse problema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Muitos parâmetros? Use o padrão Builder
&lt;/h3&gt;

&lt;p&gt;The Builder pattern is a creational design pattern that allows you to construct complex objects step by step. It's useful when you have many optional attributes in your class and you want to make the object creation more readable and maintainable.&lt;/p&gt;

&lt;p&gt;O padrão Builder é um padrão de design criacional que permite construir objetos complexos passo a passo. É útil quando você tem muitos atributos em sua classe e deseja tornar a criação do objeto mais legível e manutenível.&lt;/p&gt;

&lt;p&gt;Algumas biliotecas como Lombok, ou até plugins de IDEs como IntelliJ IDEA, podem gerar Builders para você. Isso é incrível, mas precisamos entender como ele funciona para poder usá-lo efetivamente.&lt;/p&gt;

&lt;p&gt;Vamos ver como podemos implementar o padrão Builder para nossa classe &lt;code&gt;Notification&lt;/code&gt; usando Lombok, por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.Builder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Builder&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por baixos dos panos, o Lombok irá gerar para você todas as classes de builder para a classe &lt;code&gt;Notification&lt;/code&gt;. No final, teremos um resultado similar ao abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt; &lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationDataBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt; &lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt; &lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt; &lt;span class="nf"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt; &lt;span class="nf"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationDataBuilder&lt;/span&gt; &lt;span class="nf"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O Lombok fornece muitas anotações para gerar código boilerplate para você. A anotação &lt;code&gt;@Builder&lt;/code&gt; gera uma classe builder para a classe anotada. A classe builder gerada pelo Lombok tem uma interface fluente onde os desenvolvedores podem chamar de forma encadeada os métodos para definir os atributos da classe anotada e um método &lt;code&gt;build()&lt;/code&gt; para criar uma instância da classe anotada.&lt;/p&gt;

&lt;p&gt;Builders podem ser implementados de várias maneiras, como usando o estilo tradicional utilizando métodos setter, mas é comum implementá-los seguindo o estilo de design &lt;strong&gt;Fluent API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O estilo de design &lt;strong&gt;Fluent API&lt;/strong&gt; é enfatizado pela chamada encadeada de métodos. Ele permite que os desenvolvedores chamem métodos de forma encadeada, tornando o código mais legível e manutenível. É usado em muitas bibliotecas, frameworks e APIs para melhorar a experiência do desenvolvedor. Pode ser aplicado ao padrão Builder com certeza, mas não se limita a esse uso. Pode ser usado em &lt;strong&gt;DSLs (Domain-Specific Languages)&lt;/strong&gt; e muitos outros contextos.&lt;/p&gt;

&lt;p&gt;Particularmente eu prefiro ter essas classes explicitamente no meu código. Isso me ajuda a entender como o padrão Builder funciona e, o mais importante na minha opinião: ele libera os desenvolvedores de terem o Lombok configurado em suas IDEs. Uma dependência a menos para se configurar e se preocupar!&lt;/p&gt;

&lt;p&gt;Vamos ver a flexibilidade que o padrão Builder fornece aos desenvolvedores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;generalNotification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// do something with generalNotification&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;highPriorityInfoNotificationWithAttachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"attachment.pdf"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// do something with highPriorityInfoNotificationWithAttachment;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, desenvolvedores poderão criar objetos &lt;code&gt;Notification&lt;/code&gt; usando o padrão Builder. O padrão Builder permite que os desenvolvedores construam objetos complexos passo a passo, tornando a criação do objeto mais legível e manutenível.&lt;/p&gt;

&lt;p&gt;Bom, tal builder como esses podem até ajudar facilitar a vida de alguns desenvolvedores, principalmente os desenvolvedores que estão criando o builder, mas e quanto aos desenvolvedores que irão usar o builder?&lt;/p&gt;

&lt;p&gt;Mas o que você quer dizer com isso? - você pode perguntar. É essa é uma ótima pergunta!&lt;/p&gt;

&lt;p&gt;Antes de adicionar a solução do builder na classe &lt;code&gt;Notification&lt;/code&gt;, os desenvolvedores precisavam passar os argumentos obrigatórios para os métodos fábrica estáticos para criar objetos &lt;code&gt;Notification&lt;/code&gt;. O compilador Java irá forçar o desenvolvedor a passar os argumentos obrigatórios e necessários para os métodos fábrica estáticos para criar objetos &lt;code&gt;Notification&lt;/code&gt; com estado válido. A solução builder que adicionamos a nossa classe não fornece essa capacidade de maneira padrão. Veja o código abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;anotherNotification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você pode dizer: "&lt;em&gt;Não é um grande problema! A classe respeitará suas restrições e nenhuma instância inválida será criada! Ele lançará exceções para o chamador!&lt;/em&gt;". Sim, é verdade, mas essas mesmas exceções serão lançadas apenas em tempo de execução. E isso não é bom para ninguém!&lt;/p&gt;

&lt;p&gt;Erros em tempo de execução explodem em produção, e esses, quando não tratados, afetam a imagem e percepção do cliente final da solução. Isso exigirá uma maneira inteligente de lidar com esses cenários, forçando os desenvolvedores a espalhar a lógica de tratamento de erros em cada ponto que irá utilizar esse código. Espalhar código e forçar esse cenário não é uma boa prática!&lt;/p&gt;

&lt;p&gt;Em resumo, erros de compilação (compilation errors) ou de tempo de execução (runtime errors) ainda demonstram que existem problemas na solução, mas erros de compilação ajudam os desenvolvedores a descobrir problemas em tempo de compilação, o que é melhor! Vamos tentar usar o padrão Builder para impor as restrições da classe &lt;code&gt;Notification&lt;/code&gt; em tempo de compilação.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restringindo a ordem das chamadas de métodos no padrão Builder
&lt;/h3&gt;

&lt;p&gt;O padrão Builder permite que os desenvolvedores construam objetos complexos passo a passo. O padrão Builder pode ser usado para impor as restrições da classe em tempo de compilação.&lt;/p&gt;

&lt;p&gt;Nossa implementação do Builder não restringe a ordem das chamadas de métodos. O desenvolvedor pode chamar os métodos em qualquer ordem, o que pode levar a objetos inválidos. Isso acontece porque o &lt;code&gt;NotificationBuilder&lt;/code&gt; expõe todos os atributos para serem definidos pelo desenvolvedor de maneira livre. Com isso, não conseguimos exigir que os métodos obrigatórios sejam chamados e assim garantir que os atributos obrigatórios tenham sido definidos. Para restringir essa ordem das chamadas de métodos, podemos estar utilizando uma variação do padrão Builder, o &lt;strong&gt;padrão Step Builder&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Primeiro, vamos quebrar o processo realizado pelo &lt;code&gt;NotificationBuilder&lt;/code&gt; em alguns passos. Cada passo será responsável por definir um grupo específico de atributos. Aqui está nosso plano:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Vamos garantir que &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;message&lt;/code&gt; e &lt;code&gt;recipient&lt;/code&gt; sejam definidos nessa ordem específica; Às vezes é importante seguir uma ordem predefinida durante a instanciação de um objeto. Na verdade, esse não é o nosso caso, no entanto, para fins de aprendizado, vamos fazer dessa forma. Uma vez que esses atributos obrigatórios são definidos, vamos permitir que o desenvolvedor possa construir o objeto &lt;code&gt;Notification&lt;/code&gt; com os valores padrão para os atributos opcionais, ou...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vamos permitir que os desenvolvedores definam &lt;code&gt;highPriority&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt; e &lt;code&gt;attachment&lt;/code&gt; em qualquer ordem. Como esses atributos são opcionais, devemos permitir que os desenvolvedores possam construir o objeto &lt;code&gt;Notification&lt;/code&gt; a qualquer momento a partir deste ponto;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos ver como ficará:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilder&lt;/span&gt; &lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitle&lt;/span&gt; &lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitleMessage&lt;/span&gt; &lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitleMessageRecipient&lt;/span&gt; &lt;span class="nf"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                               &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                               &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, desenvolvedores devem seguir a ordem das chamadas de métodos para criar um objeto &lt;code&gt;Notification&lt;/code&gt;. A classe &lt;code&gt;NotificationBuilderWithTitle&lt;/code&gt; é responsável por definir o atributo &lt;code&gt;title&lt;/code&gt;. A classe &lt;code&gt;NotificationBuilderWithTitleMessage&lt;/code&gt; é responsável por definir o atributo &lt;code&gt;message&lt;/code&gt;. A classe &lt;code&gt;NotificationBuilderWithTitleMessageRecipient&lt;/code&gt; é responsável por definir o atributo &lt;code&gt;recipient&lt;/code&gt;. A classe &lt;code&gt;NotificationBuilderWithTitleMessageRecipient&lt;/code&gt; tem um método &lt;code&gt;build()&lt;/code&gt; para criar um objeto &lt;code&gt;Notification&lt;/code&gt;. Vamos destacar alguns pontos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Todos os objetos criados pelo processo de construção são seguros para threads&lt;/strong&gt;, o que significa que os desenvolvedores podem criar objetos &lt;code&gt;Notification&lt;/code&gt; em um ambiente multithreaded sem problemas;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Os métodos oferecidos pelos objetos builder são nomeados&lt;/strong&gt;, o que significa que os desenvolvedores podem saber qual método deve ser chamado em seguida para criar um objeto &lt;code&gt;Notification&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A ordem das chamadas de métodos é imposta pelo padrão Builder&lt;/strong&gt;, o que significa que os desenvolvedores devem seguir a ordem das chamadas de métodos para criar um objeto &lt;code&gt;Notification&lt;/code&gt; e o compilador irá impor essa restrição;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Esse builder prove uma API fluente&lt;/strong&gt;, o que significa que os desenvolvedores podem criar objetos &lt;code&gt;Notification&lt;/code&gt; de uma maneira legível e manutenível.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Que massa! Vamos continuar a implementação para suportar a definição dos atributos opcionais.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;INFO&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"title is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"message is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;requireNonNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"recipient is required"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ofNullable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GENERAL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilder&lt;/span&gt; &lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilder&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitle&lt;/span&gt; &lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitleMessage&lt;/span&gt; &lt;span class="nf"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitleMessageRecipient&lt;/span&gt; &lt;span class="nf"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                               &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                               &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt; &lt;span class="nf"&gt;addMore&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                                      &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                                      &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                                      &lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                                      &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                                                      &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt; &lt;span class="nf"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt; &lt;span class="nf"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;attachment&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt;
            &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, após definir os atributos obrigatórios, os desenvolvedores podem criar objetos &lt;code&gt;Notification&lt;/code&gt; definindo os atributos opcionais em qualquer ordem. A classe &lt;code&gt;NotificationBuilderWithTitleMessageRecipientAndMore&lt;/code&gt; é responsável por definir os atributos opcionais e criar o objeto &lt;code&gt;Notification&lt;/code&gt;. Nesse ponto, os desenvolvedores podem definir os atributos opcionais ou chamar o método &lt;code&gt;build()&lt;/code&gt; para criar um objeto &lt;code&gt;Notification&lt;/code&gt; arbitrariamente. Vamos destacar alguns pontos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;O builder permite que os desenvolvedores definam os atributos opcionais em qualquer ordem&lt;/strong&gt;, o que significa que os desenvolvedores podem criar objetos &lt;code&gt;Notification&lt;/code&gt; com os atributos opcionais em qualquer ordem;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;O builder permite que os desenvolvedores criem objetos &lt;code&gt;Notification&lt;/code&gt; arbitrariamente&lt;/strong&gt;, o que significa que os desenvolvedores podem definir os atributos opcionais ou criar o objeto &lt;code&gt;Notification&lt;/code&gt; em qualquer ponto do processo de construção;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vamos atualizar o &lt;code&gt;NotificationProgram&lt;/code&gt; que cria um objeto &lt;code&gt;Notification&lt;/code&gt; usando o builder que implementamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;notification.Notification&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;generalNotification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Another title"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Another message"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"johndoe@system.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// do something with generalNotification&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;highPriorityWarningNotification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Warning title"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Attention people!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"johndoe@sytem.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addMore&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// do something with highPriorityWarningNotification&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;highPriorityErrorNotificationWithAttachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Warning title"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Attention people!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"johndoe@sytem.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addMore&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ERROR&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attachment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error.log"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;highPriority&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// do something with highPriorityErrorNotificationWithAttachment&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa implementação do builder vai além do tradicional padrão Builder.&lt;/p&gt;

&lt;p&gt;Como podemos ver no código anterior, os desenvolvedores podem criar objetos &lt;code&gt;Notification&lt;/code&gt; com os atributos opcionais em qualquer ordem e, ao mesmo tempo, ele impõe as restrições da classe &lt;code&gt;Notification&lt;/code&gt; em tempo de compilação forçando a definição dos atributos obrigatórios, tornando a criação do objeto mais legível e manutenível.&lt;/p&gt;

&lt;p&gt;Como o tio Ben Parker costumava dizer - "Com grandes poderes vêm grandes responsabilidades" - implementar o padrão Builder dessa forma tornará o código complexo, tornando-o mais difícil de entender e alterar, provavelmente. É um trade-off que você deve considerar ao usar o padrão Builder.&lt;/p&gt;

&lt;p&gt;Uma vez que você tenha que lidar com muitos atributos (sendo eles obrigatórios ou não) para criar objetos, o padrão Builder e suas variações podem ser uma boa escolha. Como o builder está recebendo ajuda do compilador, refatorar o código será mais fácil e seguro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Neste conteúdo, discutimos algumas abordagens para criar objetos com muitos atributos obrigatórios e opcionais. Começamos com a abordagem tradicional, usando construtores e setters para criar objetos. Vimos que essa abordagem pode levar a objetos inválidos, problemas de segurança de threads e código verboso. Em seguida, exploramos algumas abordagens como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Telescope constructors;&lt;/li&gt;
&lt;li&gt;Static Method Factory;&lt;/li&gt;
&lt;li&gt;Builder pattern;&lt;/li&gt;
&lt;li&gt;Fluent API design style;&lt;/li&gt;
&lt;li&gt;Step Builder pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Toda a abordagem têm seus prós e contras. A abordagem dos construtores telescópicos pode resolver alguns cenários, mas pode ser propensa a erros e verbosa ao lidar com muitos atributos. O Static Method Factory pode oferecer uma boa alternativa para construir objetos quando poucos atributos são necessários. O padrão Builder permite que os desenvolvedores construam objetos complexos passo a passo usando o estilo de design Fluent API, fornecendo uma interface fluente, tornando a criação do objeto mais legível e manutenível e, o padrão Step Builder pode ser usado para impor as restrições da classe em tempo de compilação. No final, pudemos ver como essas abordagens podem ajudar os desenvolvedores a facilitar suas vidas ao criar objetos com muitos atributos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lições aprendidas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tornar a vida dos desenvolvedores mais fácil é tão importante quanto tornar a vida dos clientes finais mais fácil;&lt;/li&gt;
&lt;li&gt;A abordagem &lt;strong&gt;Telescoping Constructors&lt;/strong&gt; pode resolver alguns cenários, mas pode ser propensa a erros e verbosa ao lidar com muitos atributos;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static Method Factory&lt;/strong&gt; pode oferecer uma boa alternativa para construir objetos quando poucos atributos são necessários;&lt;/li&gt;
&lt;li&gt;O padrão &lt;strong&gt;Builder&lt;/strong&gt; permite que os desenvolvedores construam objetos complexos passo a passo;&lt;/li&gt;
&lt;li&gt;O estilo de design &lt;strong&gt;Fluent API&lt;/strong&gt; pode ajudar os desenvolvedores a criar código especializado focado em encadeamento de métodos, melhorando a experiência do desenvolvedor. Normalmente é usado para expressar linguagens específicas de domínio. Em nosso contexto, foi usado para criar um builder mais fácil de usar, permitindo que os desenvolvedores criem objetos de uma forma legível e manutenível;&lt;/li&gt;
&lt;li&gt;A variação do padrão Builder chamado &lt;strong&gt;Step Builder pattern&lt;/strong&gt; permite que os desenvolvedores criem objetos complexos definindo os atributos seguindo uma ordem predefinida;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pensamentos finais
&lt;/h3&gt;

&lt;p&gt;Eu espero que você tenha gostado deste conteúdo! Se você tiver alguma dúvida ou feedback, por favor, sinta-se à vontade para entrar em contato. Eu adoraria ouvir de você!&lt;/p&gt;

&lt;p&gt;Muitos projetos open-source em Java trazem essas abordagens para criar objetos com muitos atributos opcionais. O Lombok, por exemplo, fornece a anotação &lt;code&gt;@Builder&lt;/code&gt; para gerar o padrão Builder para você, mas é importante entender como ele funciona para poder usá-lo de maneira eficiente.&lt;/p&gt;

&lt;p&gt;Os design patterns e estilos de design de código podem (pra não dizer que devem) ser misturados e combinados conforme necessário para resolver o problema que estão resolvendo. &lt;strong&gt;Não existe bala de prata no desenvolvimento de software&lt;/strong&gt;. Cada abordagem tem seus prós e contras e ninguém melhor do que você para saber qual é a melhor para o seu cenário.&lt;/p&gt;

&lt;p&gt;Para ver um bom exemplo que usa algumas dessas técnicas na prática, dê uma olhada no projeto Eclipse JNoSQL, na classe &lt;a href="https://github.com/eclipse-jnosql/jnosql/blob/ecf992ba9bb6aaf2f816e9e21802258c2037736c/jnosql-mapping/jnosql-mapping-semistructured/src/main/java/org/eclipse/jnosql/mapping/semistructured/AbstractSemiStructuredTemplate.java#L295" rel="noopener noreferrer"&gt;org.eclipse.jnosql.mapping.semistructured.AbstractSemiStructuredTemplate&lt;/a&gt; no método &lt;code&gt;QueryMapper.MapperFrom select(Class&amp;lt;T&amp;gt; type)&lt;/code&gt;. Ele usa um estilo de design Fluent API para ajudar os usuários a realizar consultas para recuperar dados de implementações de banco de dados NoSQL semi-estruturados.&lt;/p&gt;

&lt;p&gt;Se você quer aprender mais sobre o padrão Builder, eu recomendo os seguintes recursos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dzone.com/articles/java-fluent-api" rel="noopener noreferrer"&gt;Fluent-API: Creating Easier, More Intuitive Code With a Fluent API by Otavio Santana&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Effective-Java-3rd-Joshua-Bloch/dp/0134685997" rel="noopener noreferrer"&gt;Effective Java - Item 1: Consider Static Factory Methods Instead Of Constructors&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Effective-Java-3rd-Joshua-Bloch/dp/0134685997" rel="noopener noreferrer"&gt;Effective Java - Item 2: Consider a builder when faced with many constructor parameters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612" rel="noopener noreferrer"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://refactoring.guru/design-patterns/builder" rel="noopener noreferrer"&gt;Builder Pattern - Refactoring Guru&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Builder_pattern" rel="noopener noreferrer"&gt;Builder Pattern - Wikipedia&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Além disso, eu gostaria de recomendar que você coloque essas abordagens em prática no seu dia a dia. Isso ajudará você a entender quando usar cada uma e como aplicá-las de forma eficaz.&lt;/p&gt;

&lt;p&gt;Gostou deste conteúdo? Se sim, por favor, compartilhe com seus amigos e colegas. Além disso, não se esqueça de me seguir nas redes sociais para ficar atualizado com os últimos conteúdos e atualizações.&lt;/p&gt;

&lt;p&gt;Até o próximo conteúdo!&lt;/p&gt;

</description>
      <category>java</category>
      <category>tutorial</category>
      <category>learning</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>[PT-BR] Por que não é uma boa prática usar 'Object' como um tipo genérico em Java?</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Tue, 17 Dec 2024 23:18:47 +0000</pubDate>
      <link>https://dev.to/dearrudam/pt-br-por-que-nao-e-uma-boa-pratica-usar-object-como-um-tipo-generico-em-java-44jp</link>
      <guid>https://dev.to/dearrudam/pt-br-por-que-nao-e-uma-boa-pratica-usar-object-como-um-tipo-generico-em-java-44jp</guid>
      <description>&lt;p&gt;Caso queira conferir esse conteúdo em inglês, fique a vontade clicando aqui: &lt;strong&gt;&lt;a href="https://dev.to/dearrudam/the-challenges-of-using-object-as-a-catch-all-type-in-java-43le"&gt;The Challenges of Using 'Object' as a Catch-All Type in Java&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Durante uma sessão de mentoria, conversando sobre Generics em Java com o desenvolvedor mentorado, percebemos que alguns conceitos precisam ser dominados para trazer mais valor quanto as motivações e o real valor na utilização de Generics no Java. Daí surgiu a pergunta: "Por que não é uma boa prática usar &lt;code&gt;Object&lt;/code&gt; como um tipo genérico em Java?"&lt;/p&gt;

&lt;p&gt;Achei esta pergunta é muito interessante e é por isso que estou abordando esse assunto neste conteúdo.&lt;/p&gt;

&lt;p&gt;Muito bem, vamos lá!&lt;/p&gt;

&lt;p&gt;Como um desenvolvedor Java, você deve saber que &lt;code&gt;java.lang.Object&lt;/code&gt; é a raiz da hierarquia de classes na linguagem. Toda classe herda de &lt;code&gt;Object&lt;/code&gt;, incluindo arrays. Isso significa que todos os objetos são, por padrão, instâncias de &lt;code&gt;Object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjpmiis6zga4zizm3958.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjpmiis6zga4zizm3958.png" alt=" raw `java.lang.Object` endraw  é a raiz da hierarquia de classes na linguagem" width="379" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bem, se toda classe herda de &lt;code&gt;Object&lt;/code&gt;, por que não é uma boa prática usar &lt;code&gt;Object&lt;/code&gt; como um tipo genérico em Java? Vamos conferir!&lt;/p&gt;

&lt;h3&gt;
  
  
  Usando Object para Armazenar Qualquer Tipo de Objeto
&lt;/h3&gt;

&lt;p&gt;Quando declaramos variáveis, você pode tipar a variável como &lt;code&gt;Object&lt;/code&gt; como para armazenar qualquer objeto quando o seu tipo específico é desconhecido.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Isso funciona porque String é um Object!&lt;/span&gt;
    &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Isso funciona, porque Integer é um Object!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tais declarações podem compor um programa Java válido, como mostrado abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Isso funciona, pois String é um Object!&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A saida deste programa será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
Maximillian
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso acontece porque &lt;code&gt;String&lt;/code&gt; é uma subclasse de &lt;code&gt;Object&lt;/code&gt;, logo o compilador não irá encontrar nenhum problema sintático. Além disso, você pode alterar o valor de &lt;code&gt;infoA&lt;/code&gt; para um objeto de qualquer outro tipo, e o programa ainda continuará funcionando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Isso funciona porque Double é um Object!&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A saída será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
3.14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, o programa funciona independentemente do tipo de objeto atribuído à variável &lt;code&gt;infoA&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mas quais são os benefícios de usar &lt;code&gt;Object&lt;/code&gt; como um tipo? Alguns desenvolvedores podem dizer: "Isso torna o código mais flexível e reutilizável." Mas será que isso é verdade?&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitações ao Usar Object: Falta de Segurança de Tipos
&lt;/h3&gt;

&lt;p&gt;Sim, não existe uma "bala de prata" na área de desenvolvimento de software. Cada decisão tem seus prós e contras. Vamos explorar as limitações de usar &lt;code&gt;Object&lt;/code&gt; como um tipo genérico.&lt;/p&gt;

&lt;p&gt;Independente do tipo de objeto, você só pode interagir com ele através de sua &lt;strong&gt;interface&lt;/strong&gt;. Neste contexto, a palavra "interface" significa os métodos que estão expostos através da classe de seu tipo.&lt;/p&gt;

&lt;p&gt;Uma &lt;strong&gt;classe&lt;/strong&gt; é a receita ou um modelo para os objetos derivados dessa tal classe. Quando você define uma classe, você está especificando seu tipo, a estrutura e o comportamento dos objetos criados a partir dela. A classe define os atributos (o estado, ou seja, seus dados) e métodos (comportamento) que os objetos terão. Esses métodos permitem que os objetos interajam entre si.&lt;/p&gt;

&lt;p&gt;A classe &lt;code&gt;Object&lt;/code&gt; inclui alguns métodos comuns, como &lt;code&gt;toString()&lt;/code&gt;, &lt;code&gt;equals()&lt;/code&gt; e &lt;code&gt;hashCode()&lt;/code&gt;. Esses métodos são úteis em muitos casos, mas não são suficientes quando você deseja interagir com métodos específicos de uma classe particular.&lt;/p&gt;

&lt;p&gt;Vamos supor que estamos armazenando um objeto &lt;code&gt;String&lt;/code&gt; em uma variável declarada como &lt;code&gt;Object&lt;/code&gt;, e queremos obter o comprimento do valor( a string) que foi atribuído. Veja o que acontece:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Isso funciona porque String é um Object, mas...&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tentando executar o código acima, teremos o seguinte resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
ObjectAsCatchAllTypeProgram.java:5: error: cannot find symbol
        System.out.println&lt;span class="o"&gt;(&lt;/span&gt;infoA.length&lt;span class="o"&gt;())&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                                ^
  symbol:   method length&lt;span class="o"&gt;()&lt;/span&gt;
  location: variable infoA of &lt;span class="nb"&gt;type &lt;/span&gt;Object
1 error
error: compilation failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando você declara uma variável como &lt;code&gt;Object&lt;/code&gt;, você perde a segurança de tipos, para os íntimos, &lt;strong&gt;Type safety&lt;/strong&gt;. &lt;strong&gt;Type safety&lt;/strong&gt; é uma característica do Java que impede que você atribua um objeto de um tipo a uma variável de outro tipo. Essa característica ajuda a detectar erros em tempo de compilação, tornando seu código mais confiável. No exemplo acima, o compilador não sabe que &lt;code&gt;infoA&lt;/code&gt; é um instancia de um objeto do tipo &lt;code&gt;String&lt;/code&gt;, então ele não permitirá que você chame o método &lt;code&gt;length()&lt;/code&gt; nele, gerando assim um erro de compilação (&lt;strong&gt;compilation error&lt;/strong&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitações ao Usar Object: A necessidade de conversão de tipos explícita
&lt;/h3&gt;

&lt;p&gt;Para interagir com um objeto como seu tipo específico, você precisa convertê-lo para esse tipo. A conversão, ou em "javanês", &lt;strong&gt;Casting&lt;/strong&gt;, é o processo de converter um objeto de um tipo para outro. Em Java, você pode converter um objeto (fazer um &lt;strong&gt;casting&lt;/strong&gt;) para um tipo de subclasse ou superclasse. Vamos converter &lt;code&gt;infoA&lt;/code&gt; para &lt;code&gt;String&lt;/code&gt; antes de chamar o método &lt;code&gt;length()&lt;/code&gt; para corrigir o erro de compilação mostrado anteriormente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Isso funciona porque String é um Object, mas...&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, a saída será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste ponto, você pode pensar: "Não é um grande problema; eu posso apenas fazer um casting do objeto para seu tipo antes de interagir com ele." Será? Mesmo para um codebase de médio pra grande?&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitações ao Usar Object: Propenso a erros em tempo de execução
&lt;/h3&gt;

&lt;p&gt;Vamos explorar um cenário diferente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Isso funciona porque Integer é um Object, mas&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Isso não é um String, é um Integer!!!&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando este código, teremos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
Exception &lt;span class="k"&gt;in &lt;/span&gt;thread &lt;span class="s2"&gt;"main"&lt;/span&gt; java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String &lt;span class="o"&gt;(&lt;/span&gt;java.lang.Integer and java.lang.String are &lt;span class="k"&gt;in &lt;/span&gt;module java.base of loader &lt;span class="s1"&gt;'bootstrap'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        at ObjectAsCatchAllTypeProgram.main&lt;span class="o"&gt;(&lt;/span&gt;ObjectAsCatchAllTypeProgram.java:4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um &lt;strong&gt;ClassCastException&lt;/strong&gt; foi lançado porque estamos tentando fazer um cast de um objeto &lt;code&gt;Integer&lt;/code&gt; para um objeto &lt;code&gt;String&lt;/code&gt;. &lt;code&gt;Integer&lt;/code&gt; não é uma subclasse de &lt;code&gt;String&lt;/code&gt;, então o cast falha. Este tipo de erro é o que chamados de &lt;strong&gt;erro em tempo de execução&lt;/strong&gt;, ou &lt;strong&gt;runtime error&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Vamos explorar outro caso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Oops, estamos atribuindo null, e agora...?!?!?&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E como resultado, teremos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
Exception &lt;span class="k"&gt;in &lt;/span&gt;thread &lt;span class="s2"&gt;"main"&lt;/span&gt; java.lang.NullPointerException: Cannot invoke &lt;span class="s2"&gt;"String.length()"&lt;/span&gt; because &lt;span class="s2"&gt;"&amp;lt;local2&amp;gt;"&lt;/span&gt; is null
        at ObjectAsCatchAllTypeProgram.main&lt;span class="o"&gt;(&lt;/span&gt;ObjectAsCatchAllTypeProgram.java:5&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um &lt;strong&gt;NullPointerException&lt;/strong&gt; ocorre porque estamos tentando chamar um método a partir de uma variável onde seu valor é uma referência nula.&lt;/p&gt;

&lt;p&gt;Você pode pensar: "Eu posso facilmente corrigir isso usando um bloco &lt;code&gt;try-catch&lt;/code&gt; ou o operador &lt;code&gt;instanceof&lt;/code&gt;." Vamos tentar lidar com isso usando ambos os métodos:&lt;/p&gt;

&lt;p&gt;Usando um bloco &lt;code&gt;try-catch&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Oops, estamos atribuindo null, e agora...?!?!?&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NullPointerException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"infoA não pode ser convertido pois seu valor é null"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ClassCastException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"infoA não pode ser convertido para String"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
infoA não pode ser convertido pois seu valor é null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usando o operador &lt;code&gt;instanceof&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Oops, estamos atribuindo null, e agora...?!?!?&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"infoA não pode ser convertido para String"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
infoA não pode ser convertido para String
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estratégias para tratar esses cenários podem ajudar sim, mas elas não são tão práticas caso seja preciso utilizá-las toda vez que você precisar interagir com um objeto do tipo &lt;code&gt;Object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Usando o operador &lt;code&gt;instanceof&lt;/code&gt; é uma boa prática quando você precisa verificar o tipo de um objeto antes de fazer um cast. No entanto, isso pode tornar seu código mais complexo e difícil de ler, pois é preciso além de passar pelo operador &lt;code&gt;instanceof&lt;/code&gt; precisaremos fazer o casting. Já o bloco &lt;code&gt;try-catch&lt;/code&gt; é útil para lidar com exceções, mas também pode tornar seu código mais verboso e difícil de manter.&lt;/p&gt;

&lt;p&gt;Se você está usando Java 14 ou superior, podemos usar o recurso Pattern Matching for Instanceof (&lt;a href="https://openjdk.java.net/jeps/305" rel="noopener noreferrer"&gt;JEP305&lt;/a&gt;). Esse aprimoramento de linguagem integrado nos ajuda a escrever um código melhor e mais legível.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// muito mais elegante, não é? :-)&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"infoA não pode ser convertido para String"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui está a saída:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
infoA não pode ser convertido para String
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Nós aprendemos que declarar variáveis como &lt;code&gt;java.lang.Object&lt;/code&gt; é geralmente considerado uma má prática, a menos que haja uma razão específica e convincente. Usar &lt;code&gt;Object&lt;/code&gt; sacrifica a segurança de tipos, a legibilidade e a manutenibilidade. Na maioria dos casos, é melhor usar um tipo mais específico para aproveitar ao máximo o sistema de tipagem forte do Java.&lt;/p&gt;

&lt;p&gt;Durante nossa exploração, descobrimos que erros de compilação (&lt;strong&gt;compilation error&lt;/strong&gt;s) e erros em tempo de execução (&lt;strong&gt;runtime error&lt;/strong&gt;s) podem ocorrer ao usar &lt;code&gt;Object&lt;/code&gt; como um tipo genérico. Vamos recapitular as diferenças entre esses dois tipos de erros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Erros de compilação (&lt;strong&gt;compilation errors&lt;/strong&gt;) ocorrem durante a fase de compilação quando o código não pode ser convertido em bytecode. Esses erros previnem que o programa seja compilado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Errors de tempo de execução (&lt;strong&gt;runtime errors&lt;/strong&gt;) ocorrem após a compilação bem-sucedida e podem fazer com que o programa se comporte de forma imprevisível ou falhe. Erros de tempo de execução são tipicamente mais problemáticos porque podem afetar ambientes de produção.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ambos os tipos de erros indicam problemas, mas os &lt;strong&gt;erros em tempo de execução&lt;/strong&gt; são geralmente mais graves porque podem afetar os usuários e causar comportamentos inesperados, enquanto os &lt;strong&gt;erros de compilação&lt;/strong&gt; são mais fáceis de resolver durante o processo de desenvolvimento do software.&lt;/p&gt;

&lt;p&gt;Uma boa prática é implementar uma boa estratégia de tratamento de erros (&lt;strong&gt;Error Handler&lt;/strong&gt;) para lidar com erros em tempo de execução, capturando as exceções e registrando-as corretamente para ajudá-lo a depurar e corrigir os problemas quando eles surgirem (e vão surgir!).&lt;/p&gt;

&lt;h3&gt;
  
  
  Lições Aprendidas
&lt;/h3&gt;

&lt;p&gt;Através deste conteúdo, exploramos os desafios de usar &lt;code&gt;Object&lt;/code&gt; como um tipo genérico. Aprendemos que usar &lt;code&gt;Object&lt;/code&gt; pode levar a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of type safety&lt;/strong&gt; (Falta de segurança de tipos): Se o compilador não sabe o tipo específico de um objeto declarado como &lt;code&gt;Object&lt;/code&gt;, logo ele não pode detectar erros relacionados ao tipo em tempo de compilação. Isso pode levar a erros em tempo de execução ao interagir com os objetos do tipo &lt;code&gt;Object&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A necessidade de conversão de tipos explícita&lt;/strong&gt; : Para interagir com um objeto como seu tipo específico, você precisa convertê-lo para esse tipo. Fazer isso em demasia espalhando essas instruções podem tornar seu código mais complexo e difícil de ler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Propenso a erros em tempo de execução&lt;/strong&gt;: Usar &lt;code&gt;Object&lt;/code&gt; como um tipo genérico pode levar a erros em tempo de execução, como &lt;code&gt;ClassCastException&lt;/code&gt; e &lt;code&gt;NullPointerException&lt;/code&gt;. Esses erros podem ser difíceis de rastrear, depurar e corrigir, especialmente em codebases grandes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Necessidade adicional de tratamento de erros&lt;/strong&gt;: Para prevenir erros em tempo de execução, você pode precisar usar blocos &lt;code&gt;try-catch&lt;/code&gt; ou o operador &lt;code&gt;instanceof&lt;/code&gt;. Embora essas estratégias possam ajudar, elas podem tornar seu código mais verboso e difícil de manter. Recomendo usar uma boa estratégia de tratamento de erros para lidar com erros em tempo de execução, capturando as exceções e registrando-as corretamente para ajudá-lo a depurar e corrigir os problemas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Considerações finais
&lt;/h3&gt;

&lt;p&gt;Nem sempre usar &lt;code&gt;Object&lt;/code&gt; como um tipo genérico é a melhor solução. Em alguns casos, usar &lt;code&gt;Object&lt;/code&gt; pode ser mais apropriado. Por exemplo, quando você não tem controle sobre o tipo de objeto que será manipulado. No entanto, é importante entender as limitações e desafios associados ao uso de &lt;code&gt;Object&lt;/code&gt; e saber quando é apropriado usá-lo.&lt;/p&gt;

&lt;p&gt;Quando questões sobre o que é certo ou errado na área de desenvolvimento de software surgem em qualquer discussão, costumamos ver desenvolvedores respondendo assim: "Ah, isso depende do contexto com o qual você está trabalhando." E sim, eles estão certos!&lt;/p&gt;

&lt;p&gt;Mas, uma vez que você conhece o contexto, "depende" não é mais uma resposta tão válida assim. No fim, o contexto do problema deve ser utilizado para nos guiar a tomar uma melhor decisão!&lt;/p&gt;

&lt;p&gt;Então, favoreça tipos mais específicos sempre que possível para aproveitar ao máximo o poder do sistema de tipagem do Java. Isso ajudará você a escrever um código mais legível, manutenível e confiável.&lt;/p&gt;

&lt;p&gt;O que você acha de usar &lt;code&gt;Object&lt;/code&gt; como um tipo genérico em Java? Você tem alguma experiência ou melhores práticas para compartilhar? Sinta-se à vontade para deixar seus pensamentos nos comentários abaixo!&lt;/p&gt;

&lt;h3&gt;
  
  
  Próximos passos
&lt;/h3&gt;

&lt;p&gt;Parabéns por chegar ao final deste conteúdo! Espero que você tenha achado informativo e útil.&lt;/p&gt;

&lt;p&gt;Os conceitos aprendidos neste conteúdo são essenciais para entender a motivação por trás do uso de Generics no Java. Generics é um recurso poderoso que permite escrever um código mais flexível e seguro em relação ao tipo, fornecendo verificação de tipo em tempo de compilação.&lt;/p&gt;

&lt;p&gt;Gosto deste conteúdo? Se sim, por favor, compartilhe com seus amigos e colegas. Estou aceitando sugestões de assuntos para os próximos e futuros conteúdos, então, sinta-se à vontade para sugerir nos comentários, ok?&lt;/p&gt;

&lt;p&gt;Também não se esqueça de me seguir nas redes sociais para ficar atualizado com os últimos conteúdos e atualizações.&lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;

</description>
      <category>java</category>
      <category>beginners</category>
      <category>studies</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Challenges of Using 'Object' as a Catch-All Type in Java</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Sun, 15 Dec 2024 23:27:14 +0000</pubDate>
      <link>https://dev.to/dearrudam/the-challenges-of-using-object-as-a-catch-all-type-in-java-43le</link>
      <guid>https://dev.to/dearrudam/the-challenges-of-using-object-as-a-catch-all-type-in-java-43le</guid>
      <description>&lt;p&gt;If you prefer to read this content in Brazilian Portuguese, follow this link &lt;a href="https://dev.to/dearrudam/pt-br-por-que-nao-e-uma-boa-pratica-usar-object-como-um-tipo-generico-em-java-44jp"&gt;[PT-BR] Por que não é uma boa prática usar 'Object' como um tipo genérico em Java?&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;During a mentoring session with a mentee developer where we got started to talk about Java Generics, we realized that some concepts need to be mastered before than talk about Java Generics. Suddenly, a question came up: "Why it is not a good practice to use &lt;code&gt;Object&lt;/code&gt; as a catch-all type in Java?" &lt;/p&gt;

&lt;p&gt;IMHO this question is very interesting and that's the reason why I'm covering this subject in this content.&lt;/p&gt;

&lt;p&gt;Okay, let's get started!&lt;/p&gt;

&lt;p&gt;As a Java developer, you should know that &lt;code&gt;java.lang.Object&lt;/code&gt; is the root of the class hierarchy. Every class inherits from &lt;code&gt;Object&lt;/code&gt;, including arrays. This means that all objects are, by default, instances of &lt;code&gt;Object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdd6ucncgbjdtgdis3sfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdd6ucncgbjdtgdis3sfm.png" alt="" width="310" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, if every class inherits from &lt;code&gt;Object&lt;/code&gt; then why is it not a good practice to use &lt;code&gt;Object&lt;/code&gt; as a catch-all type in Java? Let's check it out!&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Object to Hold Any Type of Object
&lt;/h3&gt;

&lt;p&gt;When declaring variables, you can use &lt;code&gt;Object&lt;/code&gt; as the type to hold any object when the specific type is unknown.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Works fine, because String is an Object!&lt;/span&gt;
    &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Works fine, because Integer is an Object!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Such declarations can be part of a valid Java program, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Works fine, because String is an Object!&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of this program will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
Maximillian
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because &lt;code&gt;String&lt;/code&gt; is a subclass of &lt;code&gt;Object&lt;/code&gt;, and the compiler does not complain about it. Additionally, you can change the value of &lt;code&gt;infoA&lt;/code&gt; to an object of any type, and the program will still work fine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Works fine, because Double is an Object!&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
3.14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, the program works regardless of the type of object assigned to the &lt;code&gt;infoA&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;But what are the benefits of using &lt;code&gt;Object&lt;/code&gt; as a type? Some developers might say, "It makes the code more flexible and reusable." But is it true?&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of Using Object: Lack of type safety
&lt;/h3&gt;

&lt;p&gt;Yeah, there is no "silver bullet" in the software development area. Every decision has its pros and cons. Let's explore the limitations of using &lt;code&gt;Object&lt;/code&gt; as a catch-all type.&lt;/p&gt;

&lt;p&gt;Regardless of the type of object, you can only interact with it through its &lt;strong&gt;interface&lt;/strong&gt;. In this context the "interface" word means the exposed methods declared on its class.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;class&lt;/strong&gt; is a blueprint for an object. When you define a class, you're specifying its type, the structure and behavior of the objects created from it. The class defines the attributes (data) and methods (behavior) that the objects will have. These methods allow objects to interact with one another.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Object&lt;/code&gt; class includes some common methods, such as &lt;code&gt;toString()&lt;/code&gt;, &lt;code&gt;equals()&lt;/code&gt;, and &lt;code&gt;hashCode()&lt;/code&gt;. These methods are useful in many cases, but they are not sufficient when you want to interact with specific methods of a particular class.&lt;/p&gt;

&lt;p&gt;Let’s suppose we are holding a &lt;code&gt;String&lt;/code&gt; object in a variable declared as &lt;code&gt;Object&lt;/code&gt;, and we want to get the length of the assigned value. Here's what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Works fine, because String is an Object, but...&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trying to run the code above results in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
ObjectAsCatchAllTypeProgram.java:5: error: cannot find symbol
        System.out.println&lt;span class="o"&gt;(&lt;/span&gt;infoA.length&lt;span class="o"&gt;())&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                                ^
  symbol:   method length&lt;span class="o"&gt;()&lt;/span&gt;
  location: variable infoA of &lt;span class="nb"&gt;type &lt;/span&gt;Object
1 error
error: compilation failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you declare a variable as &lt;code&gt;Object&lt;/code&gt;, you lose type safety. Type safety is a feature of Java that prevents you from assigning an object of one type to a variable of another type. This feature helps catch errors at compile time, making your code more reliable. In the example above, the compiler doesn't know that &lt;code&gt;infoA&lt;/code&gt; is a &lt;code&gt;String&lt;/code&gt; object, so it doesn't allow you to call the &lt;code&gt;length()&lt;/code&gt; method on it by raising a &lt;strong&gt;compilation error&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of Using Object: The need for explicit casting
&lt;/h3&gt;

&lt;p&gt;To interact with an object as its specific type, you need to cast it to that type. Casting is the process of converting an object from one type to another. In Java, you can cast an object to a subclass or superclass type. Let’s cast &lt;code&gt;infoA&lt;/code&gt; to &lt;code&gt;String&lt;/code&gt; before calling the &lt;code&gt;length()&lt;/code&gt; method to fix the &lt;strong&gt;compilation failed&lt;/strong&gt; showed before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Works fine, because String is an Object, but...&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will now be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, you might think, "It's not a big deal; I can just cast the object to its type before interacting with it." But can we be sure?&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of Using Object: Susceptibility to runtime errors
&lt;/h3&gt;

&lt;p&gt;Let’s take a look at a different scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Works fine, because Integer is an Object, but...&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// It's not a String, it's an Integer!!!&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this results in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
Exception &lt;span class="k"&gt;in &lt;/span&gt;thread &lt;span class="s2"&gt;"main"&lt;/span&gt; java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String &lt;span class="o"&gt;(&lt;/span&gt;java.lang.Integer and java.lang.String are &lt;span class="k"&gt;in &lt;/span&gt;module java.base of loader &lt;span class="s1"&gt;'bootstrap'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        at ObjectAsCatchAllTypeProgram.main&lt;span class="o"&gt;(&lt;/span&gt;ObjectAsCatchAllTypeProgram.java:4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;strong&gt;ClassCastException&lt;/strong&gt; is thrown because we're trying to cast an &lt;code&gt;Integer&lt;/code&gt; object to a &lt;code&gt;String&lt;/code&gt; object. &lt;code&gt;Integer&lt;/code&gt; is not a subclass of &lt;code&gt;String&lt;/code&gt;, so the cast fails. This is a &lt;strong&gt;runtime error&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s explore another case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Oops, a null value?!?!&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
Exception &lt;span class="k"&gt;in &lt;/span&gt;thread &lt;span class="s2"&gt;"main"&lt;/span&gt; java.lang.NullPointerException: Cannot invoke &lt;span class="s2"&gt;"String.length()"&lt;/span&gt; because &lt;span class="s2"&gt;"&amp;lt;local2&amp;gt;"&lt;/span&gt; is null
        at ObjectAsCatchAllTypeProgram.main&lt;span class="o"&gt;(&lt;/span&gt;ObjectAsCatchAllTypeProgram.java:5&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;strong&gt;NullPointerException&lt;/strong&gt; occurs because we're trying to call a method on a null reference.&lt;/p&gt;

&lt;p&gt;You might think, "I can easily fix this using a try-catch block or the &lt;code&gt;instanceof&lt;/code&gt; operator." Let’s try to handle it with both approaches:&lt;/p&gt;

&lt;p&gt;Using a &lt;code&gt;try-catch&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Oops, a null value?!?!&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NullPointerException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"infoA cannot be cast because it's null"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ClassCastException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"infoA cannot be cast to String"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
infoA cannot be cast because it&lt;span class="s1"&gt;'s null
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;instanceof&lt;/code&gt; operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Oops, a null value?!?!&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"infoA cannot be cast to String"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
infoA cannot be cast to String
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While these strategies can help, they are not practical to use every time you need to interact with an object.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;instanceof&lt;/code&gt; is a good practice when you need to check the type of an object before casting it. However, it can make your code more complex and harder to read. The &lt;code&gt;try-catch&lt;/code&gt; block is useful for handling exceptions, but it can also make your code more verbose and harder to maintain.&lt;/p&gt;

&lt;p&gt;If you're using Java 14 or above, we can use the Pattern Matching for Instanceof (&lt;a href="https://openjdk.java.net/jeps/305" rel="noopener noreferrer"&gt;JEP305&lt;/a&gt;) feature. Such built-in language enhancement helps us to write better and more readable code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectAsCatchAllTypeProgram&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;infoA&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// more concise, isn't it? :-)&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"infoA cannot be cast to String"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java ObjectAsCatchAllTypeProgram.java
infoA cannot be cast to String
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;We learned that being declaring variables as &lt;code&gt;java.lang.Object&lt;/code&gt; is generally considered bad practice unless there is a specific, compelling reason. Using &lt;code&gt;Object&lt;/code&gt; sacrifices type safety, readability, and maintainability. In most cases, it’s better to use a more specific type to take full advantage of Java's strong typing system.&lt;/p&gt;

&lt;p&gt;During our exploration, we discovered that &lt;strong&gt;compilation errors&lt;/strong&gt; and &lt;strong&gt;runtime errors&lt;/strong&gt; can occur when using &lt;code&gt;Object&lt;/code&gt; as a catch-all type. Let’s recap the differences between these two types of errors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compilation errors&lt;/strong&gt; happen during the compilation phase when the code cannot be converted into bytecode. These errors prevent the program from running.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Runtime errors&lt;/strong&gt; occur after successful compilation and can cause the program to behave unpredictably or crash. Runtime errors are typically more problematic because they can affect production environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While both types of errors indicate issues, &lt;strong&gt;runtime errors&lt;/strong&gt; are usually more severe because they can affect users and cause unexpected behavior, while &lt;strong&gt;compilation errors&lt;/strong&gt; are easier to resolve during development.&lt;/p&gt;

&lt;p&gt;A good practice is to implement a good error handling strategy to deal with runtime errors, capturing the exceptions and logging them properly to help you debug and fix the issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;p&gt;Through this content, we explored the challenges of using &lt;code&gt;Object&lt;/code&gt; as a catch-all type. We learned that using &lt;code&gt;Object&lt;/code&gt; can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of type safety:&lt;/strong&gt; The compiler doesn't know the specific type of an object declared as &lt;code&gt;Object&lt;/code&gt;, so it can't catch type-related errors at compile time. This can lead to runtime errors when interacting with the object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The need for explicit casting:&lt;/strong&gt; To interact with an object as its specific type, you need to cast it to that type. This can make your code more complex and harder to read.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Susceptibility to runtime errors:&lt;/strong&gt; Using &lt;code&gt;Object&lt;/code&gt; as a catch-all type can lead to runtime errors, such as &lt;code&gt;ClassCastException&lt;/code&gt; and &lt;code&gt;NullPointerException&lt;/code&gt;. These errors can be difficult to track, debug, and fix, especially in large codebases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The need for additional error handling:&lt;/strong&gt; To prevent runtime errors, you might need to use &lt;code&gt;try-catch&lt;/code&gt; blocks or the &lt;code&gt;instanceof&lt;/code&gt; operator. While these strategies can help, they can make your code more verbose and harder to maintain. I recommend using a good error handler strategy to deal with runtime errors, capturing the exceptions and logging them properly to help you debug and fix the issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Not always using &lt;code&gt;Object&lt;/code&gt; as catch-all type is the best solution. In some cases, using &lt;code&gt;Object&lt;/code&gt; can be more appropriate. For example, when you have no control over the type of object that will be manipulated. However, it is important to understand the limitations and challenges associated with using &lt;code&gt;Object&lt;/code&gt; and know when it is appropriate to use it. &lt;/p&gt;

&lt;p&gt;When questions about what's right or wrong in the software development area comes to any discussion, we use to see developers answering like that: "It depends on the context that you're handling with." And they are right! &lt;/p&gt;

&lt;p&gt;But, once you know the context, "it depends" is not so valid answer. The problem context should guide us to make a good decision!&lt;/p&gt;

&lt;p&gt;So, I recommend you favor using more specific types whenever possible to take full advantage of Java's strong typing system. This will help you write more readable, maintainable, and reliable code.&lt;/p&gt;

&lt;p&gt;What do you think about using &lt;code&gt;Object&lt;/code&gt; as a catch-all type in Java? Do you have any experiences or best practices to share? Feel free to leave your thoughts in the comments below!&lt;/p&gt;

&lt;h3&gt;
  
  
  Next steps
&lt;/h3&gt;

&lt;p&gt;Congratulations on reaching the end of this content! I hope you found it informative and helpful.&lt;/p&gt;

&lt;p&gt;The learned concepts in this content are essential for understanding the motivation behind using generics in Java. Generics are a powerful feature that allows you to write more flexible, type-safe code by providing compile-time type checking. &lt;/p&gt;

&lt;p&gt;Did you like this content? If so, please share it with your friends and colleagues. I'm accepting subject suggestions for the next and future contents, so, feel free to suggest in the comments, okay?&lt;/p&gt;

&lt;p&gt;Also, don't forget to follow me on social media to stay up to date with the latest content and updates.&lt;br&gt;
See you in the next content!&lt;/p&gt;

</description>
      <category>java</category>
      <category>beginners</category>
      <category>studies</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>[PT-BR] Transformando listas com Java Stream API</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Tue, 13 Sep 2022 17:05:06 +0000</pubDate>
      <link>https://dev.to/dearrudam/pt-br-transformando-listas-com-java-stream-api-4c2c</link>
      <guid>https://dev.to/dearrudam/pt-br-transformando-listas-com-java-stream-api-4c2c</guid>
      <description>&lt;p&gt;E aí pessoal! Espero que todos estejam bem!!!&lt;/p&gt;

&lt;p&gt;Bom, após descansar do &lt;a href="https://thedevconf.com/tdc/2022/business/" rel="noopener noreferrer"&gt;&lt;strong&gt;TDC Business 2022&lt;/strong&gt;&lt;/a&gt;, onde tive a honra e a felicidade de realizar um sonho: ser coordenador na trilha de Carreira e Mentoria, ser expositor da empresa em que trabalho (&lt;a href="https://stackspot.com" rel="noopener noreferrer"&gt;StackSpot&lt;/a&gt;) e ser palestrante na trilha de arquitetura Java, falando sobre &lt;strong&gt;Streams API&lt;/strong&gt; junto com &lt;a href="https://www.linkedin.com/in/rolmertelis/" rel="noopener noreferrer"&gt;Rolmer Telis de Oliveria&lt;/a&gt;, estou de volta explorando, estudando e aprendendo cada vez mais sobre &lt;strong&gt;Programação Funcional com Java&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No artigo anterior, vimos que a partir do Java 8, a interface &lt;code&gt;Iterable&lt;/code&gt; foi melhorada com um método especial: um  &lt;strong&gt;default method&lt;/strong&gt; chamado &lt;code&gt;forEach&lt;/code&gt;. Agora, caso estivermos trabalhando com objetos que implementam a interface &lt;code&gt;Iterable&lt;/code&gt;, poderemos usufruir desse método para iterar nos itens de maneira declarativa, utilizando uma &lt;em&gt;lambda expression&lt;/em&gt; ou &lt;em&gt;method references&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas o que são Default Methods
&lt;/h2&gt;

&lt;p&gt;A feature &lt;strong&gt;default method&lt;/strong&gt;, que foi adicionado ao Java 8, permitiu uma evolução suave de toda a API do Java, permitindo &lt;em&gt;métodos padrões&lt;/em&gt; fossem implementados em interfaces, mantendo assim toda uma retro-compatibilidade das versões anteriores do Java. &lt;/p&gt;

&lt;p&gt;Com isso, podemos dizer que todos objetos que implementam a interface &lt;code&gt;Iterable&lt;/code&gt; poderão usufruir do método &lt;code&gt;forEach&lt;/code&gt;, já que esse é um &lt;strong&gt;default method&lt;/strong&gt;, implementado na própria interface &lt;code&gt;Iterable&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Muito mais que iterar em uma lista
&lt;/h2&gt;

&lt;p&gt;Já conhecemos o método &lt;code&gt;forEach&lt;/code&gt;, na qual podemos iterar nos itens de uma determinada lista ou coleções, mas sabemos também que só iterar não nos basta! &lt;/p&gt;

&lt;p&gt;Sem dúvida, vamos ter que realizar operações muito mais complexas: como  filtrar, transformar ou modificar os dados dessas listas.&lt;/p&gt;

&lt;p&gt;Manipular coleções para produzir outros resultados é tão comum como iterar através dos elementos de uma coleção.&lt;/p&gt;

&lt;p&gt;Vamos dizer que precisamos pegar uma lista de produtos e pegar só os preços desses produtos. &lt;/p&gt;

&lt;p&gt;Abaixo segue o &lt;code&gt;Record&lt;/code&gt; que representará nosso produto:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PS&lt;/em&gt;: Vamos utilizar a especificação &lt;a href="http://javamoney.github.io/" rel="noopener noreferrer"&gt;JSR 354 Java Money&lt;/a&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MonetaryAmount&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E aqui está a lista de produtos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Monetary&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCurrency&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BRL"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bean"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.99&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"rice"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;12.49&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"coffee"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;18.99&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bread"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;6.59&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"chocolate"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;6.80&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
  &lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma vez que estamos utilizando uma lista imutável criada através do método &lt;code&gt;List.of&lt;/code&gt;, nós precisamos criar uma nova lista para armazenar esses preços. &lt;/p&gt;

&lt;p&gt;Utilizando uma abordagem imperativa, nós escreveríamos um código parecido com esse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MonetaryAmount&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="nl"&gt;product:&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
      &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Precisamos criar uma lista vazia para só então coletar todos os preços ao iterar pelos produtos da lista. Como primeiro passo para utilizar um estilo funcional, vamos usar o &lt;em&gt;internal interator&lt;/em&gt; &lt;code&gt;forEach&lt;/code&gt; fornecido pela interface &lt;code&gt;Iterable&lt;/code&gt;, como fizemos no &lt;a href="https://dev.to/dearrudam/pt-br-collections-foreach-lambda-expressions-o-que-sao-external-ou-internal-iterators-1e2m"&gt;&lt;em&gt;blogpost&lt;/em&gt; anterior&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MonetaryAmount&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
  &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estamos utilizando um &lt;em&gt;internal iterator&lt;/em&gt;, mas ainda há a necessidade de criar uma lista vazia e ainda assim adicionar os preços item a item. Que tal explorar um pouco uma abordagem mais funcional para solucionar esse detalhe?&lt;/p&gt;

&lt;h2&gt;
  
  
  Muito mais que um simples iterador!
&lt;/h2&gt;

&lt;p&gt;A criação de uma lista vazia e a manipulação explicita desta instância introduz variáveis mutáveis, o que deixam o nosso código mais propenso a erros, pois estamos, além de iterar pelos produtos, temos que nos preocupar em coletar só os preços e adicioná-los na nova lista: estamos instruindo nosso programa como a coleta deve ser feita ao invés de declarar qual é a informação que queremos coletar explicitamente. &lt;/p&gt;

&lt;p&gt;A partir do Java 8, a interface &lt;code&gt;Stream&lt;/code&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt; foi adicionada com o intuito de permitir a manipulação de coleções de maneira mais declarativa, mais funcional.&lt;/p&gt;

&lt;p&gt;A interface &lt;code&gt;Stream&lt;/code&gt; é muito mais que um simples iterador: ela fornece uma API fluente na qual nos permite, em conjunto com &lt;em&gt;Lambda Expressions&lt;/em&gt; e &lt;em&gt;Reference Methods&lt;/em&gt;, encadear operações que podem ou não utilizar &lt;strong&gt;objetos de função&lt;/strong&gt; afim de nos permitir executar tarefas como filtrar, mapear ou transformar, contar, reduzir e por aí vai.&lt;/p&gt;

&lt;p&gt;Graças aos &lt;strong&gt;default method&lt;/strong&gt;s, objetos que implementam uma &lt;code&gt;Collection&lt;/code&gt; detém o método &lt;code&gt;stream&lt;/code&gt; para adquirir instâncias do tipo &lt;code&gt;Stream&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Abaixo, vamos utilizar um &lt;code&gt;Stream&lt;/code&gt; a partir da lista de produtos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MonetaryAmount&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, um método chamado &lt;code&gt;map&lt;/code&gt; fornecido pela interface &lt;code&gt;Stream&lt;/code&gt; nos permitem mapear ou transformar cada item do &lt;code&gt;Stream&lt;/code&gt; no valor solicitado, nesse caso, o preço de cada produto. No passo seguinte, instruímos o &lt;code&gt;Stream&lt;/code&gt; para que, através do método &lt;code&gt;collect&lt;/code&gt;, colete o resultado como uma nova lista, e isso está sendo declarado através de uma instância do tipo &lt;code&gt;Collector&lt;/code&gt; fornecido através da chamada do método &lt;code&gt;toList&lt;/code&gt; da classe fábrica &lt;code&gt;Collectors&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Do ponto de vista de execução, você pode pensar que cada método, que representa uma operação, é executada de maneira &lt;strong&gt;eager&lt;/strong&gt;, ou seja, no momento da chamada da operação, mas isso não é verdade para alguns metodos da interface &lt;code&gt;Stream&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A interface &lt;code&gt;Stream&lt;/code&gt; fornece as &lt;strong&gt;operações intermediárias&lt;/strong&gt; e &lt;strong&gt;operações terminadoras&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;As &lt;strong&gt;operações intermediárias&lt;/strong&gt; são operações &lt;strong&gt;lazy&lt;/strong&gt;, isto é, elas só são performadas quando uma operação terminal é executada. &lt;/p&gt;

&lt;p&gt;Já as &lt;strong&gt;operações terminadoras&lt;/strong&gt; são responsáveis por efetivamente desencadear toda as operações encadeadas através da interface fluente &lt;code&gt;Stream&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;O encadeamento dessas operações ocorre com uma ou várias operações intermediárias em conjunto com uma operação terminal, formando assim o &lt;strong&gt;Stream Pipeline&lt;/strong&gt;. Vamos conhecer mais sobre a interface &lt;code&gt;Stream&lt;/code&gt; em blogposts futuros! 😉&lt;/p&gt;

&lt;p&gt;Em nosso exemplo, a operação &lt;code&gt;map&lt;/code&gt; é uma operação intermediária, e ela só será disparada quando alguma operação terminal for executada, no nosso caso, a operação &lt;code&gt;collect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora, em nosso exemplo, não estamos lidando mais com váriaveis mutáveis, e assim deixando declarativo o que queremos. Não precisamos mais criar uma lista vazia. Todas essas preocupações estão sendo controladas e delegadas para a implementação fornecida pela API do Java.&lt;/p&gt;

&lt;p&gt;Mas podemos também utilizar no lugar da &lt;em&gt;Lambda Expression&lt;/em&gt; um &lt;em&gt;Method Reference&lt;/em&gt;, diminuindo ainda mais a chance de algum possível erro na lógica de dentro da declaração da expressão. Vejamos como fica o resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MonetaryAmount&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Product:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Talvez, você deve estar se perguntando: &lt;/p&gt;

&lt;h3&gt;
  
  
  Quando devemos utilizar Method References?
&lt;/h3&gt;

&lt;p&gt;Nós normalmente utilizamos muito mais &lt;em&gt;lambda expressions&lt;/em&gt; do que &lt;em&gt;method references&lt;/em&gt; quando estamos programando em Java. Mas isso não significa que &lt;em&gt;method references&lt;/em&gt; não são importantes ou menos útil. &lt;/p&gt;

&lt;p&gt;Se uma &lt;em&gt;lambda expression&lt;/em&gt; simplesmente repassa os parâmetros para outro método, mesmo sendo um método de uma instância ou estático, podemos substitui-la pelo método em questão, referenciando-o, por isso o nome &lt;em&gt;method reference&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Além de deixar o código conciso do que utilizando &lt;em&gt;lambda expressions&lt;/em&gt;, ao utilizar &lt;em&gt;method reference&lt;/em&gt; ganhamos a habilidade de utilizar métodos nomeados, e assim facilitar a compreensão do código.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mas e quanto a performance?
&lt;/h3&gt;

&lt;p&gt;Como já sabemos, a linguagem Java já tem um longo caminho e é usada em um grande número de aplicativos corporativos onde o desempenho é crítico. Mas mesmo sabendo disso, é muito razoável questionar se as novas features afetarão o desempenho. &lt;/p&gt;

&lt;p&gt;A resposta é sim, mas principalmente para melhor! Pode parecer ingênuo essa afirmação a princípio, mas antes de discutirmos sobre melhorias de desempenho, vamos lembrar as sábias palavras de Donald Knuth:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Traduzindo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Devemos esquecer as pequenas eficiências, digamos que cerca de 97% das vezes: a otimização prematura é a raiz de todo o mal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Com isso em mente, devemos ser ousados em experimentar novos estilos onde eles podem fazer sentido. Se, ao utilizar o novo estilo e esse atender o desempenho adequado às necessidades da aplicação, então podemos adotá-lo e seguir em frente, caso contrário, devemos avaliar de forma crítica o design de código afim de encontrar os gargalos reais que o código está apresentando. &lt;/p&gt;

&lt;p&gt;As especificações inseridas a partir do Java 8 fornecem um grande flexibilidade para facilitar as otimizações do compilador. Essas otimizações em conjunto com a instrução otimizada do bytecode &lt;em&gt;InvokeDynamic&lt;/em&gt; podem fazer com que as chamadas utilizando &lt;em&gt;Lambda Expressions&lt;/em&gt; sejam bem rápidas.  &lt;/p&gt;

&lt;p&gt;Vamos fazer um teste sobre performance.&lt;/p&gt;

&lt;p&gt;Abaixo, temos um código imperativo que contam os números primos em uma coleção de números:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isPrime&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utilizamos no examplo o habitual &lt;code&gt;for loop&lt;/code&gt; para invocar um método &lt;code&gt;isPrime&lt;/code&gt; para determinar se cada número na coleção é um número primo. Se ele for primo, nós incrementamos a variável &lt;code&gt;count&lt;/code&gt;. Vamos medir o tempo considerando uma lista de 1.000.000 (um milhão) de números.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  PT0.163687193S
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso levou aproximadamente &lt;strong&gt;0.163&lt;/strong&gt; segundos, mas vamos reduzir esse código; vamos ver ver se utilizando um novo estilo que queremos adotar bate esse desempenho. Vamos refatorar o código para o estilo funcional: onde o código é declarativo, é criado favorecendo a imutabilidade, não tem efeitos colaterais, seguindo um encadeamento de funções de primeira ordem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
         &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isPrime&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
         &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui, transformamos a coleção em um &lt;code&gt;Stream&lt;/code&gt; e então aplicamos um filtro através de uma operação intermediária, &lt;code&gt;filter&lt;/code&gt;, declarando que queremos somente os números primos da coleção, e finalmente efetuamos o cálculo ao performar a operação terminal &lt;code&gt;count&lt;/code&gt;. Vamos ver quanto tempo essa versão levou para executar a mesma lógica na mesma coleção de 1.000.000 (um milhão) de números:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; PT0.167082778S
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A saída, como podemos ver, utilizando &lt;em&gt;lambda expression&lt;/em&gt;, foi aproximadamente o mesmo: &lt;strong&gt;0.167&lt;/strong&gt; segundos; Pode parecer que não ganhamos ou perdemos nada, mas na verdade, ganhamos muito sim!&lt;/p&gt;

&lt;p&gt;É algo trivial paralelizar códigos desenvolvidos utilizando o estilo funcional, agora paralelizar um código imperativo, por outro lado, se ele já não foi arquitetado para esse fim, provavelmente não será algo tão trivial assim, não é?&lt;/p&gt;

&lt;p&gt;Segue uma versão utilizando o estilo funcional e paralelizada de nosso código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parallelStream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
              &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isPrime&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
              &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com praticamente nenhum esforço, apenas chamando um outro &lt;em&gt;default method&lt;/em&gt; chamado &lt;code&gt;parallelStream&lt;/code&gt; da classe &lt;code&gt;Collection&lt;/code&gt;, que também fornece uma instância de &lt;code&gt;Stream&lt;/code&gt;, habilitamos o paralelismo. Vamos ver se tivemos ganho de desempenho executando esse código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; PT0.055318673S
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando essa versão paralelizada, em um processador com 8 núcleos, utilizando Java 17, levou aproximadamente &lt;strong&gt;0.055&lt;/strong&gt; segundos para executar a tarefa.&lt;/p&gt;

&lt;p&gt;Bom, brincadeiras à parte, antes de comemorarmos essa performance, temos que admitir que um grande número de métricas de desempenho podem ser artificiais e não podemos confiar cegamente neles. O que esse exemplo quer demonstrar nada mais é que o uso de lambda expressions e o estilo funcional não significam desempenho ruim. Sempre ao criar código real para aplicações corporativas, devemos ficar de olho no desempenho e tratar as preocupações onde elas surgirem.&lt;/p&gt;

&lt;h3&gt;
  
  
  E é isso aí pessoal👍 ...
&lt;/h3&gt;

&lt;p&gt;Estou curtindo demais ler o livro do renomado &lt;strong&gt;Venkat Subramaniam&lt;/strong&gt; : &lt;strong&gt;"Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expression"&lt;/strong&gt; &lt;sup id="fnref3"&gt;3&lt;/sup&gt;, então vou continuar a publicar mais blogposts com o intuido de fixar meu aprendizado e assim também ajudar quem interessar!&lt;/p&gt;

&lt;p&gt;Espero que tenha gostado do texto! 😄&lt;/p&gt;

&lt;p&gt;Se gostou e achou relevante esse conteúdo, compartilhe com seus amigos.😉&lt;/p&gt;

&lt;p&gt;Críticas e sugestões serão sempre bem-vindos!!!&lt;/p&gt;

&lt;p&gt;No próximo blogpost, vamos conhecer mais sobre &lt;strong&gt;Stream API&lt;/strong&gt;, seu funcionamento, seu pipeline, suas operações e detalhes entre outras coisas...&lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;

&lt;h3&gt;
  
  
  Source dos exemplos &lt;sup id="fnref4"&gt;4&lt;/sup&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/GettingProductPrices.java" rel="noopener noreferrer"&gt;GettingProductPrices.java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/CheckingPerformance.java" rel="noopener noreferrer"&gt;CheckingPerformance.java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Referências:
&lt;/h3&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Estou usando &lt;a href="http://javamoney.github.io/" rel="noopener noreferrer"&gt;JSR 354 Java Money&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Javadoc - &lt;a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/stream/package-summary.html" rel="noopener noreferrer"&gt;Package java.util.stream&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Livro - &lt;a href="https://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/" rel="noopener noreferrer"&gt;"Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expression" by Venkat Subramaniam&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;Estou usando &lt;a href="https://www.jbang.dev/" rel="noopener noreferrer"&gt;JBang&lt;/a&gt;; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>java</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>[PT-BR] Collections, forEach, Lambda Expressions - o que são external ou internal iterators?</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Mon, 15 Aug 2022 11:38:50 +0000</pubDate>
      <link>https://dev.to/dearrudam/pt-br-collections-foreach-lambda-expressions-o-que-sao-external-ou-internal-iterators-1e2m</link>
      <guid>https://dev.to/dearrudam/pt-br-collections-foreach-lambda-expressions-o-que-sao-external-ou-internal-iterators-1e2m</guid>
      <description>&lt;p&gt;É muito comum utilizarmos estruturas de dados para nos ajudar a atender as necessidades requeridas em nossas aplicações. Uma dessas estruturas são as &lt;em&gt;collections&lt;/em&gt;. Elas são tão comuns que remover até mesmo uma pequena quantidade de cerimônia para operá-las traria um grande ganho na redução de possíveis confusões que podem aparecer em nossos códigos.&lt;/p&gt;

&lt;p&gt;Vamos explorar como podemos utilizar as &lt;code&gt;Lambda Expressions&lt;/code&gt; para manipular essas tais coleções. Com elas podemos, de uma forma declarativa, filtrar dados, realizar transformações, criar novas coleções, concatenar elementos, entre outras operações. &lt;/p&gt;

&lt;h2&gt;
  
  
  Iterando em Coleções
&lt;/h2&gt;

&lt;p&gt;Iterar por meio de uma lista é uma operação básica nas coleções (&lt;code&gt;collection&lt;/code&gt;), e ao longo dos anos, essa operação também sofreu mudanças significativa dentro da linguagem Java.&lt;/p&gt;

&lt;p&gt;Vamos começar com um exemplo - enumerando uma lista de nomes - utilizando uma abordagem mais antiga e seguir evoluindo até uma versão onde a escrita dessa operação apresente uma forma mais concisa e elegante.&lt;/p&gt;

&lt;p&gt;Aqui criamos uma coleção imutável de lista de nomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;developers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
              &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
              &lt;span class="s"&gt;"Otavio Santana"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
              &lt;span class="s"&gt;"Bruno Souza"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
              &lt;span class="s"&gt;"Elder Moraes"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
              &lt;span class="s"&gt;"Sérgio Lopes"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
              &lt;span class="s"&gt;"Fernando Boaglio"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abaixo, uma forma de iterar e escrever cada item no console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Provavelmente, alguma vez, durande a escrita de um laço &lt;code&gt;for&lt;/code&gt; conforme escrito acima, vc se deparou questionando: é &lt;code&gt;i &amp;lt;&lt;/code&gt; ou &lt;code&gt;i &amp;lt;=&lt;/code&gt;. Essa abordagem é bem verbosa e propensa a erros, e outra, ela só é útil se precisarmos manipular elementos em um particular índice na coleção.&lt;/p&gt;

&lt;p&gt;Uma outra forma que o Java também oferece do que o &lt;em&gt;bom e velho &lt;code&gt;for&lt;/code&gt;&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nl"&gt;developer:&lt;/span&gt; &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por baixo do capô, essa forma utiliza a interface &lt;code&gt;Iterator&lt;/code&gt; para iterar entre os itens, chamando o método &lt;code&gt;hasNext&lt;/code&gt; para saber quando parar de iterar, e o método &lt;code&gt;next&lt;/code&gt; para capturar o item na posição corrente.&lt;/p&gt;

&lt;p&gt;Nesses dois casos, são utilizados &lt;em&gt;iteradores externos&lt;/em&gt; (&lt;strong&gt;external iterators&lt;/strong&gt; &lt;sup id="fnref1"&gt;1&lt;/sup&gt;). &lt;/p&gt;

&lt;p&gt;No primeiro exemplo, precisamos explicitamente controlar a iteração, indicando onde começar e onde parar; Já no segundo, essas mesmas operações acontecem &lt;em&gt;por baixo dos panos&lt;/em&gt; utilizando os métodos da interface &lt;code&gt;Iterator&lt;/code&gt;. E mais, através desse controle explícito, podemos utilizar as declarações &lt;code&gt;break&lt;/code&gt; e &lt;code&gt;continue&lt;/code&gt; para gerenciar o fluxo de controle da execução da iteração. &lt;/p&gt;

&lt;p&gt;Com &lt;strong&gt;external iterators&lt;/strong&gt;, instruimos o programa &lt;strong&gt;COMO&lt;/strong&gt; fazer a iteração para que, só então atingir o &lt;strong&gt;QUE&lt;/strong&gt; queremos no final das contas.&lt;/p&gt;

&lt;p&gt;Já no segundo exemplo, iteramos entre os elementos da coleção com menos &lt;em&gt;cerimônia&lt;/em&gt; do que a primeira versão. Essa estrutura só é melhor do que a primeira quando não temos a intenção de acessar ou modificar a coleção baseada em índices e posições específicas , porém, ambas utilizam um estilo imperativo e nós podemos dispensar essa abordagem uma vez que podemos utilizar o estilo funcional.&lt;/p&gt;

&lt;p&gt;Há boas razões a favor de mudar do estilo imperativo para o estilo funcional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loops utilizando &lt;code&gt;for&lt;/code&gt; são inerentemente sequenciais e são difíceis de paralelizar;&lt;/li&gt;
&lt;li&gt;Tais loops são &lt;strong&gt;&lt;em&gt;non-polymorphic&lt;/em&gt;&lt;/strong&gt;, isto é, temos que passar a coleção na instrução do &lt;code&gt;for&lt;/code&gt; ao invés de executar algum método (que pode usufruir do polimorfismo por baixo dos panos) na coleção para executar a tarefa.&lt;/li&gt;
&lt;li&gt;No nível de design, o princípio &lt;strong&gt;"Tell, don't ask"&lt;/strong&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt; cai por terra! Nós solicitamos a execução de uma específica iteração ao invés de deixar esses detalhes da iteração para a biblioteca de nível mais baixo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dito isso, vamos utilizar o estilo funcional no lugar do imperativo, e assim utilizar &lt;em&gt;iteradores internos&lt;/em&gt; (&lt;strong&gt;internal iterators&lt;/strong&gt; &lt;sup id="fnref1"&gt;1&lt;/sup&gt;). &lt;/p&gt;

&lt;p&gt;Com uma &lt;strong&gt;internal iterators&lt;/strong&gt;, nós deixamos a maioria das instruções de &lt;strong&gt;COMO&lt;/strong&gt; fazer tal iteração para a biblioteca de nível mais baixo e focamos no &lt;strong&gt;QUE&lt;/strong&gt; queremos realizar durante a iteração. &lt;/p&gt;

&lt;p&gt;A interface &lt;code&gt;Iterable&lt;/code&gt; foi melhorada no Java 8 com um método especial chamado &lt;code&gt;forEach&lt;/code&gt;, que aceita um parâmetro do tipo &lt;code&gt;Consumer&lt;/code&gt;. Como o próprio nome indica, uma instância do tipo &lt;code&gt;Consumer&lt;/code&gt; irá consumir o que for passado pra ele através do seu método &lt;code&gt;accept&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nd"&gt;@Override&lt;/span&gt;
      &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao trocar a utilização do velho &lt;code&gt;for&lt;/code&gt; pelo novo &lt;em&gt;internal iterator&lt;/em&gt; &lt;sup id="fnref1"&gt;1&lt;/sup&gt; &lt;code&gt;forEach&lt;/code&gt; ganhamos o benefício de não necessitar focar em como iterar na coleção em questão e sim em no que fazer a cada iteração. O código aplica o princípio &lt;strong&gt;Tell, don't ask&lt;/strong&gt; de maneira satisfatória.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Espere um pouco, essa interface &lt;code&gt;Consumer&lt;/code&gt; não é uma interface funcional!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Exato! Com isso podemos utilizar Lambda Expressions ao invés de implementar uma classe anônima! &lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;forEach&lt;/code&gt; é um método que aplica o pilar &lt;em&gt;higher-order function&lt;/em&gt;, onde nos permite oferecer uma Lambda Expression ou um bloco de código que irá executar dentro do contexto de cada elemento da lista. A variável &lt;code&gt;developer&lt;/code&gt; será vinculada a cada elemento da coleção durante sua chamada. &lt;/p&gt;

&lt;p&gt;Assim, a implementação por baixo dos panos deste método terá o controle de como iterar e como executar o objeto de função recebido como argumento. Encapsular a implementação atrás de métodos como esse permitem que implementações como essas possam também poderá decidir vários aspectos interessantes, como se a execução deve ser ou não &lt;em&gt;preguiçosa&lt;/em&gt; (&lt;strong&gt;lazy&lt;/strong&gt;), ou definir a ordem dos itens durante a iteração, ou até explorar o paralelismo como achar melhor. Esse é o poder do &lt;em&gt;encapsulamento&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
                            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A sintaxe padrão de Lambda Expressions espera que os parâmetros estejam junto com seu tipo definido entre parênteses e separado por vírgulas, mas o compilador Java também oferece a &lt;em&gt;inferência de tipos&lt;/em&gt; &lt;sup id="fnref3"&gt;3&lt;/sup&gt; &lt;sup id="fnref4"&gt;4&lt;/sup&gt; &lt;sup id="fnref5"&gt;5&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Baseado na assinatura do método da interface que a Lambda Expression está implementando, o compilador é capaz de detectar qual é o tipo do parâmetro em questão e efetuar sua inferência.&lt;/p&gt;

&lt;p&gt;Vamos usufruir da inferência de tipos em nosso exemplo tirando a declaração:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
                            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim, baseado no contexto do método, o compilador sabe determinar o tipo do parâmetro que está sendo fornecido.&lt;/p&gt;

&lt;p&gt;Para casos onde há multiplos parâmetros, podemos seguir o mesmo princípio, não declarar o tipo de cada parâmetro, mas se precisarmos especificar o tipo de um parâmetro, precisaremos especificar o tipo de todos os parâmentros, isto é, ou declara nenhum ou declara todos os tipos de cada parâmetros.&lt;/p&gt;

&lt;p&gt;Para casos onde só há um parâmetro, o compilador Java não exige que o parâmetro esteja dentro de parenteses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
                            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mas uma resalva:&lt;/strong&gt; parâmetros inferidos são &lt;strong&gt;non-final&lt;/strong&gt;. Em um dos exemplos anteriores, escrevemos uma &lt;em&gt;Lambda Expression&lt;/em&gt; onde além de explicitamente definir o tipo do parâmetro, nós também definimos que o parâmetro deve ser &lt;code&gt;final&lt;/code&gt;. Isso instrui o compilador a nos alertar caso o parâmetro for modificado dentro da &lt;em&gt;Lambda Expression&lt;/em&gt;. De modo geral, modificar parâmetros é algo ruim que pode conduzir a erros, então defini-los com &lt;code&gt;final&lt;/code&gt; é uma boa prática.&lt;/p&gt;

&lt;p&gt;Infelizmente, quando favorecemos a inferência de tipos na declaração dos parâmetros em uma Lambda Expressions, temos que ter uma disciplina extra em não modificar os parâmetros, pois o compilador não poderá nos ajudar nesses casos. &lt;/p&gt;

&lt;h2&gt;
  
  
  Reduzindo código com Method References
&lt;/h2&gt;

&lt;p&gt;Vimos até agora exemplos com Lambda Expressions, porém há mais um passo que podemos dar para deixar o codigo mais conciso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No último código de exemplo nós usamos um &lt;strong&gt;&lt;em&gt;Method Reference&lt;/em&gt;&lt;/strong&gt;. O Java nos deixa, de maneira simples, substituir o corpo de código com um método nomeado de nossa escolha. Vamos olhar com mais detalhes sobre &lt;em&gt;Method Reference&lt;/em&gt; em artigos futuros, no worries! 😉&lt;/p&gt;

&lt;p&gt;Como não existe &lt;strong&gt;bala de prata&lt;/strong&gt;, utilizar &lt;code&gt;forEach&lt;/code&gt; também tem suas limitações. Uma vez que começa o método, diferentemente das versões que utilizam &lt;code&gt;for&lt;/code&gt;, a iteração não podem ser interrompidas. Como consequência, esse estilo é útil em casos comuns onde nós queremos processar cada elemento de uma coleção.  &lt;/p&gt;

&lt;p&gt;No próximo artigo, vamos ver como &lt;code&gt;Lambda Expressions&lt;/code&gt; podem nos ajudar a lidar com a mutabilidade e deixar nosso código mais conciso durante operações de transformação com coleções...spoiler: &lt;strong&gt;Streams API 🚀 !!!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Obrigado a todos e até o próximo artigo!!!&lt;/p&gt;

&lt;h3&gt;
  
  
  Source dos exemplos &lt;sup id="fnref6"&gt;6&lt;/sup&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/Iteration.java" rel="noopener noreferrer"&gt;Iteration.java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Referências:
&lt;/h3&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Livro:&lt;a href="https://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/" rel="noopener noreferrer"&gt;"Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expression" by Venkat Subramaniam&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://martinfowler.com/bliki/TellDontAsk.html#:~:text=Tell%2DDon't%2DAsk,an%20object%20what%20to%20do." rel="noopener noreferrer"&gt;&lt;strong&gt;Tell-Don't-Ask Principle&lt;/strong&gt; by Martin Fowler&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://openjdk.org/jeps/323" rel="noopener noreferrer"&gt;JEP 323: Local-Variable Syntax for Lambda Parameters&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://openjdk.org/jeps/286" rel="noopener noreferrer"&gt;JEP 286: Local-Variable Type Inference&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://www.alura.com.br/artigos/java-9-na-pratica-inferencia-de-tipos" rel="noopener noreferrer"&gt;Arquivo: Java 9 na prática: Inferência de tipos&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;&lt;a href="https://www.jbang.dev/" rel="noopener noreferrer"&gt;JBang&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>java</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>[PT-BR] Functional Interfaces, a fundação para a programação funcional com Java</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Mon, 08 Aug 2022 13:04:18 +0000</pubDate>
      <link>https://dev.to/dearrudam/pt-br-functional-interfaces-a-fundacao-para-a-programacao-funcional-com-java-3c0e</link>
      <guid>https://dev.to/dearrudam/pt-br-functional-interfaces-a-fundacao-para-a-programacao-funcional-com-java-3c0e</guid>
      <description>&lt;p&gt;No último post vimos como implementar o pattern EAM (&lt;em&gt;Execute Around Method&lt;/em&gt;) no Java através das &lt;strong&gt;Lambdas Expressions&lt;/strong&gt;, e vimos também que esse pattern utiliza um dos pilares da programação funcional chamado &lt;em&gt;Higher-order functions&lt;/em&gt; para prover a sua solução. &lt;/p&gt;

&lt;p&gt;É através dos objetos de função podemos aplicar o pilar &lt;em&gt;Higher-order functions&lt;/em&gt; no Java, pois podemos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passar objetos de função como argumentos nos métodos;&lt;/li&gt;
&lt;li&gt;Criar objetos de função dentro dos métodos e;&lt;/li&gt;
&lt;li&gt;Retornar objetos de função de métodos;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para escrever códigos que interajam com qualquer objeto, isso inclui os objetos de função, precisamos conhecer o seu tipo, o seu contrato. Comumente, utilizamos interfaces para definir esse contrato, que é onde definimos os métodos que podemos chamar das instâncias baseadas nas classes que implementam esse tal contrato. O mesmo acontece quando queremos interagir com uma váriavel, precisamos conhecer qual é o seu tipo.&lt;/p&gt;

&lt;p&gt;Inevitavelmente, ao escrever nossos métodos precisamos definir, em suas assinaturas, os tipos dos argumentos que ele suporta e, se caso retornem algum objeto, precisamos também declarar qual é seu tipo. O mesmo se aplica a métodos que recebem ou devolvam objetos de função, isto é, será necessário declarar seu tipo, a sua interface. &lt;/p&gt;

&lt;p&gt;Objetos de função que são criados através de &lt;em&gt;lambda expressions&lt;/em&gt; ou &lt;em&gt;method references&lt;/em&gt; (sim, vamos ver isso no futuro!😉), devem implementar interfaces especiais, as interfaces funcionais (&lt;strong&gt;Functional Interfaces&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;As interfaces funcionais são interfaces que tem um único método abstrato para ser implementado e que podem ou não ter vários métodos estáticos ou &lt;em&gt;default&lt;/em&gt; methods que estão implementados na própria interface. &lt;/p&gt;

&lt;p&gt;Interfaces bem conhecidas &lt;code&gt;Runnable&lt;/code&gt;, &lt;code&gt;Callable&lt;/code&gt;, &lt;code&gt;Comparable&lt;/code&gt;, entre outras que combinam com essa essa definição, são também tratadas como interfaces funcionais.&lt;/p&gt;

&lt;p&gt;Você pode ficar atentado a criar suas interfaces funcionais, mas uma boa prática é utilizar as interfaces funcionais padrão fornecidas pelo pacote &lt;code&gt;java.util.function&lt;/code&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt; uma vez que alguma atenda sua necessidade. &lt;/p&gt;

&lt;p&gt;As interfaces funcionais são a fundação para a utilização das &lt;em&gt;Lambdas Expressions&lt;/em&gt; e &lt;em&gt;Method References&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conhecendo as interfaces funcionais mais utilizadas!
&lt;/h2&gt;

&lt;p&gt;A biblioteca padrão do Java tem aproximadamente &lt;strong&gt;43&lt;/strong&gt; interfaces funcionais no pacote &lt;code&gt;java.util.function&lt;/code&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt; para facilitar a vida do desenvolvedor.&lt;/p&gt;

&lt;p&gt;Abaixo podemos conferir uma lista com &lt;strong&gt;seis&lt;/strong&gt; interfaces básicas que frequentemente iremos encontrar e, por esse motivo, é importante ficarmos familiarizados com elas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumer&amp;lt;T&amp;gt;&lt;/li&gt;
&lt;li&gt;Supplier&amp;lt;T&amp;gt;&lt;/li&gt;
&lt;li&gt;Predicate&amp;lt;T&amp;gt;&lt;/li&gt;
&lt;li&gt;
Function&amp;lt;T,R&amp;gt;
&lt;/li&gt;
&lt;li&gt;
UnaryOperator&amp;lt;T&amp;gt;
&lt;/li&gt;
&lt;li&gt;BinaryOperator&amp;lt;T&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;Há também &lt;em&gt;três&lt;/em&gt; variantes para cada uma dessas &lt;em&gt;seis&lt;/em&gt; interfaces funcionais básicas que operam com os seguintes tipos primitivos &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt; e &lt;code&gt;double&lt;/code&gt;. Essas são as &lt;em&gt;Primitive Specializations&lt;/em&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;As &lt;em&gt;Primitive Specializations&lt;/em&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt; foram adicionadas para remover a necessidade de se lidar com &lt;code&gt;autoboxing&lt;/code&gt;&lt;sup id="fnref3"&gt;3&lt;/sup&gt; e &lt;code&gt;unboxing&lt;/code&gt;&lt;sup id="fnref3"&gt;3&lt;/sup&gt; de tipos primitivos, e assim melhorar a performance da aplicação. Esses tipos não são parametrizados, exceto as variantes &lt;code&gt;Function&amp;lt;T,R&amp;gt;&lt;/code&gt; que devem ser parametrizadas. Por exemplo: &lt;code&gt;LongFunction&amp;lt;int[]&amp;gt;&lt;/code&gt; que recebe um &lt;code&gt;long&lt;/code&gt; e retorna um &lt;code&gt;int[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A interface &lt;code&gt;Function&amp;lt;T,R&amp;gt;&lt;/code&gt; tem nove variantes complementares que são utilizadas quando o tipo de retorno é primitivo. Já para funções que recebem o mesmo tipo como argumento e retorno, a interface &lt;code&gt;UnaryOperator&amp;lt;T&amp;gt;&lt;/code&gt; entra na cena. &lt;/p&gt;

&lt;p&gt;Para encontrar interfaces variantes complementares de &lt;code&gt;Function&amp;lt;T,R&amp;gt;&lt;/code&gt; para retornos que resultem em primitivos, basta procurar interfaces onde o nome segue o padrão &amp;lt;&lt;em&gt;Src&lt;/em&gt;&amp;gt;To&amp;lt;&lt;em&gt;Result&lt;/em&gt;&amp;gt;Function, por exemplo, &lt;em&gt;LongToIntFunction&lt;/em&gt;. Há &lt;strong&gt;seis&lt;/strong&gt; variantes para essa condição.&lt;/p&gt;

&lt;p&gt;Agora, para encontrar as interfaces variantes complementares de &lt;code&gt;Function&amp;lt;T,R&amp;gt;&lt;/code&gt; para parâmetros do tipo primitivo porém o retorno uma referência para um objeto, basta procurar as interfaces onde o nome segue o padrão &amp;lt;&lt;em&gt;Src&lt;/em&gt;&amp;gt;ToObjFunction, por exemplo, &lt;em&gt;LongToObjFunction&lt;/em&gt;. Há &lt;strong&gt;três&lt;/strong&gt; variantes para esse tipo de interface.&lt;/p&gt;

&lt;p&gt;Há também variações especiais para &lt;code&gt;Predicate&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Function&amp;lt;T,R&amp;gt;&lt;/code&gt; e &lt;code&gt;Consumer&amp;lt;T&amp;gt;&lt;/code&gt; onde ambas aceitam dois argumentos: &lt;code&gt;BiPredicate&amp;lt;T,U&amp;gt;&lt;/code&gt;, &lt;code&gt;BiFunction&amp;lt;T,U&amp;gt;&lt;/code&gt; e &lt;code&gt;BiConsumer&amp;lt;T,U&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BiFunction&amp;lt;T,U&amp;gt;&lt;/code&gt; também tem variantes que retornam os &lt;em&gt;três&lt;/em&gt; tipos primitivos relevantes: &lt;code&gt;ToIntBiFunction&amp;lt;T,U&amp;gt;&lt;/code&gt;, &lt;code&gt;ToLongBiFunction&amp;lt;T,U&amp;gt;&lt;/code&gt; e &lt;code&gt;ToDoubleBiFunction&amp;lt;T,U&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Já a interface &lt;code&gt;BiConsumer&amp;lt;T,U&amp;gt;&lt;/code&gt; tem variações que recebem dois argumentos, uma referência de objeto e um tipo primitivo: &lt;code&gt;ObjDoubleConsumer&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;ObjLongConsumer&amp;lt;T&amp;gt;&lt;/code&gt; e &lt;code&gt;ObjIntConsumer&amp;lt;T&amp;gt;&lt;/code&gt;, somando no total &lt;strong&gt;&lt;em&gt;nove&lt;/em&gt;&lt;/strong&gt; versões de dois argumentos das interfaces básicas. &lt;/p&gt;

&lt;p&gt;Temos também a interface &lt;code&gt;BooleanSupplier&lt;/code&gt;, uma variante de &lt;code&gt;Supplier&amp;lt;T&amp;gt;&lt;/code&gt; que retorna um &lt;code&gt;boolean&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Resumo das seis interfaces funcionais básicas
&lt;/h3&gt;

&lt;p&gt;A maioria das interfaces funcionais padrões existe somente para fornecer suporte para os tipos primitivos, então:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Não ceda à tentação de usar as interfaces funcionais básicas com os tipos primitivos ao invés de utilizar as interfaces funcionais primitivas já existentes na biblioteca padrão. As consequências advindas da utilização do empacotamento dos tipos primitivos podem ser perigosíssimas para operações em massa.&lt;/strong&gt; &lt;sup id="fnref4"&gt;4&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Segue um resumo de cada uma das &lt;em&gt;seis&lt;/em&gt; interfaces funcionais básicas:&lt;/p&gt;

&lt;h4&gt;
  
  
  Consumer&amp;lt;T&amp;gt;
&lt;/h4&gt;

&lt;p&gt;Essa interface representa uma operação que vai aceitar um input do tipo &lt;code&gt;T&lt;/code&gt; e não retornará nada (&lt;code&gt;void&lt;/code&gt;).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;método abstrato&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;accept&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;default method(s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;andThen&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uso comum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Como parâmetro em métodos &lt;code&gt;forEach&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primitive Specializations&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;IntConsumer&lt;/code&gt;, &lt;code&gt;LongConsumer&lt;/code&gt;, &lt;code&gt;DoubleConsumer&lt;/code&gt;,...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;⬅️ Voltar para a lista das interfaces funcionais mais utilizadas.&lt;/p&gt;

&lt;h4&gt;
  
  
  Supplier&amp;lt;T&amp;gt;
&lt;/h4&gt;

&lt;p&gt;Essa interface representa um objeto fábrica que espera retornar dado objeto do tipo &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;método abstrato&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;get&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;default method(s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uso comum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Utilizado para criar Streams infinitos preguiçosos (lazy) do tipo &lt;code&gt;T&lt;/code&gt; e também utilizado como parâmetro para o método &lt;code&gt;orElseGet&lt;/code&gt; da classe &lt;code&gt;Optional&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primitive Specializations&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;IntSupplier&lt;/code&gt;, &lt;code&gt;LongSupplier&lt;/code&gt;, &lt;code&gt;DoubleSupplier&lt;/code&gt;,...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;⬅️ Voltar para a lista das interfaces funcionais mais utilizadas.&lt;/p&gt;

&lt;h4&gt;
  
  
  Predicate&amp;lt;T&amp;gt;
&lt;/h4&gt;

&lt;p&gt;Essa interface define um objeto de função muito utilizado para checar se o argumento do tipo &lt;code&gt;T&lt;/code&gt; satisfaz ou não alguma condição, returnando &lt;code&gt;true&lt;/code&gt; ou &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;método abstrato&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;test&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;default method(s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;and&lt;/code&gt;,&lt;code&gt;negate&lt;/code&gt;, e &lt;code&gt;or&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uso comum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Como parâmetro para métodos da classe &lt;code&gt;Stream&lt;/code&gt;, como &lt;code&gt;filter&lt;/code&gt; e &lt;code&gt;anyMatch&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primitive Specializations&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;IntSupplier&lt;/code&gt;, &lt;code&gt;LongSupplier&lt;/code&gt;, &lt;code&gt;DoubleSupplier&lt;/code&gt;,...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;⬅️ Voltar para a lista das interfaces funcionais mais utilizadas.&lt;/p&gt;

&lt;h4&gt;
  
  
  Function&amp;lt;T,R&amp;gt;
&lt;/h4&gt;

&lt;p&gt;Essa interface representa uma operação de transformação, que seu intuito é aceitar um input do tipo &lt;code&gt;T&lt;/code&gt; e retornar o uma instância do tipo &lt;code&gt;R&lt;/code&gt;. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;método abstrato&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;default method(s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;andThen&lt;/code&gt;, &lt;code&gt;compose&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uso comum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Como parâmetro ao método &lt;code&gt;map&lt;/code&gt; da classe &lt;code&gt;Stream&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primitive Specializations&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;IntFunction&lt;/code&gt;, &lt;code&gt;LongFunction&lt;/code&gt;, &lt;code&gt;DoubleFunction&lt;/code&gt;,&lt;code&gt;IntToDoubleFunction&lt;/code&gt;,&lt;code&gt;DoubleToIntFunction&lt;/code&gt;,...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;⬅️ Voltar para a lista das interfaces funcionais mais utilizadas.&lt;/p&gt;

&lt;h4&gt;
  
  
  UnaryOperator&amp;lt;T&amp;gt;
&lt;/h4&gt;

&lt;p&gt;Essa interface representa uma operação que aceita um input do tipo &lt;code&gt;T&lt;/code&gt; e retornar o uma instância do mesmo tipo &lt;code&gt;T&lt;/code&gt;. Essa interface é uma especialização da interface &lt;code&gt;Function&amp;lt;T&amp;gt;&lt;/code&gt;, isto é, ela estende a interface &lt;code&gt;Function&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;método abstrato&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;default method(s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;andThen&lt;/code&gt;, &lt;code&gt;compose&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uso comum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quando há necessidade de transformação, enriquecimento de uma data instância do tipo &lt;code&gt;T&lt;/code&gt; ou a substituição  por outra instância do mesmo tipo &lt;code&gt;T&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primitive Specializations&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;IntUnaryOperator&lt;/code&gt;, &lt;code&gt;LongUnaryOperator&lt;/code&gt;, &lt;code&gt;DoubleUnaryOperator&lt;/code&gt;,...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;⬅️ Voltar para a lista das interfaces funcionais mais utilizadas.&lt;/p&gt;

&lt;h4&gt;
  
  
  BinaryOperator&amp;lt;T&amp;gt;
&lt;/h4&gt;

&lt;p&gt;Essa interface representa uma operação de transformação, que seu intuito é aceitar dois inputs do tipo &lt;code&gt;T&lt;/code&gt; e retornar o uma instância do tipo &lt;code&gt;R&lt;/code&gt;. Essa interface estende a interface &lt;code&gt;BiFunction&amp;lt;T, U, R&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;método abstrato&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;apply&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;default method(s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;andThen&lt;/code&gt;, &lt;code&gt;compose&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uso comum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Como parâmetro aos métodos com o nome &lt;code&gt;reduce&lt;/code&gt; da classe &lt;code&gt;Stream&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primitive Specializations&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;IntBinaryOperator&lt;/code&gt;, &lt;code&gt;LongBinaryOperator&lt;/code&gt;, &lt;code&gt;DoubleBinaryOperator&lt;/code&gt;,...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;⬅️ Voltar para a lista das interfaces funcionais mais utilizadas.&lt;/p&gt;

&lt;p&gt;É muita informação para assimilar, porém a maior parte das interfaces funcionais já foram escritas e estão disponíveis na biblioteca padrão do Java e seus nomes foram estruturados para que não seja difícil encontrá-las quando precisarmos delas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando a sua interface funcional
&lt;/h2&gt;

&lt;p&gt;Caso nenhuma dessas interfaces padrões mencionadas anteriomente satisfaça o que deseja fazer - como por exemplo, a necessidade de criar um predicado que suporte &lt;em&gt;três&lt;/em&gt; argumentos ou a necessidade de ter uma interface funcional que lance exceções checadas (&lt;a href="https://dev.to/dearrudam/be-the-exception-dicas-para-dominar-excecoes-em-seus-codigos-java-4nlo"&gt;veja aqui um artigo meu que fala um pouco desses tipos de exceções 😉&lt;/a&gt;) -, então a criação de uma interface funcional customizada será necessária.&lt;/p&gt;

&lt;p&gt;Outro fato também a se considerar é que terá momentos que devemos escrever nossa própria interface funcional mesmo quando alguma outra interface padrão é estruturamente idêntico. &lt;/p&gt;

&lt;p&gt;Quando ela, a sua possível interface funcional, apresentar requisitos fortes na qual seu nome seja relevante para o domínio do negócio que ela se propõe a resolver, talvez seja uma boa sua escrita.&lt;/p&gt;

&lt;p&gt;Uma forma de ter certeza da necessidade de criar uma interface funcional sob medida seria quando ela assume uma ou mais das seguintes características:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ela está associada a um contrato forte;&lt;/li&gt;
&lt;li&gt;Ela será usada com frequência e poderia se beneficiar de um nome descritivo;&lt;/li&gt;
&lt;li&gt;Ela se beneficiaria de métodos padrões customizados;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uma vez que decidimos em criar nossas próprias interfaces funcionais, elas precisarão seguir alguns critérios para serem consideradas interfaces funcionais válidas. &lt;/p&gt;

&lt;p&gt;Os critérios são:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tem que ter apenas um método abstrato;&lt;/li&gt;
&lt;li&gt;Pode ou não conter vários métodos estáticos;&lt;/li&gt;
&lt;li&gt;Pode ou não conter vários métodos &lt;em&gt;default&lt;/em&gt;;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Outro detalhe opcional, porém muito útil é anotar essas interfaces com a anotação &lt;code&gt;@FuncionalInterface&lt;/code&gt;. Além de deixar explícito o propósito para qual a interface foi criada, também instrui o compilador a reforçar a checagem para verificar se a interface realmente se qualifica como uma interface funcional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interfaces funcionais - a fundação para permitir a programação funcional com Java
&lt;/h2&gt;

&lt;p&gt;As interfaces funcionais são, sem dúvida, uma peça fundamental para que possamos utilizar o estilo funcional em nossos códigos Java.&lt;/p&gt;

&lt;p&gt;Elas promovem o reuso de código e abrem a oportunidade de aplicarmos &lt;strong&gt;Higher-order functions&lt;/strong&gt;, passando de lá para cá objetos de função definidos por &lt;em&gt;Lambda Expressions&lt;/em&gt; ou por &lt;em&gt;Method References&lt;/em&gt;. Esses detalhes tendem a auxiliar a criação de códigos concisos, menos propenso à erros, facilitando o entendimento, manutenção e evolução.&lt;sup id="fnref5"&gt;5&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;E é isso galera! 👍&lt;/p&gt;

&lt;p&gt;Espero que tenha gostado do texto! 😄&lt;/p&gt;

&lt;p&gt;Se gostou e achou relevante esse conteúdo, compartilhe com seus amigos.😉&lt;/p&gt;

&lt;p&gt;Críticas e sugestões serão sempre bem-vindos!!!&lt;/p&gt;

&lt;p&gt;Até a próxima.&lt;/p&gt;

&lt;h3&gt;
  
  
  Referências:
&lt;/h3&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html" rel="noopener noreferrer"&gt;Package java.util.function&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Livro:&lt;a href="https://books.google.com.br/books?id=JGxCEAAAQBAJ&amp;amp;pg=PT143&amp;amp;lpg=PT143&amp;amp;dq=o+que+significa+primative+specialization+java&amp;amp;source=bl&amp;amp;ots=lwy3wb_R-j&amp;amp;sig=ACfU3U2rAmNfXsux1QyL53GQk1JsPBnY0A&amp;amp;hl=pt-BR&amp;amp;sa=X&amp;amp;ved=2ahUKEwjTp9aCvLX5AhWUALkGHb91A5gQ6AF6BAgREAM#v=onepage&amp;amp;q=o%20que%20significa%20primative%20specialization%20java&amp;amp;f=false" rel="noopener noreferrer"&gt;"Core Java Interview Questions You'll Most Likely Be Asked" by Vibrant Publishers&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html" rel="noopener noreferrer"&gt;The Java Tutorials: Autoboxing and unboxing&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;Livro:&lt;a href="https://www.amazon.com/Effective-Java-Joshua-Bloch/dp/0134685997/ref=sr_1_1?keywords=effective+java&amp;amp;qid=1657086875&amp;amp;s=books&amp;amp;sprefix=effective%2Cstripbooks%2C272&amp;amp;sr=1-1" rel="noopener noreferrer"&gt;"Effective Java" - Joshua Bloch&lt;/a&gt;; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;Livro:&lt;a href="https://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/" rel="noopener noreferrer"&gt;"Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expression" by Venkat Subramaniam&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>java</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>[PT-BR] EAM - Execute Around Method pattern utilizando Lambda Expressions</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Sat, 30 Jul 2022 04:22:59 +0000</pubDate>
      <link>https://dev.to/dearrudam/pt-br-eam-execute-around-method-pattern-utilizando-lambda-expressions-58j6</link>
      <guid>https://dev.to/dearrudam/pt-br-eam-execute-around-method-pattern-utilizando-lambda-expressions-58j6</guid>
      <description>&lt;p&gt;Nos últimos artigos vimos os benefícios de maneira geral em utilizar o estilo de programação funcional, mas será realmente vantajoso começar a utilizar esse novo estilo? Deveríamos mesmo esperar grandes melhorias, ou só estamos trocando &lt;em&gt;seis por meia dúzia&lt;/em&gt;? &lt;/p&gt;

&lt;p&gt;Pode não parecer, mas essas são questões genuínas que nós precisamos responder antes de nos comprometermos nosso tempo e esforço em considerar essa abordagem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Por que codar no estilo funcional?
&lt;/h3&gt;

&lt;p&gt;Olhando a sintaxe do Java, podemos ver que, apesar de muitos acharem ela verbosa até, ela é simples! E uma vez que a sintaxe se torna familiar, sua utilização se torna confortável. Isso é verdade para praticamente qualquer linguagem. Quanto mais familiar estivermos com a linguagem, será confortável trabalhar com suas APIs e frameworks.&lt;/p&gt;

&lt;p&gt;Mas o que mais nos atrapalha é que, além do esforço de &lt;em&gt;codificar&lt;/em&gt; soluções para os problemas propostos, é o grande esforço para manter essa mesma base de código que, provavelmente, tem ou tiveram muitas &lt;em&gt;mãos&lt;/em&gt; envolvidas em seu desenvolvimento.&lt;/p&gt;

&lt;p&gt;Temos que garantir que nós e nossos amigos programadores estejamos sempre atentos a vários pontos sensíveis da aplicação que podem ser facilmente se tornar em um pesadelo de manutenção e evolução de nossos códigos. Não estou falando só de regras de negócios, mas também de códigos que tem preocupações ortogonais que suportam essas tais regras.&lt;/p&gt;

&lt;p&gt;Só pra relembrar, abaixo temos alguns itens que precisamos dar atenção quando estamos desenvolvendo nossos códigos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Será que estamos lidando de maneira correta os recursos como banco de dados ou fluxos I/O? Estamos lidando corretamente com conexões de banco de dados? Será que estamos fechando as conexões no tempo certo? Será que estamos mantendo transações ativas além do tempo necessário?&lt;/li&gt;
&lt;li&gt;E quanto a tratamento de exceções? Será que estamos lidando com elas nos níveis adequados? Estamos registrando nos logs as exceções de maneira correta e no nível correto? E quan a auditoria de acesso e execuções?&lt;/li&gt;
&lt;li&gt;E quanto o processamento concorrente? Estamos adquirindo e liberando os locks de maneira adequada?&lt;/li&gt;
&lt;li&gt;E a lista se estende... etc...etc... &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cada um desses itens, olhando isoladamente, podem até parecer não serem grandes problemas para se lidar. Mas as coisas mudam de figura quando eles estão combinados a complexidade inerente ao domínio que a aplicação está se propondo a resolver. Com certeza, as coisas ficarão complicadas de maneira bem rápida, exigindo um trabalho árduo de manutenção dos códigos e dificultando também a sua evolução.&lt;/p&gt;

&lt;p&gt;E se nós encapsularmos cada uma dessas decisões em pequenos pedaços de código, onde cada pedaço gerenciasse suas restrições de maneira mais concisa? Assim, não precisaríamos gastar energia além do necessário para garantir a execução adequada desses tais códigos.&lt;/p&gt;

&lt;p&gt;Novamente essas palavras: &lt;em&gt;código conciso&lt;/em&gt;. Talvez elas pairam na cabeça de vocês assim como pairam na minha, e então, perguntas como a seguinte pode surgir:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Será que código conciso significa apenas código enxuto?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lendo o livro do &lt;strong&gt;Venkat Subramaniam&lt;/strong&gt; &lt;sup id="fnref1"&gt;1&lt;/sup&gt;, encontrei uma explição bem interessante que eu gostaria de compartilhar com vocês:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Writing code is like throwing ingredients together; making it concise is like turning that into a sauce.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dando uma traduzida para o português:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Escrever código é como juntar ingredientes; fazer isso de forma concisa é como transformar isso em um molho."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Assim como criar um molho depende de um esforço em conhecer bem como juntar todos os ingredientes, escrever códigos concisos também requerem um esforço maior para serem desenvolvidos. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It often takes more effort to write concise code. It's less code to read, but effective code is transparent. A short code listing that's hard to understand or hides details is terse rather than concise.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Minha humilde tradução:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Muitas vezes é preciso mais esforço para escrever um código conciso. É menos código para ler, mas código efetivo é transparente. Uma pequena lista de códigos que são difíceis de entender ou que escondem detalhes são mais enxutos do que concisos;    &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;PS&lt;/strong&gt;: o termo &lt;em&gt;terse&lt;/em&gt;, pelo que consegui encontrar na internet &lt;sup id="fnref2"&gt;2&lt;/sup&gt; , significa que muitas palavras foram descartadas da frase em questão, dificultando sua compreensão, então usei o termo enxuto no contexto. &lt;strong&gt;Fica aqui meu apelo pela ajuda por alguém que domina inglês 🙏&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Concise code equals design agility. Concise code has less ceremony. This means we can quickly try out our design ideas and move forward if they're good, or move on if they turn sour.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Traduzindo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Código conciso é como design ágil. Código conciso tem menos cerimônia. Isso significa que nós podemos experimentar rápidamente nossas ideias de design e seguir em frente se elas forem boas, ou mudá-las se elas "azedarem".   &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Então podemos concluir que um código conciso é aquele que além de fazer o que é proposto a fazer, ele deve ser claro, sucinto, sem ambigüidades, curto porém com todas as informações necessária para sua compreensão.&lt;/p&gt;

&lt;p&gt;Bom, com certeza não é algo fácil de se atingir... mas não desanimem! Com prática e estudo chegaremos lá! 👍&lt;/p&gt;

&lt;p&gt;Que tal agora codar um pouco?&lt;/p&gt;

&lt;h3&gt;
  
  
  EAM - Execute Around Method pattern utilizando Lambda Expressions
&lt;/h3&gt;

&lt;p&gt;Nos textos anteriores, encontraremos a seguinte questão:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Será que estamos lidando de maneira correta os recursos como banco de dados ou fluxos I/O? &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;E nos parágrafos subsequentes também encontraremos o seguinte texto:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;E se nós encapsularmos cada uma dessas decisões em pequenos pedaços de código, onde cada pedaço gerenciasse suas restrições de maneira mais concisa? &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pois bem, trabalhar com recursos externos traz alguns detalhes que são importantes, pois se não tratarmos da maneira correta, problemas como vazamento de memória (&lt;em&gt;memory leaks&lt;/em&gt;) podem surgir. &lt;/p&gt;

&lt;p&gt;O Java provê algumas opções para fechar e liberar recursos, mas acredito que podemos utilizar Lambda Expressions de uma maneira interessante para lidar com esse detalhe.&lt;/p&gt;

&lt;p&gt;Vamos iniciar a partir de uma simples classe que lida com um recurso externo, uma classe que utiliza um FileWriter para escrever algumas mensagens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriter&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;FileWriter&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MessageFileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;writeMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;closeFile&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No construtor da classe &lt;code&gt;MessageFileWriter&lt;/code&gt; inicializamos a instância &lt;code&gt;FileWriter&lt;/code&gt; passando o nome do arquivo destino em que queremos escrever. Com o método &lt;code&gt;writeMessage&lt;/code&gt; podemos escrever mensagens utilizando a instância do &lt;code&gt;FileWriter&lt;/code&gt;. Já o método &lt;code&gt;closeFile&lt;/code&gt; nós poderemos fechar o recurso chamando o método &lt;code&gt;close&lt;/code&gt; da instância &lt;code&gt;FileWriter&lt;/code&gt; e com isso, esperamos que as mensagens sejam descarregadas para o arquivo para só então fechá-lo.  &lt;/p&gt;

&lt;p&gt;Agora vamos escrever o método &lt;code&gt;main&lt;/code&gt; para que possamos utilizar essa classe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messageWriter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages.txt"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;messageWriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello folks!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui, criamos uma instância da classe &lt;code&gt;MessageFileWriter&lt;/code&gt; e então invocamos o método &lt;code&gt;writeMessage&lt;/code&gt; passando uma &lt;code&gt;String&lt;/code&gt; com o texto "Hello folks!" como a mensagem que queremos escrever, mas se executarmos esse código, nós vamos ver que o arquivo &lt;code&gt;message.txt&lt;/code&gt; está em branco 😱. O método &lt;code&gt;closeFile&lt;/code&gt; nunca é chamado, assim o arquivo nunca será fechado e o conteúdo que queremos escrever nunca será descarregado da memória para o arquivo. &lt;/p&gt;

&lt;p&gt;Se criarmos várias instâncias em processos de longa duração (&lt;em&gt;long-running process&lt;/em&gt;) nós iríamos acabar com vários arquivos abertos que não seriam fechados e todos estariam em branco!&lt;/p&gt;

&lt;p&gt;Você pode estar pensando:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ah, vamos adicionar a invocação do método &lt;code&gt;closeFile&lt;/code&gt; então!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Provavelmente iremos terminar um código similar como demostrado abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messageWriter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages.txt"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;messageWriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello folks!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;messageWriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;closeFile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apesar de aparentemente termos resolvido o problema, essa abordagem ainda demonstra alguns problemas (&lt;em&gt;code smells&lt;/em&gt;) 😕:&lt;/p&gt;

&lt;p&gt;Esse código tende a introduzir duplicação de código e assim, aumento de custo de manutenção. Isso quer dizer, em qualquer lugar que fossemos utilizar instâncias da nossa classe &lt;code&gt;MessageFileWriter&lt;/code&gt;, teríamos que sempre chamar o método &lt;code&gt;closeFile&lt;/code&gt; para ter certeza que o conteúdo vai ser descarregado no arquivo e o recurso fechado. E devemos concordar que o design da interface de nossa classe não ajuda a evitar esquecer esse detalhe. &lt;/p&gt;

&lt;p&gt;Estamos trabalhando com recursos externos, então, provavelmente exceções podem ser lançadas e se não tratadas, o recurso não será fechado e talvez a aplicação possa entrar em um estado inconsistente. &lt;/p&gt;

&lt;p&gt;Podemos implementar blocos &lt;code&gt;try&lt;/code&gt; e &lt;code&gt;finally&lt;/code&gt; em torno da chamada desses métodos e assim garantir que o método &lt;code&gt;closeFile&lt;/code&gt; será chamado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messageWriter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages.txt"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;messageWriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello folks!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;   
            &lt;span class="n"&gt;messageWriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;closeFile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Poderíamos também utilizar uma feature que foi introduzida no Java 7, &lt;strong&gt;ARM - Automatic Resource Management&lt;/strong&gt;, na qual podemos reduzir a verbosidade da versão no exemplo anterior usando o bloco &lt;code&gt;try-resources&lt;/code&gt;, que é uma forma especial de utilizar o bloco &lt;code&gt;try&lt;/code&gt; informando instâncias que implementam a interface &lt;code&gt;AutoCloseable&lt;/code&gt; na qual serão fechados ao finalizar o bloco &lt;code&gt;try&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Caso tenha interesse em saber mais sobre tratalmento de exceções, segue o meu artigo &lt;a href="https://dev.to/dearrudam/be-the-exception-dicas-para-dominar-excecoes-em-seus-codigos-java-4nlo"&gt;[PT-BR] Be the exception! Dicas para dominar exceções em seus códigos Java&lt;/a&gt; 😎. &lt;/p&gt;

&lt;p&gt;Vamos refatorar nossa classe &lt;code&gt;MessageFileWriter&lt;/code&gt; para que ela implemente essa interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;AutoCloseable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;FileWriter&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MessageFileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;writeMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E aqui aplicamos o &lt;code&gt;try-resources&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messageWriter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"messages.txt"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;messageWriter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello folks!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Porém, o problema de duplicação de código e aumento de esforço de manutenção ainda vão continuar e, toda vez que alguém mexer em alguma nessa parte que contenha esse trecho de código, será necessário verificar se nada foi quebrado com a mudança. (Testes, please 🙏!)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ARM&lt;/em&gt; foi um passo para o caminho certo, mas mesmo assim, há a necessidade de declarações adicionais para utilizar nossa classe. IMHO, ninguém deveria ter a necessidade de saber que nossa classe implementa &lt;code&gt;AutoCloseable&lt;/code&gt; e que pode utilizar &lt;code&gt;try-resources&lt;/code&gt; para utilizá-la. &lt;/p&gt;

&lt;p&gt;Como desenvolvedores, amamos quando o compilador e a IDE nos auxiliam na utilização de uma dada API, não é mesmo? &lt;/p&gt;

&lt;p&gt;Que tal desenhar nossa classe de tal forma a ser mais concisa e fácil de utilizar!?&lt;/p&gt;

&lt;h2&gt;
  
  
  Conhecendo o pattern &lt;em&gt;Execute Around Method - EAM&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Para nossa solução, vamos utilizar Lambda Expressions para implementar um pattern chamado &lt;strong&gt;Execute Around Method - EAM&lt;/strong&gt; &lt;sup id="fnref3"&gt;3&lt;/sup&gt;, na qual fornecerá um melhor controle para coordenar a execução sequencial de operações. &lt;/p&gt;

&lt;p&gt;Esse padrão nos permite encapsular as operações na sequência desejada para que, a partir de uma possível &lt;strong&gt;função de primeira ordem&lt;/strong&gt; passada como argumento, dispare a execução das operações e da função de maneira adequada.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que é "Função de primeira ordem"?
&lt;/h3&gt;

&lt;p&gt;Diferentemente de linguagens de programação funcionais, como Haskell, que favorecem a imutabilidade, o Java nos permite utilizar a mutabilidade. A esse respeito, Java é uma linguagem orientada à objetos, e não é, e nunca será, uma linguagem funcional pura, porém, podemos utilizar o estilo funcional no Java.&lt;/p&gt;

&lt;p&gt;As funções de primeira ordem (&lt;em&gt;Higher-order functions&lt;/em&gt;) elevam o conceito de reusabilidade de código para o próximo nível. Ao invés de somente contar com objetos e classes para promover o reuso, com funções de primeira ordem nós podemos facilmente reutilizar funções pequenas, coesas e muito bem definidas.&lt;/p&gt;

&lt;p&gt;Em OOP (&lt;em&gt;Object-Oriented Programming&lt;/em&gt;), nós passamos objetos para métodos, criamos e retornamos objetos de métodos. Funções de primeira ordem fazem para as funções o que métodos fazem para os objetos. Com funções de primeira ordem podemos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passar funções para funções;&lt;/li&gt;
&lt;li&gt;Criar funções dentro de funções;&lt;/li&gt;
&lt;li&gt;Retornar funções de funções;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No Java, podemos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passar &lt;em&gt;objetos de função&lt;/em&gt; para métodos;&lt;/li&gt;
&lt;li&gt;Criar &lt;em&gt;objetos de função&lt;/em&gt; dentro de métodos;&lt;/li&gt;
&lt;li&gt;Retornar &lt;em&gt;objetos de função&lt;/em&gt; de métodos;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logo, podemos usufruir dessa mesma abordagem para trazer esse conceito para o mundo do Java.&lt;/p&gt;

&lt;p&gt;Agora vamos voltar aos nossos códigos...&lt;/p&gt;

&lt;p&gt;Vamos preparar uma classe chamada &lt;code&gt;MessageFileWriterEAM&lt;/code&gt; para essa a nova solução utilizando &lt;em&gt;EAM&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriterEAM&lt;/span&gt;  &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;FileWriter&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;MessageFileWriterEAM&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileWriter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;writeMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;closeFile&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como você pode ter notado, deixamos essa classe com o construtor e o método &lt;code&gt;closeFile&lt;/code&gt; privados, além de fazer com que essa classe não implemente mais a interface &lt;code&gt;AutoClosable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Uma vez que não podemos criar diretamente uma instancia do tipo &lt;code&gt;MessageFileWriterEAM&lt;/code&gt; pelo seu construtor, nós precisaremos de um método fábrica (&lt;em&gt;Factory Method&lt;/em&gt;)&lt;sup id="fnref4"&gt;4&lt;/sup&gt; para poder usa-la.&lt;/p&gt;

&lt;p&gt;Diferentemente dos métodos fábricas que criam uma instância e as devolvem para uso, nosso método vai receber um &lt;em&gt;objeto de função&lt;/em&gt; do usuário, realizar a operação e só retornar ao fluxo da aplicação após o término de seu trabalho.&lt;/p&gt;

&lt;p&gt;Primeiramente teremos que implementar uma &lt;em&gt;interface funcional&lt;/em&gt; que será o tipo de função que nosso método irá receber.&lt;/p&gt;

&lt;p&gt;As interfaces funcionais (&lt;em&gt;Functional Interfaces&lt;/em&gt;) são interfaces que contém um único método, e são cadidatos ideais para que o compilador sintetize &lt;em&gt;objetos de função&lt;/em&gt; atravez de &lt;em&gt;Lambda Expressions&lt;/em&gt; ou &lt;em&gt;Method References&lt;/em&gt; - Sim... no futuro falaremos mais sobre Method References! 😉&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@FunctionalInterface&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UseMessageFileWriter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;E&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="no"&gt;E&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;PS&lt;/strong&gt;: Nesse nosso exemplo, para fins didádicos optamos em criar uma interface funcional customizada, mas uma boa prática é utilizar as interfaces funcionais padrão fornecidas pelo pacote &lt;code&gt;java.util.function&lt;/code&gt;&lt;sup id="fnref5"&gt;5&lt;/sup&gt; uma vez que alguma atenda sua necessidade. Há aproximadamente &lt;strong&gt;43&lt;/strong&gt; interfaces funcionais no pacote &lt;code&gt;java.util.function&lt;/code&gt;. Não espere se lembrar de todas elas, porém se você lembrar de pelo menos seis interfaces básicas, provavelmente você vai deduzir o restante quando precisar.  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;UseMessageFileWriter&lt;/code&gt; será nossa interface funcional. Repare que anotamos a interface com &lt;code&gt;@FunctionalInterface&lt;/code&gt;. Isso é puramente opcional, mas sempre é útil comunicar a intensão explicitamente para quem for utilizar nossos códigos. Assim, qualquer desenvolvedor irá compreender que é uma interface funcional e que não deve adicionar novos métodos à interface. &lt;/p&gt;

&lt;p&gt;Agora vamos implementar esse método:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;UseMessageFileWriter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MessageFileWriterEAM&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriterEAM&lt;/span&gt; &lt;span class="n"&gt;messageFileWriterEAM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MessageFileWriterEAM&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messageFileWriterEAM&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;messageFileWriterEAM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;closeFile&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mais um detalhe: poderíamos fazer com que a classe &lt;code&gt;MessageFilterWriteEAM&lt;/code&gt; implementasse &lt;code&gt;AutoCloseable&lt;/code&gt; e assim utilizar &lt;code&gt;try-resources&lt;/code&gt; ao invés de usar o bloco &lt;code&gt;try&lt;/code&gt; e &lt;code&gt;finally&lt;/code&gt;, mas, por decisão de design, não desejamos permitir que desenvolvedores tenham acesso ao método &lt;code&gt;close&lt;/code&gt; e assim abrir a possibilidade para esse método ser chamado antes da hora.&lt;/p&gt;

&lt;p&gt;E assim podemos ver o ganho na utilização desta abordagem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;MessageFileWriterEAM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"messages.txt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;writerEAM&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;writerEAM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello folks!"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, qualquer componente poderá fazer uso da classe &lt;code&gt;MessageFileWriterEAM&lt;/code&gt; de maneira concisa, permitindo os clientes de nossos códigos passar &lt;em&gt;objetos de função&lt;/em&gt; e consumir a nossos códigos da maneira adequada, sem se preocupar se há necessidade de fechar recursos ou se precisa orquestrar invocações de métodos pois todos esses detalhes estão encapsulados atrás da chamada do método &lt;code&gt;use&lt;/code&gt;. Isso abre oportunidade para evoluir o código de implementação, como adicionar features, como por exemplo: logging, etc.&lt;/p&gt;

&lt;p&gt;E é isso galera!👏👏👏&lt;/p&gt;

&lt;p&gt;Espero que tenham gostado do texto! 👍&lt;/p&gt;

&lt;p&gt;Caso gostou e achou relevante esse conteúdo, compartilhe com seus amigos.😉&lt;/p&gt;

&lt;p&gt;Se não gostou, compartilhe com seus inimigos!😈 (okay, não foi tão boa assim a piada...)&lt;/p&gt;

&lt;p&gt;Críticas e sugestões serão sempre bem-vindos!!!&lt;/p&gt;

&lt;p&gt;Até a próxima.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source dos exemplos: &lt;sup id="fnref6"&gt;6&lt;/sup&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/MessageFileWriter.java" rel="noopener noreferrer"&gt;MessageFileWriter.java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/MessageFileWriterEAM.java" rel="noopener noreferrer"&gt;MessageFileWriterEAM.java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Referências:
&lt;/h3&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/" rel="noopener noreferrer"&gt;"Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expression" by Venkat Subramaniam&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://writing-rag.com/4082/the-difference-between-concise-and-terse/#:~:text=Concise%20means%20you%20take%20out,Terseness%20introduces%20ambiguity." rel="noopener noreferrer"&gt;The Difference Between “Concise” and “Terse”&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="http://wiki.c2.com/?ExecuteAroundMethod" rel="noopener noreferrer"&gt;Execute Around Method&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Effective-Java-Joshua-Bloch/dp/0134685997/ref=sr_1_1?keywords=effective+java&amp;amp;qid=1657086875&amp;amp;s=books&amp;amp;sprefix=effective%2Cstripbooks%2C272&amp;amp;sr=1-1" rel="noopener noreferrer"&gt;Effective Java - Joshua Bloch&lt;/a&gt;; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html" rel="noopener noreferrer"&gt;Package java.util.function&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;&lt;a href="https://www.jbang.dev/" rel="noopener noreferrer"&gt;JBang&lt;/a&gt;; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>[PT-BR] Analisando Lambda Expressions em um Heap-dump</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Mon, 18 Jul 2022 10:52:41 +0000</pubDate>
      <link>https://dev.to/dearrudam/pt-br-analisando-lambda-expressions-em-um-heap-dump-27ai</link>
      <guid>https://dev.to/dearrudam/pt-br-analisando-lambda-expressions-em-um-heap-dump-27ai</guid>
      <description>&lt;p&gt;É muito interessante ver o quanto podemos aprender ao compartilhar conhecimento!&lt;/p&gt;

&lt;p&gt;Um exemplo disso são os comentários que recebi no último artigo que publiquei - &lt;a href="https://dev.to/dearrudam/lambda-expressions-nao-sao-classes-anonimas-5eho"&gt;"Lambdas Expressions não são classes anônimas"&lt;/a&gt;! &lt;/p&gt;

&lt;p&gt;Agradeço a todos! &lt;/p&gt;

&lt;p&gt;Um desses comentários foi muito interessante, praticamente um &lt;a href="https://dev.to/wldomiciano/comment/2022e"&gt;&lt;strong&gt;mini artigo&lt;/strong&gt;&lt;/a&gt;, onde &lt;a href="https://dev.to/wldomiciano"&gt;Wellington Domiciano&lt;/a&gt;, motivado pelo tema, pesquisou e compartilhou suas conclusões ao explorar Lambda Expressions e como a especificação transforma essas expressões lambdas em implementações de interfaces funcionais.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/j_a_o_v_c_t_r"&gt;João Victor Martins&lt;/a&gt; e eu até concordamos e recomendamos ao Wellington para reescrever esse &lt;em&gt;mini artigo&lt;/em&gt; em um artigo propriamente dito. Essa interação foi muito massa e espero que continue sempre, pois todos nós, a comunidade, sairemos ganhando com isso!&lt;/p&gt;

&lt;p&gt;Pois bem, uma coisa interessante sobre Lambdas Expressions é compreender como elas são implementadas.&lt;/p&gt;

&lt;p&gt;No artigo anterior, utilizamos o utilitário &lt;em&gt;javap&lt;/em&gt; para visualizar a classe (*.class) gerada a partir de um dado source com expressões lambdas e assim conferir que as lambdas são chamadas pelas das instruções &lt;strong&gt;InvokeDynamic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lembram do &lt;em&gt;mini artigo&lt;/em&gt; do Wellington? &lt;/p&gt;

&lt;p&gt;Pois bem, o Wellington, com a contribuição muito massa dele através do seu comentário, demonstrou um uso muito interessante para visualizar as inner classes derivadas das lambdas e isso me despertou mais curiosidades e gostaria de trazer algo bem interessante! Valeu Wellington!&lt;/p&gt;

&lt;h2&gt;
  
  
  Descarregando as inner classes derivadas das lambdas
&lt;/h2&gt;

&lt;p&gt;Baseado no &lt;em&gt;mini artigo&lt;/em&gt; do Wellington, vamos compilar a seguinte classe abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.function.Consumer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreatingLambdaExpression&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;printer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Wellington"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"João Vitor"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Maximillian"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;printer&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse source se tornará no *.class abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;tree.
&lt;span class="nb"&gt;.&lt;/span&gt;
└── CreatingLambdaExpression.class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E se executarmos o comando abaixo, podemos explorar um pouco mais como o cenário com a lambda foi compilada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;javap &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; CreatingLambdaExpression 
Compiled from &lt;span class="s2"&gt;"CreatingLambdaExpression.java"&lt;/span&gt;
public class CreatingLambdaExpression &lt;span class="o"&gt;{&lt;/span&gt;
  public CreatingLambdaExpression&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokespecial &lt;span class="c"&gt;#8                  // Method java/lang/Object."&amp;lt;init&amp;gt;":()V&lt;/span&gt;
       4: &lt;span class="k"&gt;return

  &lt;/span&gt;public static void main&lt;span class="o"&gt;(&lt;/span&gt;java.lang.String...&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: invokedynamic &lt;span class="c"&gt;#16,  0             // InvokeDynamic #0:accept:()Ljava/util/function/Consumer;&lt;/span&gt;
       5: astore_1
       6: ldc           &lt;span class="c"&gt;#20                 // String Wellington&lt;/span&gt;
       8: ldc           &lt;span class="c"&gt;#22                 // String João Vitor&lt;/span&gt;
      10: ldc           &lt;span class="c"&gt;#24                 // String Maximillian&lt;/span&gt;
      12: invokestatic  &lt;span class="c"&gt;#26                 // InterfaceMethod java/util/List.of:(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/List;&lt;/span&gt;
      15: aload_1
      16: invokeinterface &lt;span class="c"&gt;#32,  2           // InterfaceMethod java/util/List.forEach:(Ljava/util/function/Consumer;)V&lt;/span&gt;
      21: &lt;span class="k"&gt;return

  &lt;/span&gt;private static void lambda&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;java.lang.String&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: getstatic     &lt;span class="c"&gt;#44                 // Field java/lang/System.out:Ljava/io/PrintStream;&lt;/span&gt;
       3: aload_0
       4: invokevirtual &lt;span class="c"&gt;#50                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V&lt;/span&gt;
       7: &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas podemos ir além, graças a essa &lt;a href="https://stackoverflow.com/a/47469864/3334365" rel="noopener noreferrer"&gt;resposta&lt;/a&gt; compartilhada pelo Wellington, basta adicionarmos a seguinte propriedade na execução do programa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-Djdk&lt;/span&gt;.internal.lambda.dumpProxyClasses&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;dump directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;P.S&lt;/strong&gt;: Quando utilizar essa propriedade, recomendo indicar um diretório vazio, pois a JVM irá &lt;strong&gt;descarregar&lt;/strong&gt; além das inner classes geradas pelo seu projeto, ele também descarregará inner classes das bibliotecas de terceiros que seu projeto esteja utilizando. Isso poluirá seu diretorio e talvez, não é o que você deseja, certo?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos utilizar na execução do nosso código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;java &lt;span class="nt"&gt;-Djdk&lt;/span&gt;.internal.lambda.dumpProxyClasses&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; CreatingLambdaExpression
Wellington
João Vitor
Maximillian
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Muito bem, o código executou como esperado, mas agora podemos ver a inner classe derivada da lambda em nosso fonte &lt;strong&gt;descarregadas&lt;/strong&gt; no diretório bin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/ $ tree .
.
├── CreatingLambdaExpression$$Lambda$1.class
└── CreatingLambdaExpression.class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E assim podemos visualizar sua classe utilizando o utilitário &lt;strong&gt;javap&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;javap &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; CreatingLambdaExpression&lt;span class="se"&gt;\$\$&lt;/span&gt;Lambda&lt;span class="se"&gt;\$&lt;/span&gt;1.class 
final class CreatingLambdaExpression&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$1&lt;/span&gt; implements java.util.function.Consumer &lt;span class="o"&gt;{&lt;/span&gt;
  private CreatingLambdaExpression&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokespecial &lt;span class="c"&gt;#10                 // Method java/lang/Object."&amp;lt;init&amp;gt;":()V&lt;/span&gt;
       4: &lt;span class="k"&gt;return

  &lt;/span&gt;public void accept&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_1
       1: checkcast     &lt;span class="c"&gt;#14                 // class java/lang/String&lt;/span&gt;
       4: invokestatic  &lt;span class="c"&gt;#20                 // Method CreatingLambdaExpression.lambda$main$0:(Ljava/lang/String;)V&lt;/span&gt;
       7: &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso podemos concluir que: &lt;/p&gt;

&lt;p&gt;Quando a JVM encontra uma lambda, ele utiliza instruções ASM contidas na própria JVM para construir as &lt;em&gt;inner classes&lt;/em&gt; (classes internas) necessárias. &lt;/p&gt;

&lt;p&gt;As classes derivadas de lambdas são geradas "on the fly" pelo componente &lt;a href="https://docs.oracle.com/javase/8/docs/api/?java/lang/invoke/LambdaMetafactory.html" rel="noopener noreferrer"&gt;LambdaMetafactory&lt;/a&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, isso quer dizer, em tempo de execução pela JRE. &lt;/p&gt;

&lt;p&gt;É legal saber que essas coisas foram desenvolvidas, mas é legal também saber o &lt;strong&gt;por quê&lt;/strong&gt; elas foram desenvolvidas!&lt;/p&gt;

&lt;h2&gt;
  
  
  Descobrindo "O POR QUÊ"
&lt;/h2&gt;

&lt;p&gt;Pesquisando um pouco mais sobre essa propriedade, cheguei a esse issue &lt;a href="https://bugs.openjdk.org/browse/JDK-8023524" rel="noopener noreferrer"&gt;JDK-8023524&lt;/a&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhm0youiujdlu7wkm8ymg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhm0youiujdlu7wkm8ymg.png" alt="JDK-8023524" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bom, temos o motivo bem claro aqui:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The lambda metafactory generates classes on the fly. For supportability and serviceability reasons, it is desirable to be able to inspect these classes..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dando uma traduzida para o português:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A lambda metafactory gera classes em tempo de execução. Por motivos de suporte e manutenção, é desejável poder inspecionar essas classes..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sim, suporte e manutenção!&lt;/p&gt;

&lt;p&gt;Para explorar e ajudar o entendimento, vamos explorar um cenário: Encontrar a lambda que está causando um possível memory leak através de um heap-dump! &lt;/p&gt;

&lt;h2&gt;
  
  
  Encontrar lambdas a partir de um heap-dump
&lt;/h2&gt;

&lt;p&gt;Inspirado por um issue no &lt;a href="https://stackoverflow.com/questions/41570839/finding-a-java-lambda-from-its-mangled-name-in-a-heap-dump" rel="noopener noreferrer"&gt;StackOverflow: Finding a Java lambda from its mangled name in a heap dump&lt;/a&gt;&lt;sup id="fnref3"&gt;3&lt;/sup&gt;, vamos implementar nosso programa que criará um cenário próximo de um memory leak, porém vamos tentar utilizar ferramentas e entender o porque foi importante a criação dessa propriedade &lt;em&gt;jdk.internal.lambda.dumpProxyClasses&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Arrays&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.function.IntSupplier&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.stream.Collectors&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CollectingIntegerListFromLambdaExpressions&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IntSupplier&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;IntSupplier&lt;/span&gt; &lt;span class="nf"&gt;suppliersA&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;IntSupplier&lt;/span&gt; &lt;span class="nf"&gt;suppliersB&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;IntSupplier&lt;/span&gt; &lt;span class="nf"&gt;suppliersC&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;IntSupplier&lt;/span&gt; &lt;span class="nf"&gt;suppliersD&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;suppliersA&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;suppliersB&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;suppliersC&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;suppliersD&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"It's done! A list of integers has been created!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the generated list of integers is : %s"&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;IntSupplier:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getAsInt&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;())));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""
            Keeping the application alive in order to let aheap dump be taken.
            Press CTRL+C to close the application.
            """&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MAX_VALUE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Basicamente, em nosso programa irá gerar uma lista de objetos de função do tipo &lt;em&gt;java.util.function.IntSupplier&lt;/em&gt;, e esses serão fornecidos por métodos  através de expressões lambdas, e, a partir dessa lista, iremos gerar uma lista de inteiros e escrever seu conteúdo na saída do programa, porém, para ser possível realizar o dump da heap, a thread main ficará &lt;em&gt;dormindo&lt;/em&gt; através do método &lt;em&gt;Thread.sleep&lt;/em&gt;;&lt;/p&gt;

&lt;p&gt;O problema está no método &lt;em&gt;suppliersC&lt;/em&gt;, e esse método retornará uma lambda que irá manter a referência do argumento &lt;em&gt;o&lt;/em&gt;, que é do tipo &lt;em&gt;Object&lt;/em&gt;, que na verdade receberá a instância de um array de &lt;em&gt;bytes&lt;/em&gt; com &lt;em&gt;10.000.000&lt;/em&gt; posições durante a execução. &lt;/p&gt;

&lt;p&gt;Essas instâncias estão vinculadas a thread &lt;em&gt;main&lt;/em&gt;, que pelo fato dela estar dormindo, o Garbage Collector não conseguirá remover essas instâncias da memória, causando assim um cenário de vazamento de memória.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;end TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bom, a compilação desse source resultou nesse *.class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
└── CollectingIntegerListFromLambdaExpressions.class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Então, iniciação a aplicação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/ $ java CollectingIntegerListFromLambdaExpressions
It's done! A list of integers has been created!
the generated list of integers is : [0, 2124308362, 2124308362, 11]
Keeping the application alive in order to let aheap dump be taken.
Press CTRL+C to close the application.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E, para capturar o heap-dump, utilizei o Eclipse Memory Analyzer(MAT)&lt;sup id="fnref4"&gt;4&lt;/sup&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0k2tgzwavi8tupaw9cby.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0k2tgzwavi8tupaw9cby.gif" alt="memory-leak-lambda.gif" width="1001" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De acordo com a analyzer, uma instância do tipo da classe &lt;strong&gt;CollectingIntegerListFromLambdaExpressions$$Lambda$3&lt;/strong&gt; está consumindo aproximadamente &lt;strong&gt;10.000.016&lt;/strong&gt; bytes (&lt;strong&gt;90.83%&lt;/strong&gt;) na memória heap.&lt;/p&gt;

&lt;p&gt;Mas essa classe foi gerada "on the fly" a partir de alguma lambda que não temos como analizar, pois não temos acesso a ela!&lt;/p&gt;

&lt;p&gt;Tudo bem, sabemos que o problema está na lambda que retorna do método &lt;em&gt;suppliersC(Object o)&lt;/em&gt;, porém na vida real, teremos muito mais classes e métodos envolvidos, possivelmente isso causará, no mínimo, um esforço e um tempo maior para localizar esse ponto lendo os fontes. É aqui que essa propriedade pode nos ajudar!&lt;/p&gt;

&lt;p&gt;Então vamos ativa-la e assim ver como podemos ser mais assertivos para localizar esse lambda danadinha!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bin/ $ java -Djdk.internal.lambda.dumpProxyClasses=. CollectingIntegerListFromLambdaExpressions
It's done! A list of integers has been created!
the generated list of integers is : [0, 1627674070, 1627674070, 11]
Keeping the application alive in order to let aheap dump be taken.
Press CTRL+C to close the application.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Muito bem, com isso já podemos ver as inner classes derivadas de nosso fonte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
├── CollectingIntegerListFromLambdaExpressions&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$1&lt;/span&gt;.class
├── CollectingIntegerListFromLambdaExpressions&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$2&lt;/span&gt;.class
├── CollectingIntegerListFromLambdaExpressions&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$3&lt;/span&gt;.class
├── CollectingIntegerListFromLambdaExpressions&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$4&lt;/span&gt;.class
├── CollectingIntegerListFromLambdaExpressions&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$5&lt;/span&gt;.class
├── CollectingIntegerListFromLambdaExpressions.class
└── java
    └── util
        └── stream
            ├── Collectors&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$6&lt;/span&gt;.class
            ├── Collectors&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$7&lt;/span&gt;.class
            └── Collectors&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$8&lt;/span&gt;.class

3 directories, 9 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, todas as inner classes derivadas do nosso fonte foram &lt;strong&gt;descarregadas&lt;/strong&gt; no diretório &lt;em&gt;bin&lt;/em&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;P.S&lt;/strong&gt;: Quando utilizar essa propriedade, recomendo indicar um diretório vazio, pois a JVM irá &lt;strong&gt;descarregar&lt;/strong&gt; além das inner classes geradas pelo seu projeto, ele também descarregará inner classes das bibliotecas de terceiros que seu projeto esteja utilizando. Isso poluirá seu diretorio e talvez, não é o que você deseja, certo?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Agora, vamos visualizar a classe &lt;strong&gt;CollectingIntegerListFromLambdaExpressions$$Lambda$3.class&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;javap &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; CollectingIntegerListFromLambdaExpressions&lt;span class="se"&gt;\$\$&lt;/span&gt;Lambda&lt;span class="se"&gt;\$&lt;/span&gt;3
final class CollectingIntegerListFromLambdaExpressions&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$3&lt;/span&gt; implements java.util.function.IntSupplier &lt;span class="o"&gt;{&lt;/span&gt;
  private final java.lang.Object arg&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  private CollectingIntegerListFromLambdaExpressions&lt;span class="nv"&gt;$$&lt;/span&gt;Lambda&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokespecial &lt;span class="c"&gt;#13                 // Method java/lang/Object."&amp;lt;init&amp;gt;":()V&lt;/span&gt;
       4: aload_0
       5: aload_1
       6: putfield      &lt;span class="c"&gt;#15                 // Field arg$1:Ljava/lang/Object;&lt;/span&gt;
       9: &lt;span class="k"&gt;return

  &lt;/span&gt;public int getAsInt&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: getfield      &lt;span class="c"&gt;#15                 // Field arg$1:Ljava/lang/Object;&lt;/span&gt;
       4: invokestatic  &lt;span class="c"&gt;#23                 // Method CollectingIntegerListFromLambdaExpressions.lambda$suppliersC$2:(Ljava/lang/Object;)I&lt;/span&gt;
       7: ireturn
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos ver que essa classe recebe no construtor um argumento do tipo &lt;em&gt;java.lang.Object&lt;/em&gt;, e dentro do método &lt;em&gt;getAsInt()&lt;/em&gt; é possível ver uma instrução &lt;strong&gt;invokestatic&lt;/strong&gt; que está com um comentário apontando uma chamada para o método estático &lt;strong&gt;CollectingIntegerListFromLambdaExpressions.lambda$suppliersC$2&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Aqui já podemos ver o nome do método que instanciou o objeto que está causando o memory leak.&lt;/p&gt;

&lt;p&gt;Mas vamos visualizar a classe &lt;strong&gt;CollectingIntegerListFromLambdaExpressions.class&lt;/strong&gt; e ver um pouco mais de detalhes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;javap &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; CollectingIntegerListFromLambdaExpressions
Compiled from &lt;span class="s2"&gt;"CollectingIntegerListFromLambdaExpressions.java"&lt;/span&gt;
public class CollectingIntegerListFromLambdaExpressions &lt;span class="o"&gt;{&lt;/span&gt;
  static java.util.List&amp;lt;java.util.function.IntSupplier&amp;gt; list&lt;span class="p"&gt;;&lt;/span&gt;

  public CollectingIntegerListFromLambdaExpressions&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokespecial &lt;span class="c"&gt;#1                  // Method java/lang/Object."&amp;lt;init&amp;gt;":()V&lt;/span&gt;
       4: &lt;span class="k"&gt;return

  &lt;/span&gt;static java.util.function.IntSupplier suppliersA&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: invokedynamic &lt;span class="c"&gt;#7,  0              // InvokeDynamic #0:getAsInt:()Ljava/util/function/IntSupplier;&lt;/span&gt;
       5: areturn

  static java.util.function.IntSupplier suppliersB&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokevirtual &lt;span class="c"&gt;#11                 // Method java/lang/Object.hashCode:()I&lt;/span&gt;
       4: istore_1
       5: iload_1
       6: invokedynamic &lt;span class="c"&gt;#15,  0             // InvokeDynamic #1:getAsInt:(I)Ljava/util/function/IntSupplier;&lt;/span&gt;
      11: areturn

  static java.util.function.IntSupplier suppliersC&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokedynamic &lt;span class="c"&gt;#18,  0             // InvokeDynamic #2:getAsInt:(Ljava/lang/Object;)Ljava/util/function/IntSupplier;&lt;/span&gt;
       6: areturn

  static java.util.function.IntSupplier suppliersD&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokevirtual &lt;span class="c"&gt;#21                 // Method java/lang/Object.toString:()Ljava/lang/String;&lt;/span&gt;
       4: invokevirtual &lt;span class="c"&gt;#25                 // Method java/lang/String.length:()I&lt;/span&gt;
       7: istore_1
       8: iload_1
       9: invokedynamic &lt;span class="c"&gt;#15,  0             // InvokeDynamic #1:getAsInt:(I)Ljava/util/function/IntSupplier;&lt;/span&gt;
      14: areturn

  static void run&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: ldc           &lt;span class="c"&gt;#30                 // int 10000000&lt;/span&gt;
       2: newarray       byte
       4: astore_0
       5: iconst_4
       6: anewarray     &lt;span class="c"&gt;#31                 // class java/util/function/IntSupplier&lt;/span&gt;
       9: dup
      10: iconst_0
      11: aload_0
      12: invokestatic  &lt;span class="c"&gt;#33                 // Method suppliersA:(Ljava/lang/Object;)Ljava/util/function/IntSupplier;&lt;/span&gt;
      15: aastore
      16: dup
      17: iconst_1
      18: aload_0
      19: invokestatic  &lt;span class="c"&gt;#38                 // Method suppliersB:(Ljava/lang/Object;)Ljava/util/function/IntSupplier;&lt;/span&gt;
      22: aastore
      23: dup
      24: iconst_2
      25: aload_0
      26: invokestatic  &lt;span class="c"&gt;#41                 // Method suppliersC:(Ljava/lang/Object;)Ljava/util/function/IntSupplier;&lt;/span&gt;
      29: aastore
      30: dup
      31: iconst_3
      32: aload_0
      33: invokestatic  &lt;span class="c"&gt;#44                 // Method suppliersD:(Ljava/lang/Object;)Ljava/util/function/IntSupplier;&lt;/span&gt;
      36: aastore
      37: invokestatic  &lt;span class="c"&gt;#47                 // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;&lt;/span&gt;
      40: putstatic     &lt;span class="c"&gt;#53                 // Field list:Ljava/util/List;&lt;/span&gt;
      43: getstatic     &lt;span class="c"&gt;#57                 // Field java/lang/System.out:Ljava/io/PrintStream;&lt;/span&gt;
      46: ldc           &lt;span class="c"&gt;#63                 // String It\'s done! A list of integers has been created!&lt;/span&gt;
      48: invokevirtual &lt;span class="c"&gt;#65                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V&lt;/span&gt;
      51: getstatic     &lt;span class="c"&gt;#57                 // Field java/lang/System.out:Ljava/io/PrintStream;&lt;/span&gt;
      54: ldc           &lt;span class="c"&gt;#71                 // String the generated list of integers is : %s&lt;/span&gt;
      56: iconst_1
      57: anewarray     &lt;span class="c"&gt;#2                  // class java/lang/Object&lt;/span&gt;
      60: dup
      61: iconst_0
      62: getstatic     &lt;span class="c"&gt;#53                 // Field list:Ljava/util/List;&lt;/span&gt;
      65: invokeinterface &lt;span class="c"&gt;#73,  1           // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;&lt;/span&gt;
      70: invokedynamic &lt;span class="c"&gt;#79,  0             // InvokeDynamic #3:apply:()Ljava/util/function/Function;&lt;/span&gt;
      75: invokeinterface &lt;span class="c"&gt;#83,  2           // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;&lt;/span&gt;
      80: invokestatic  &lt;span class="c"&gt;#89                 // Method java/util/stream/Collectors.toList:()Ljava/util/stream/Collector;&lt;/span&gt;
      83: invokeinterface &lt;span class="c"&gt;#95,  2           // InterfaceMethod java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;&lt;/span&gt;
      88: aastore
      89: invokevirtual &lt;span class="c"&gt;#99                 // Method java/lang/String.formatted:([Ljava/lang/Object;)Ljava/lang/String;&lt;/span&gt;
      92: invokevirtual &lt;span class="c"&gt;#65                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V&lt;/span&gt;
      95: &lt;span class="k"&gt;return

  &lt;/span&gt;public static void main&lt;span class="o"&gt;(&lt;/span&gt;java.lang.String...&lt;span class="o"&gt;)&lt;/span&gt; throws java.lang.InterruptedException&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: invokestatic  &lt;span class="c"&gt;#103                // Method run:()V&lt;/span&gt;
       3: getstatic     &lt;span class="c"&gt;#57                 // Field java/lang/System.out:Ljava/io/PrintStream;&lt;/span&gt;
       6: ldc           &lt;span class="c"&gt;#106                // String Keeping the application alive in order to let aheap dump be taken.\nPress CTRL+C to close the application.\n&lt;/span&gt;
       8: invokevirtual &lt;span class="c"&gt;#65                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V&lt;/span&gt;
      11: ldc2_w        &lt;span class="c"&gt;#110                // long 9223372036854775807l&lt;/span&gt;
      14: invokestatic  &lt;span class="c"&gt;#112                // Method java/lang/Thread.sleep:(J)V&lt;/span&gt;
      17: &lt;span class="k"&gt;return

  &lt;/span&gt;private static int lambda&lt;span class="nv"&gt;$suppliersC$2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokevirtual &lt;span class="c"&gt;#11                 // Method java/lang/Object.hashCode:()I&lt;/span&gt;
       4: ireturn

  private static int lambda&lt;span class="nv"&gt;$suppliersB$1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;int&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: iload_0
       1: ireturn

  private static int lambda&lt;span class="nv"&gt;$suppliersA$0&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: iconst_0
       1: ireturn
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bom, com isso, podemos ver o poder que essa propriedade pode nos ajudar caso precisarmos enfrentar problemas parecidos com esse, na qual precisaremos analizar as inner classes geradas a partir de lambdas expressions.&lt;/p&gt;

&lt;p&gt;Novamente, gostaria de agradecer ao Wellington por compartilhar sua experiência e espero que eu possa ter agregado a todos vocês um pouco mais com essa minha experiência e que acendam a vontade de todos para compartilhar e ajudar cada vez mais uns aos outros, como uma comunidade tem que ser!&lt;/p&gt;

&lt;p&gt;Obrigado a todos e até o próximo artigo!!!&lt;/p&gt;

&lt;h3&gt;
  
  
  Source dos exemplos: &lt;sup id="fnref5"&gt;5&lt;/sup&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/CreatingLambdaExpression.java" rel="noopener noreferrer"&gt;CreatingLambdaExpression.java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/CollectingIntegerListFromLambdaExpressions.java" rel="noopener noreferrer"&gt;CollectingIntegerListFromLambdaExpressions.java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Referências
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/" rel="noopener noreferrer"&gt;&lt;strong&gt;"Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expression" by Venkat Subramaniam&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;: Livro: &lt;a href="https://www.amazon.com/Effective-Java-Joshua-Bloch/dp/0134685997/ref=sr_1_1?keywords=effective+java&amp;amp;qid=1657086875&amp;amp;s=books&amp;amp;sprefix=effective%2Cstripbooks%2C272&amp;amp;sr=1-1" rel="noopener noreferrer"&gt;Effective Java - Joshua Bloch&lt;/a&gt;;&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/?java/lang/invoke/LambdaMetafactory.html" rel="noopener noreferrer"&gt;Javadoc: java.lang.invoke.LambdaMetafactory&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://bugs.openjdk.org/browse/JDK-8023524" rel="noopener noreferrer"&gt;Issue: JDK-8023524 - Mechanism to dump generated lambda classes / log lambda code generation&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/41570839/finding-a-java-lambda-from-its-mangled-name-in-a-heap-dump" rel="noopener noreferrer"&gt;StackOverflow: Finding a Java lambda from its mangled name in a heap dump&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://www.eclipse.org/mat/" rel="noopener noreferrer"&gt;Eclipse Memory Analyzer(MAT)&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://www.jbang.dev/" rel="noopener noreferrer"&gt;JBang&lt;/a&gt;; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>braziliandevs</category>
      <category>java</category>
      <category>jvm</category>
    </item>
    <item>
      <title>[PT-BR] Lambda Expressions não são classes anônimas?</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Wed, 06 Jul 2022 06:39:59 +0000</pubDate>
      <link>https://dev.to/dearrudam/lambda-expressions-nao-sao-classes-anonimas-5eho</link>
      <guid>https://dev.to/dearrudam/lambda-expressions-nao-sao-classes-anonimas-5eho</guid>
      <description>&lt;p&gt;Seguindo essa série sobre &lt;strong&gt;"Programação Funcional com Java"&lt;/strong&gt;, me deperei com uma dúvida, que talvez não seja só minha, então vamos lá:&lt;/p&gt;

&lt;h2&gt;
  
  
  Lambda Expressions não são classes anônimas?
&lt;/h2&gt;

&lt;p&gt;Talvez o óbvio pra mim, não seja óbvio para vocês e vice-versa!&lt;/p&gt;

&lt;p&gt;Então, nesse texto, gostaria de abordar um pouco sobre Lambda Expression!&lt;/p&gt;

&lt;p&gt;Com Java 8, muitas features, como Lambdas Expression, Streams API e Method References nos permitiram a desenvolver com Java de uma maneira diferente, uma maneira &lt;strong&gt;funcional&lt;/strong&gt;. Estamos no Java 18, com o Java 19 batendo em nossa porta, com previsão para setembro/2022, e algumas questões sobre essas features, que apesar de não serem tão novas, pairam em nossas cabeças. &lt;/p&gt;

&lt;h2&gt;
  
  
  Objetos de Função
&lt;/h2&gt;

&lt;p&gt;Antes dessas novas features introduzidas pelo Java 8, as interfaces (ou, raramente, as classes abstratas) com um único método abstrato eram utilizadas para representar &lt;em&gt;tipos de função&lt;/em&gt;. As instâncias dessas classes são conhecidas como &lt;em&gt;objetos de função&lt;/em&gt;, e através dessas implementações, tinhamos uma forma para representar funções ou ações em nossas aplicações.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Desde o JDK 1.1, o principal meio para criar objetos de função era por &lt;em&gt;classes anônimas&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;JButton&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Click!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addActionListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ActionListener&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@Override&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;actionPerformed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ActionEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// that's a nostalgic thing, do ya!?&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quem nunca implementou algo assim utilizando a API Swing do Java? Tudo bem, este código é nostálgico, talvez ele traga lembranças não tão agradáveis, então, brincadeiras de lado, vamos olhar outro fragmento de código onde precisamos ordenar palavras pelo comprimento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Comparator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compare&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui, instanciamos uma classe anônima e implementamos a lógica exigida pela interface comparator onde, se retornar -1, significa que o comprimento do primeiro argumento nomeado como &lt;em&gt;word1&lt;/em&gt;, é menor que o comprimento do segundo argumento nomeado como &lt;em&gt;word2&lt;/em&gt;, se retornar 0 significa que ambos argumentos tem o mesmo comprimento e, finalmente, se retornar 1 significa que o comprimento do argumento &lt;em&gt;word1&lt;/em&gt; é maior que o argumento &lt;em&gt;word2&lt;/em&gt;. (Desculpem-me, mas sempre tive que consultar o javadoc para implementar essa lógica, ela sempre me confundia... :P !)&lt;/p&gt;

&lt;p&gt;Classes anônimas eram adequadas aos padrões clássicos quando eram exigidos a criação de &lt;em&gt;objetos de função&lt;/em&gt;, lembram do design pattern Strategy &lt;sup id="fnref2"&gt;2&lt;/sup&gt;?&lt;/p&gt;

&lt;p&gt;Mas toda essa verbosidade exigida na utilização das classes anônimas fazia com a programação funcional se tornasse uma possibilidade bem desagradável.&lt;/p&gt;

&lt;p&gt;Pois bem, com o Lambda expressions podemos trazer melhorias significativas a esse código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compare&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;word2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Todo aquela verbosidade - instanciação e declaração da classe anônima com parenteses e assinatura do método -  desapareceu e o comportamento ficou um pouco mais evidente. Agradeçam as expressões lambdas!&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas o que são expressões lambdas?
&lt;/h2&gt;

&lt;p&gt;No Java 8, interfaces com um único método abstrato agora recebem um tratamento especial. A linguagem agora permite que expressões lambdas, ou apenas lambdas (para abreviar) implemente objetos de função que representam essas interfaces, que agora essas podem ser chamadas de &lt;em&gt;Interfaces Funcionais&lt;/em&gt; - sim \o/... podemos falar mais sobre interfaces funcionais em um futuro próximo.&lt;/p&gt;

&lt;p&gt;Então podemos dizer que expressão lambdas são funções anônimas que podemos adicionar em nossos códigos afim de representar um objeto de função.&lt;/p&gt;

&lt;p&gt;Você pode estar agora se convencendo que, debaixo do capô, as expressões lambdas são convertidas para classes anônimas, não é?&lt;/p&gt;

&lt;p&gt;É agora que a coisa fica interessante!&lt;/p&gt;

&lt;p&gt;Olhem esse código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsingAnonymousClasses&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="n"&gt;th&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Runnable&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"thread [%s] is doing A..."&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;

        &lt;span class="n"&gt;th&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Runnable&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"thread [%s] is doing B..."&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;

        &lt;span class="n"&gt;th&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Runnable&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"thread [%s] is doing C..."&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;

        &lt;span class="n"&gt;th&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por ora, ignore a orquestração da execução das threads, ok ?&lt;/p&gt;

&lt;p&gt;Neste código, podemos ver que implementamos 3 (três) classes anônimas com comportamentos distintos.&lt;/p&gt;

&lt;p&gt;Para desencargo de consciência, vamos listar as classes compiladas a partir deste código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
├── UsingAnonymousClasses&lt;span class="nv"&gt;$1&lt;/span&gt;.class
├── UsingAnonymousClasses&lt;span class="nv"&gt;$2&lt;/span&gt;.class
├── UsingAnonymousClasses&lt;span class="nv"&gt;$3&lt;/span&gt;.class
└── UsingAnonymousClasses.class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos criar uma versão e utilizar lambdas ao invés de classes anônimas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsingLambdaExpressions&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="n"&gt;th&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"thread [%s] is doing A..."&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;())));&lt;/span&gt;
        &lt;span class="n"&gt;th&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"thread [%s] is doing B..."&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;())));&lt;/span&gt;
        &lt;span class="n"&gt;th&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;th&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"thread [%s] is doing C..."&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;())));&lt;/span&gt;
        &lt;span class="n"&gt;th&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;        
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Muito bem, vamos então conferir as classes compiladas a partir desta nova versão de código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
└── UsingLambdaExpressions.class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, na verdade, as expressões lambdas não são convertidas para classes anônimas, logo, elas não são classes anônimas!!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas como elas são implementadas afinal!?
&lt;/h2&gt;

&lt;p&gt;Utilizando o utilitário &lt;em&gt;javap&lt;/em&gt; podemos dar uma espiada no bytecode gerado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/ &lt;span class="nv"&gt;$ &lt;/span&gt;javap &lt;span class="nt"&gt;-c&lt;/span&gt; UsingLambdaExpressions.class 
Compiled from &lt;span class="s2"&gt;"UsingLambdaExpressions.java"&lt;/span&gt;
public class UsingLambdaExpressions &lt;span class="o"&gt;{&lt;/span&gt;
  public UsingLambdaExpressions&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: aload_0
       1: invokespecial &lt;span class="c"&gt;#8                  // Method java/lang/Object."&amp;lt;init&amp;gt;":()V&lt;/span&gt;
       4: &lt;span class="k"&gt;return

  &lt;/span&gt;public static void main&lt;span class="o"&gt;(&lt;/span&gt;java.lang.String...&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    Code:
       0: new           &lt;span class="c"&gt;#16                 // class java/lang/Thread&lt;/span&gt;
       3: dup
       4: invokedynamic &lt;span class="c"&gt;#18,  0             // InvokeDynamic #0:run:()Ljava/lang/Runnable;&lt;/span&gt;
       9: invokespecial &lt;span class="c"&gt;#22                 // Method java/lang/Thread."&amp;lt;init&amp;gt;":(Ljava/lang/Runnable;)V&lt;/span&gt;
      12: astore_1
      13: aload_1
      14: invokevirtual &lt;span class="c"&gt;#25                 // Method java/lang/Thread.start:()V&lt;/span&gt;
      17: new           &lt;span class="c"&gt;#16                 // class java/lang/Thread&lt;/span&gt;
      20: dup
      21: invokedynamic &lt;span class="c"&gt;#28,  0             // InvokeDynamic #1:run:()Ljava/lang/Runnable;&lt;/span&gt;
      26: invokespecial &lt;span class="c"&gt;#22                 // Method java/lang/Thread."&amp;lt;init&amp;gt;":(Ljava/lang/Runnable;)V&lt;/span&gt;
      29: astore_1
      30: aload_1
      31: invokevirtual &lt;span class="c"&gt;#25                 // Method java/lang/Thread.start:()V&lt;/span&gt;
      34: new           &lt;span class="c"&gt;#16                 // class java/lang/Thread&lt;/span&gt;
      37: dup
      38: invokedynamic &lt;span class="c"&gt;#29,  0             // InvokeDynamic #2:run:()Ljava/lang/Runnable;&lt;/span&gt;
      43: invokespecial &lt;span class="c"&gt;#22                 // Method java/lang/Thread."&amp;lt;init&amp;gt;":(Ljava/lang/Runnable;)V&lt;/span&gt;
      46: astore_1
      47: aload_1
      48: invokevirtual &lt;span class="c"&gt;#25                 // Method java/lang/Thread.start:()V&lt;/span&gt;
      51: &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Curiosamente, não precisamos ter tanto conhecimento para interpretar bytecodes em java para conseguir ver que as expressões lambdas se tornaram instruções chamadas &lt;strong&gt;InvokeDynamic&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Mas e o corpo das lambdas?! &lt;/p&gt;

&lt;p&gt;Dependendo do contexto, o compilador irá converter o corpo das lambdas em um desses possiveis casos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ou em métodos estáticos (static methods) da própria classe &lt;/li&gt;
&lt;li&gt;Ou métodos vinculado a instâncias definidas (instance methods) &lt;/li&gt;
&lt;li&gt;Ou simplesmente rotear a chamada para métodos existente em uma outras classes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interessante não é!? &lt;/p&gt;

&lt;p&gt;Bom, agradeço e muito ao &lt;strong&gt;"Venkat Subramaniam"&lt;/strong&gt;, pois em uma palestra que ele apresentou no &lt;strong&gt;Devoxx&lt;/strong&gt; em 2015 me ensinou muito! Super recomendo! Segue o link da palestra: &lt;a href="https://www.youtube.com/watch?v=1OpAgZvYXLQ" rel="noopener noreferrer"&gt;Get a Taste of Lambdas and Get Addicted to Streams by Venkat Subramaniam&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Até o próximo artigo!!!&lt;/p&gt;

&lt;h3&gt;
  
  
  Source dos exemplos &lt;sup id="fnref3"&gt;3&lt;/sup&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/UsingAnonymousClasses.java" rel="noopener noreferrer"&gt;UsingAnonymousClasses.java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/UsingLambdaExpressions.java" rel="noopener noreferrer"&gt;UsingLambdaExpressions.java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Referências:
&lt;/h3&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Livro: &lt;a href="https://www.amazon.com/Effective-Java-Joshua-Bloch/dp/0134685997/ref=sr_1_1?keywords=effective+java&amp;amp;qid=1657086875&amp;amp;s=books&amp;amp;sprefix=effective%2Cstripbooks%2C272&amp;amp;sr=1-1" rel="noopener noreferrer"&gt;Effective Java - Joshua Bloch&lt;/a&gt;; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Desing Patterns - Strategy &lt;a href="https://refactoring.guru/pt-br/design-patterns/strategy" rel="noopener noreferrer"&gt;[PT-BR]&lt;/a&gt;/&lt;a href="https://refactoring.guru/design-patterns/strategy" rel="noopener noreferrer"&gt;[EN-US]&lt;/a&gt; | Livro: &lt;a href="https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_1?crid=WNFJ58ETWC0D&amp;amp;keywords=design+patterns&amp;amp;qid=1657081268&amp;amp;sprefix=design+patterns%2Caps%2C266&amp;amp;sr=8-1" rel="noopener noreferrer"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://www.jbang.dev/" rel="noopener noreferrer"&gt;JBang&lt;/a&gt;; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>java</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>[PT-BR] Estilo Imperativo X Estilo Declarativo com Java</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Tue, 05 Jul 2022 08:33:44 +0000</pubDate>
      <link>https://dev.to/dearrudam/pr-br-estilo-imperativo-x-estilo-declarativo-com-java-2a02</link>
      <guid>https://dev.to/dearrudam/pr-br-estilo-imperativo-x-estilo-declarativo-com-java-2a02</guid>
      <description>&lt;p&gt;Estou lendo um livro muito legal do renomado &lt;strong&gt;Venkat Subramaniam&lt;/strong&gt; : &lt;a href="https://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/" rel="noopener noreferrer"&gt;&lt;strong&gt;"Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expression"&lt;/strong&gt;&lt;/a&gt; e por estar gostando muito, decidi publicar posts com o intuido de fixar meu aprendizado e assim também ajudar quem interessar!&lt;/p&gt;

&lt;h2&gt;
  
  
  Mude a sua forma de pensar ao escrever seus códigos
&lt;/h2&gt;

&lt;p&gt;Desde sua concepção, o Java tem fornecido uma forma imperativa para escrevermos nossos códigos, isto é: dizemos ao Java, passo a passo, o que queremos que ele faça e assim ter o resultado esperado. Essa forma tem funcionado, porém códigos imperativos tendem a serem verbosos e difíceis de manter. Para melhor descrever esse cenário, vamos programar um pouco! :)&lt;/p&gt;

&lt;p&gt;Vamos dizer que temos uma certa necessidade em nossa regra de negócio: precisamos verificar se a cidade "São Paulo" faz parte de uma lista de cidades fornecida, para que assim possamos efetuar outras regras de negócios...&lt;/p&gt;

&lt;p&gt;Pois bem, talvez você tenha imaginado construir um código similar conforme abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cities&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"São Paulo"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Found São Paulo? "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código acima, podemos ver um forma imperativa de busca para verificar se &lt;em&gt;São Paulo&lt;/em&gt; está contido na coleção &lt;em&gt;cities&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Mas o que é utilizar o estilo imperativo?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Estilo Imperativo - descrevemos explicitamente COMO o programa deve fazer suas tarefas especificando cada instrução passo a passo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apesar de simples, é um código nada intuitivo de se &lt;strong&gt;ler&lt;/strong&gt; e &lt;strong&gt;compreender&lt;/strong&gt;; há variáves que, apesar de serem necessárias para computar nossa busca, acabam ofuscando o que realmente o código tem a intenção de executar, deixando-o distante da linguagem de negócio. &lt;/p&gt;

&lt;p&gt;Primeiramente, definimos a varíavel boleana nomeada &lt;strong&gt;"found"&lt;/strong&gt; que será nossa flag que dirá se encontramos ou não a cidade, e então iteramos entre os elementos da coleção &lt;strong&gt;cities&lt;/strong&gt;. Se encontrarmos a cidade que estamos procurando então definimos a flag como &lt;strong&gt;"true"&lt;/strong&gt; e paramos a iteração na lista. Daí então, escrevemos na saída padrão o resultado de nossa busca.&lt;/p&gt;

&lt;p&gt;Além de cansativo, traz muitos detalhes de implementação que ofuscam não acham!?&lt;/p&gt;

&lt;p&gt;Como desbravadores da linguagem Java, no minuto que olhamos esse código nós rapidamente pensaremos em uma construção mais concisa e fácil de ler, ao parecido com isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Found São Paulo?:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"São Paulo"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Que diferença não é!?&lt;/p&gt;

&lt;p&gt;Isso é um exemplo do estilo declarativo: agora podemos rapidamente compreender a intenção do código para o negócio de maneira mais concisa e direta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Estilo Declarativo - descrevemos O QUE o programa deve fazer sem explicitamente dizer COMO ele deve fazer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Outras melhorias que podemos perceber em nosso código com essa abordagem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não há bagunça em torno do código com variaveis mutáveis;&lt;/li&gt;
&lt;li&gt;A iteração na lista ocorrem "debaixo do capô";&lt;/li&gt;
&lt;li&gt;Menos desordem;&lt;/li&gt;
&lt;li&gt;Mais clareza; Foco na regra de negócio;&lt;/li&gt;
&lt;li&gt;Menos impedância: o código segue a intenção do negócio;&lt;/li&gt;
&lt;li&gt;Menos propenso a erros;&lt;/li&gt;
&lt;li&gt;Maior facilidade de entendimento e manutenção;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bom, concordo que estamos olhando um exemplo simples - uma método para checar se um elemento está presente em uma coleção já está faz tempo no Java.&lt;/p&gt;

&lt;p&gt;Mas agora, conhecendo esses benefícios na utilização desse estilo &lt;strong&gt;"declarativo"&lt;/strong&gt;, por que não utilizar essa abordagem para não escrever códigos imperativos para operações mais avançadas como por exemplo: processamento com dados complexos (oriundos de fontes externas: banco de dados, web, ou arquivos), programação concorrente, etc.? &lt;/p&gt;

&lt;p&gt;Calma, mostre-me mais algum exemplo mais avançado!&lt;/p&gt;

&lt;h2&gt;
  
  
  Além de casos simples
&lt;/h2&gt;

&lt;p&gt;Vamos olhar um outro exemplo:&lt;/p&gt;

&lt;p&gt;Vamos definir uma coleção de preços e vamos desenvolver algumas formas para calcular descontos &lt;sup id="fnref1"&gt;1&lt;/sup&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Monetary&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCurrency&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BRL"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos dizer que queremos o total de preços que sejam maiores que BRL 18.00, aplicando 15% de desconto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uma forma habitual
&lt;/h3&gt;

&lt;p&gt;Em uma forma habitual, chegaríamos um código como o abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;totalOfDiscountedPrices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MonetaryAmount&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;totalOfDiscountedPrices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;totalOfDiscountedPrices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;multiply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Total of discounted prices: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;totalOfDiscountedPrices&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apesar de ser um código bem familiar, é interessante analisá-lo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primairamente iniciamos a variável para mantermos o total dos preços com desconto;&lt;/li&gt;
&lt;li&gt;Iteramos na coleção de preços, pegando os preços que forem maior que BRL 18, e para cada preço encontrado, computamos o preço com desconto e adicionamos ao valor total;&lt;/li&gt;
&lt;li&gt;E para terminar, escrevemos o total dos preços com desconto na saída da aplicação.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aqui está a saída que o código produziu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Total of discounted prices: BRL 80.75
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Funcionou conforme esperado, mas a sensação de sugeira ao escrever esse código com certeza veio a tona. Muitos de nós (incluindo eu, é claro) aprendemos assim e utilizavamos o que podíamos de acordo com a ferramentas que temos. Se olharmos esse código, ele está cuidando de coisas bem baixo nível perto do que o negócio em si pede. &lt;/p&gt;

&lt;p&gt;Códigos como esse sofre de "Primitive Obsession" &lt;sup id="fnref2"&gt;2&lt;/sup&gt; além de desafiarem o princípio de responsabilidade única do "SOLID" (listamos, filtramos e calculamos em um só lugar - multipla responsabilidade).&lt;/p&gt;

&lt;h3&gt;
  
  
  Bom, podemos fazer melhor...realmente bem melhor!
&lt;/h3&gt;

&lt;p&gt;Olhando com calma, podemos deixar o nosso código mais próximo da necessidade do negócio, respeitando o requerimento especificado e, diminuindo assim chances de má interpretação.&lt;/p&gt;

&lt;p&gt;Vamos evitar criar variáveis mutáveis e manipulá-las atribuindo valores e vamos trazer as coisas para um nível maior de abstração, assim como no código abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;totalOfDiscountedPrices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compareTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;multiply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reduce&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nl"&gt;Money:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Total of discounted prices: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;totalOfDiscountedPrices&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E ao executar esse código, temos a mesma saída conforme mostrado no exemplo imperativo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Total of discounted prices: BRL 80.75 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como em nosso primeiro exemplo, nós reduzimos longas linhas de código com um encadeiamento de métodos a partir do método &lt;em&gt;stream()&lt;/em&gt; a partir da lista de preços. &lt;br&gt;
O código está conciso, nós conseguimos até ler em voz alta e assim perceber o quanto próximo da especificação do requerimento estamos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;filtrar os preços que foram maior que BRL 18.00;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;mapeie o preço atual para um novo preço aplicando o desconto de 15% e...&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;reduza os preços com desconto somando os e armazenando na variável **totalOfDiscountedPrices&lt;/em&gt;**. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A utilização do método &lt;em&gt;stream()&lt;/em&gt; fornecido pelas Collections do Java trazem um tipo especial de iterator com uma variedade de funções especiais que poderemos trazer em próximos posts!&lt;/p&gt;

&lt;p&gt;Ao invés de explicitamente iterar entre os preços na lista (de maneira imperativa), nós delegamos essa iteração para a implementação interna do iterator e utilizamos alguns métodos especiais, como o &lt;em&gt;filter&lt;/em&gt;, onde definimos o a condição do filtro, e o &lt;em&gt;map&lt;/em&gt;, onde dado um valor podemos transformar em outro, e assim conseguir o comportamento desejado de forma &lt;strong&gt;declarativa&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Novamente, podemos confirmar essas melhorias:&lt;/p&gt;

&lt;h3&gt;
  
  
  Melhorias utilizando um estilo declarativo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Não há bagunça em torno do código com variaveis mutáveis;&lt;/li&gt;
&lt;li&gt;A iteração na lista ocorrem "debaixo do capô";&lt;/li&gt;
&lt;li&gt;Menos desordem;&lt;/li&gt;
&lt;li&gt;Mais clareza; Foco na regra de negócio;&lt;/li&gt;
&lt;li&gt;Menos impedância: o código segue a intenção do negócio;&lt;/li&gt;
&lt;li&gt;Menos propenso a erros;&lt;/li&gt;
&lt;li&gt;Maior facilidade de entendimento e manutenção;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com isso, compreendo o porque é interessante repensar nossa maneira de programar e procurar utilizar o estilo declarativo em nossos códigos.&lt;/p&gt;

&lt;p&gt;Estou lendo um livro muito legal do renomado &lt;strong&gt;Venkat Subramaniam&lt;/strong&gt; : &lt;a href="https://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/" rel="noopener noreferrer"&gt;&lt;strong&gt;"Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expression"&lt;/strong&gt;&lt;/a&gt; e por estar gostando muito, decidi publicar posts com o intuido de fixar meu aprendizado e assim também ajudar quem interessar!&lt;/p&gt;

&lt;p&gt;Source dos exemplos &lt;sup id="fnref3"&gt;3&lt;/sup&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/ImperativeSample01.java" rel="noopener noreferrer"&gt;https://github.com/dearrudam/learning-notes/blob/main/java/ImperativeSample01.java&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/DeclarativeSample01.java" rel="noopener noreferrer"&gt;https://github.com/dearrudam/learning-notes/blob/main/java/DeclarativeSample01.java&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/ImperativeDiscount.java" rel="noopener noreferrer"&gt;https://github.com/dearrudam/learning-notes/blob/main/java/ImperativeDiscount.java&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/dearrudam/learning-notes/blob/main/java/DeclarativeDiscount.java" rel="noopener noreferrer"&gt;https://github.com/dearrudam/learning-notes/blob/main/java/DeclarativeDiscount.java&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Estou usando &lt;a href="http://javamoney.github.io/" rel="noopener noreferrer"&gt;JSR 354 Java Money&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Primitive Obsession &lt;a href="https://refactoring.guru/pt-br/smells/primitive-obsession" rel="noopener noreferrer"&gt;PT-BR&lt;/a&gt; ou &lt;a href="https://refactoring.guru/smells/primitive-obsession" rel="noopener noreferrer"&gt;EN-US&lt;/a&gt;  ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Utilizei &lt;a href="https://www.jbang.dev/" rel="noopener noreferrer"&gt;JBang&lt;/a&gt;;  ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>java</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>[PT-BR] Be the exception! Dicas para dominar exceções em seus códigos Java</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Mon, 12 Jul 2021 20:07:20 +0000</pubDate>
      <link>https://dev.to/dearrudam/be-the-exception-dicas-para-dominar-excecoes-em-seus-codigos-java-4nlo</link>
      <guid>https://dev.to/dearrudam/be-the-exception-dicas-para-dominar-excecoes-em-seus-codigos-java-4nlo</guid>
      <description>&lt;p&gt;Esse artigo foi a base da palestra que apresentei no 1o. &lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=R-3v90oM0TI&amp;amp;t=1808s" rel="noopener noreferrer"&gt;SouJava Lightning Talks&lt;/a&gt;&lt;/strong&gt; então fique a vontade de conferir, okay?! &lt;/p&gt;

&lt;p&gt;Você já se perguntou: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Como será que devo criar as exceções para minha as minhas regras de negócio?&lt;/li&gt;
&lt;li&gt;Será que não estou criando exceções demais?&lt;/li&gt;
&lt;li&gt;Em relação às exceções das regras de negócios que estou criando: devo extender de RuntimeException ou de Exception?&lt;/li&gt;
&lt;li&gt;E quanto a lidar com o tratamento de exceções:&lt;/li&gt;
&lt;li&gt;E as mensagem de erro, estou sendo claro nelas?&lt;/li&gt;
&lt;li&gt;será que estou logando de maneira adequada a captura de exceções em meus códigos?&lt;/li&gt;
&lt;li&gt;Será que estou "silenciando" uma exceção de maneira equivocada?&lt;/li&gt;
&lt;li&gt;Será que estou desenvolvendo meus códigos "orientados à exceções"?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É comum desenvolvedores Java enfrentarem esses dilemas quando se há a necessidade de desenvolver ou lidar com exceções em seus códigos. &lt;/p&gt;

&lt;p&gt;Uns lidam com exceções como &lt;strong&gt;"erros"&lt;/strong&gt; da  aplicação, outros como &lt;strong&gt;"caminhos alternativos"&lt;/strong&gt; para as regras de negócios em questão e assim por diante. É algo interessante e muitas vezes interpretativa.&lt;/p&gt;

&lt;p&gt;Tem desenvolvedores que se utilizam da forma que a linguagem &lt;strong&gt;"força"&lt;/strong&gt; o tratamento das exceções a fim que atingir o seu objetivo, e acho que todos eles estão corretos de acordo com o cada contexto alvo. &lt;/p&gt;

&lt;p&gt;Há uns meses atrás tive uma discussões interessantes com outros desenvolvedores e em particular com a comunidade &lt;strong&gt;SouJava&lt;/strong&gt; sobre o assunto. Quero parabenizar a todos pelas ótimas discussões &lt;strong&gt;(You rock folks!!!)&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Mas uma coisa que temos que admitir: pode não parecer, mas exceções são peças importantes para entender os cenários &lt;strong&gt;"excepcionais"&lt;/strong&gt; que &lt;strong&gt;"brotam"&lt;/strong&gt; em tempo de desenvolvimento e de execução em nossos códigos.&lt;/p&gt;

&lt;p&gt;Vamos explorar algumas dessas dicas que possam nos ajudar a modelar e lidar com exceções em nossos códigos Java. &lt;/p&gt;

&lt;h2&gt;
  
  
  Não conhecer a hierarquia de classes de exceções do Java
&lt;/h2&gt;

&lt;p&gt;Essa é uma dúvida que pode atrapalhar e muito a modelagem do código.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fem6woonxnfn1x7nfu2t2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fem6woonxnfn1x7nfu2t2.png" alt="image" width="650" height="400"&gt;&lt;/a&gt;&lt;br&gt;
Olhando a hierarquia das classes de exceções do Java podemos reconhecer que as classes em vermelho são as consideradas &lt;strong&gt;Checked Exceptions&lt;/strong&gt; e as amarelas são as &lt;strong&gt;Unchecked Exception&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Não saber a diferença entre Checked Exceptions e Unchecked Exceptions e quando usá-las
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Checked Exceptions&lt;/strong&gt; são exceções que devem ser usadas para &lt;strong&gt;erros recuperáveis ou que sejam requisitos de um regra de negócio importante&lt;/strong&gt;. Normalmente exceções de seu domínio classificam-se nessa categoria. &lt;strong&gt;O compilador da linguagem vai obrigar o tratamento dela sempre que um método que declarativamente a lançar for chamado&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Já as &lt;strong&gt;Unchecked Exceptions&lt;/strong&gt; devem ser utilizadas &lt;strong&gt;quando algum cenário "excepcional" é irreversível ou irrecuperável&lt;/strong&gt;. A princípio não deveríamos capturar esses tipos de exceções. Normalmente utilizam-se &lt;strong&gt;"Tratadores de exceções"&lt;/strong&gt; para esse fim, que geralmente é o de notificar o utilizador da regra que algo aconteceu e não há nada o que fazer para aquela situação.&lt;/p&gt;
&lt;h2&gt;
  
  
  Capturar toda exceção como Exception
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Pra quê criar minhas exceções, vamos utilizar a que tem!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Bom, capturar qualquer exceção (ou todas... hehehe) como Exception pode ser um problema. O mesmo ocorre do lado de quem está escrevendo um método que lança somente exceções do tipo Exception.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;debitAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transferTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;creditAccount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// Ok, mas o que aconteceu?&lt;/span&gt;
    &lt;span class="c1"&gt;// Teremos que checar a mensagem, e torcer para que ela seja útil&lt;/span&gt;
    &lt;span class="c1"&gt;// E talvez analisar a stacktrace&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código acima, por utilizar somente a classe Exception, a identificação está prejudicada então &lt;strong&gt;se a mensagem de erro não ajudar, a análise do stacktrace será um dos únicos pontos para sua identificação&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Como a classe Exception é uma &lt;strong&gt;checked exception&lt;/strong&gt; então crie suas exceções a partir dela para os cenários queira que o compilador force o tratamento da mesma. &lt;strong&gt;Lembre-se de criar suas exceções checadas para casos que devem e que realmente fazem sentido de acordo com seu domínio&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criar muitas exceções de maneira desordenada
&lt;/h2&gt;

&lt;p&gt;Cuidado pra não criar exceções para tudo! Caso o fizer, provavelmente terá muitas classes para gerenciar e manter então crie somente as exceções necessárias e seja claro nas mensagens.&lt;/p&gt;

&lt;p&gt;Imagine em um sistema de transferência de valores entre contas, onde criássemos uma exceção para cada cenário:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;debitAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transferTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;creditAccount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvalidAmountException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// quantia inválida, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExceededAmountException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// quantia excedida, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BalanceNotAvailableException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// saldo não disponível, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DisabledCreditAccountException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// conta à creditar está desativada, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DisabledDebitAccountException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// conta à debitar está desativada, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BlockedCreditAccountException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// conta à creditar está bloqueada, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BlockedDebitAccountException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// conta à debitar está bloqueada e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BusinessException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// alguma outra coisa aconteceu, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E se utilizarmos essa outra sintaxe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;debitAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transferTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;creditAccount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvalidAmountException&lt;/span&gt; 
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;ExceededAmountException&lt;/span&gt; 
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;BalanceNotAvailableException&lt;/span&gt; 
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;DisabledCreditAccountException&lt;/span&gt; 
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;DisabledDebitAccountException&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;BlockedCreditAccountException&lt;/span&gt; 
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;BlockedDebitAccountException&lt;/span&gt; 
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;BusinessException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// quantia inválida ou&lt;/span&gt;
    &lt;span class="c1"&gt;// quantia excedida ou&lt;/span&gt;
    &lt;span class="c1"&gt;// saldo não disponível ou&lt;/span&gt;
    &lt;span class="c1"&gt;// conta à creditar está desativada ou&lt;/span&gt;
    &lt;span class="c1"&gt;// conta à debitar está desativada ou&lt;/span&gt;
    &lt;span class="c1"&gt;// conta à creditar está bloqueada ou&lt;/span&gt;
    &lt;span class="c1"&gt;// conta à debitar está bloqueada ou&lt;/span&gt;
    &lt;span class="c1"&gt;// alguma outra coisa aconteceu, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nada agradável, não é?&lt;/p&gt;

&lt;p&gt;Que tal reduzir nossa lista de exceções:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fyuml.me%2Fdearrudam%2Fbe-the-exception.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fyuml.me%2Fdearrudam%2Fbe-the-exception.png" alt="image" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assim ficará mais sucinta o seu tratamento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;debitAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transferTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;creditAccount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BalanceNotAvailableException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// saldo não disponível, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DeactivatedAccountException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// uma ou ambas estão desativadas, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BlockedAccountException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// uma ou ambas estão bloqueadas, e agora?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claro, não existe &lt;strong&gt;"bala de prata"&lt;/strong&gt;. Será preciso utilizar mensagens bem claras para fornecer um bom contexto para identificar o ocorrido. Em nosso exemplo, mensagens claras serão necessárias, especialmente as exceções DeactivatedAccountException e BlockedAccountException. Ambas não deixa claro se a debitAccount ou creditAccount ou ambas causaram o cenário em questão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Não utilizar mensagens claras nas exceções
&lt;/h2&gt;

&lt;p&gt;Acredito que é unânime essa dica: sempre use mensagens claras em suas exceções. Isso ajudará bastante a encontrar e entender o erro. &lt;br&gt;
Normalmente é utilizado um arquivos de propriedades para armazenar essas mensagens de erros, fornecendo assim talvez uma maneira de exibir a mensagem na camada de apresentação de maneira internacionalizada. &lt;/p&gt;
&lt;h2&gt;
  
  
  Silenciar exceções
&lt;/h2&gt;

&lt;p&gt;Outra abordagem muito equivocada e muito comum que ocorre é no tratamento de exceções que o chamador "acham desnecessário" realizar o tratamento, simplesmente ignorando o fato da ocorrência do lançamento de exceção.&lt;/p&gt;

&lt;p&gt;Por exemplo, você pode talvez ter visto algo assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Connection&lt;/span&gt;  &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConnection&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// executando uma regra incrível aqui&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQLException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;handleSQLException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQLException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Não finalizar/fechar recursos abertos no contexto que ocorreu a exceção
&lt;/h2&gt;

&lt;p&gt;Um dos fatores de leaks em aplicações java é o não fechamento correto de recursos como conexão de banco de dados, streams ou qualquer outro componente que tem por necessidade serem fechados ao finalizar o bloco de código que eles foram abertos ou gerados. &lt;br&gt;
Utilize o bloco &lt;strong&gt;finally&lt;/strong&gt; para fechar os recursos ou componentes necessários.&lt;/p&gt;

&lt;p&gt;Então, não faça isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Connection&lt;/span&gt;  &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConnection&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// executando uma regra incrível aqui&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQLException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;handleSQLException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meu conselho é fazer algo assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Connection&lt;/span&gt;  &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConnection&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// executando uma regra incrível aqui&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQLException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;handleSQLException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQLException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalStateException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"algo grave aconteceu ao fechar a conexão"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fim de ajudar a lidar com esse problema, a partir do Java 7 foi adicionado o &lt;strong&gt;try-with-resources&lt;/strong&gt; statement, onde é possível utilizar quando precisarmos trabalhar com qualquer objeto que implemente a interface &lt;strong&gt;java.lang.AutoCloseable&lt;/strong&gt;, que inclui todos os objetos que implementam &lt;strong&gt;java.io.Closeable&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Connection&lt;/span&gt;  &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConnection&lt;/span&gt;&lt;span class="o"&gt;()){&lt;/span&gt;
        &lt;span class="c1"&gt;// executando uma regra incrível aqui&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQLException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;handleSQLException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim os componentes e recursos abertos dentro do &lt;strong&gt;try()&lt;/strong&gt; serão fechados ao finalizar o bloco.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; &lt;em&gt;Uma instrução try-with-resources pode ter blocos catch e finally, exatamente como uma instrução try comum. Em uma instrução try-with-resources, qualquer catch ou finally block é executado depois que os recursos declarados são fechados.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Silenciar exceções
&lt;/h2&gt;

&lt;p&gt;Outra abordagem muito equivocada e muito comum que ocorre é no tratamento de exceções que o chamador "acham desnecessário" realizar o tratamento, simplesmente ignorando o fato da ocorrência do lançamento de exceção.&lt;/p&gt;

&lt;p&gt;Mas não se ilude, talvez a aplicação entrou em um estado inconsistente e isso ninguém quer, não é? &lt;/p&gt;

&lt;p&gt;Um outro exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CurrencyUnit&lt;/span&gt; &lt;span class="n"&gt;usd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Monetary&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCurrency&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"USD"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usd&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;maxAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bank&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAccount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;otavioAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bank&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAccount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;333&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;maxAccount&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transferTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otavioAccount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coffee&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commit&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BalanceNotAvailableException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="c1"&gt;// É impossível saber o que aconteceu aqui sem realizar um debug! &lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É impossível saber o que aconteceu aqui sem realizar um debug! (Bom, o Otávio infelizmente vai saber... ☹️).&lt;/p&gt;

&lt;p&gt;Então, sempre trate ou log essas exceções (talvez em um nível WARN ou ERROR).&lt;/p&gt;

&lt;h2&gt;
  
  
  Perder o rastreamento da pilha
&lt;/h2&gt;

&lt;p&gt;Quem sou eu pra ditar regras, não é? Mas vamos olhar o exemplo abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CurrencyUnit&lt;/span&gt; &lt;span class="n"&gt;usd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Monetary&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCurrency&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"USD"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usd&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;maxAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bank&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAccount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;otavioAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bank&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAccount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;333&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;maxAccount&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transferTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otavioAccount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coffee&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commit&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BalanceNotAvailableException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="c1"&gt;// Assim perderemos a causa raiz da exceção que é: &lt;/span&gt;
    &lt;span class="c1"&gt;// o Max não vai poder para o café pro Otávio dessa vez!&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ExceededAmountException&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para quem desenvolveu pode parecer nada significante, mas ignorar a causa raiz irá causar um desconforto para quem estiver dando o suporte caso a exceção ocorra. &lt;/p&gt;

&lt;p&gt;Se a mensagem não for clara, será necessário navegar até o ponto do código que  ocorreu a exceção. &lt;/p&gt;

&lt;p&gt;Assim perderemos a causa raiz da exceção que é: o Max não conseguiu pagar o café pro Otávio dessa vez! &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Trabalhar com exceções em Java é um assunto um tanto quanto polêmico e interessante. Tem uns que abominam, outros que se favorecem da funcionalidade e até pode ser divisor de águas quando se tenta conhecer outras linguagens (como por exemplo o Golang). &lt;/p&gt;

&lt;p&gt;Na verdade o que interessa é resolver o problema da melhor maneira possível, digo, sempre olhando os prós e os contras de cada abordagem, &lt;strong&gt;pensando não só do ponto de vista de quem desenvolve mas também do ponto de vista de manutenção&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Deixo abaixo alguns artigos que utilizei que são referências ótimas para todos sobre o tema!&lt;/p&gt;

&lt;p&gt;Espero ter &lt;strong&gt;"lançado"&lt;/strong&gt; em sua mente a vontade de explorar mais sobre esse tema e assim torço para que você continue a &lt;strong&gt;"capturar "&lt;/strong&gt; e aprender! &lt;/p&gt;

&lt;p&gt;Esse artigo foi a base da palestra que apresentei no 1o. &lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=R-3v90oM0TI&amp;amp;t=1808s" rel="noopener noreferrer"&gt;SouJava Lightning Talks&lt;/a&gt;&lt;/strong&gt; então fique a vontade de conferir!!!&lt;/p&gt;

&lt;p&gt;Deixe suas dicas, dúvidas e &lt;strong&gt;"exceções"&lt;/strong&gt;, quero dizer, sugestões aqui!&lt;/p&gt;

&lt;p&gt;Abraços e até a próxima!&lt;/p&gt;

&lt;h3&gt;
  
  
  Referências:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.oracle.com/br/technical-resources/article/java/erros-java-exceptions.html" rel="noopener noreferrer"&gt;11 Erros que desenvolvedores Java ocometem quando usam Exceptions - por Rafael Del Nero&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learning-notes.mistermicheels.com/architecture-design/exception-handling/" rel="noopener noreferrer"&gt;Exception handling - (https://learning-notes.mistermicheels.com/)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html" rel="noopener noreferrer"&gt;The try-with-resources Statement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>braziliandevs</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Using Docker day by day</title>
      <dc:creator>Maximillian Arruda</dc:creator>
      <pubDate>Wed, 14 Oct 2020 13:28:39 +0000</pubDate>
      <link>https://dev.to/dearrudam/using-docker-day-by-day-55on</link>
      <guid>https://dev.to/dearrudam/using-docker-day-by-day-55on</guid>
      <description>&lt;p&gt;Hi, everyone? How is it going? I'm here trying to learn how to share a little of my knowledge in order to learn much more with those of you who have come this far. So don't hesitate to comment, okay? Your feedback is so important. And it doesn't matter if it means that I need to stop.😜 lol!&lt;/p&gt;

&lt;p&gt;In this first article in English, I will try to be straightforward with regard to the use of Docker from the point of view of a mere software developer, which is my point of view.&lt;/p&gt;

&lt;p&gt;Solutions, such as in-memory databases (Derby, H2, among others) or the "mocking" of external services (using libraries like Mockito or solutions like Wiremock), have always been good solutions during the development of some solutions until I learned about Docker. This doesn't mean that I've replaced those items from my "utility belt" with Docker. It is because I don't believe in a "silver bullet." Also, we need to deal with the "it-depends" thinking that clarifies the issues that we are working on in the technology world, which evolves every day.&lt;/p&gt;

&lt;p&gt;The other interesting thing is that you may be able to test something that perhaps runs on a different OS that you're working on right now in a couple of seconds. You can do this instead of waiting for an IT Team to provide you with a kind of development environment that you need to communicate with. (Whoever has never faced a scenario like that probably will not understand what I'm talking about. Maybe you do. Am I right?) &lt;/p&gt;

&lt;p&gt;Okay, I think that I've talked enough! Let's see some Docker commands!&lt;/p&gt;

&lt;p&gt;For more details about Docker, take a look at the &lt;a href="https://docs.docker.com/get-started/overview/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listing of the available Docker commands:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Getting detail about a given Docker command usage:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &amp;lt;comando&amp;gt; &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What version am I using?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
Docker version 19.03.13, build 4484c46d9d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How can I see the available Docker images that are in my local environment?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Where can I find and get more Docker images?
&lt;/h2&gt;

&lt;p&gt;I'm used to getting Docker images from the &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt; site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cool! Okay, I've got the image that I want to execute, but now what? How can I execute it?
&lt;/h2&gt;

&lt;p&gt;Let's suppose that you would like to download a Docker image with a Postgres database; you should perform a search with a "postgres" word in the Docker hub. You'll find the official Docker image with Postgres and others that are not official.&lt;/p&gt;

&lt;p&gt;Docker images have a version control that is related through "tags" in order to identify the version.  &lt;/p&gt;

&lt;p&gt;By default, in case no tag is informed, the "latest" version will be used. Maybe you'll find a lot of available "tags." This means there will be many versions. &lt;/p&gt;

&lt;p&gt;Right here, it's up to you! Choose one tag, and go ahead! (In this article, I've chosen the latest one!)&lt;/p&gt;

&lt;p&gt;There are two ways to download Docker images: using a "docker pull" command or a "docker run" command. &lt;/p&gt;

&lt;h3&gt;
  
  
  Downloading Docker images:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker pull &amp;lt;imagem:tag&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check it out below. I'm getting the official "postgres" Docker image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker pull postgres

ou

&lt;span class="nv"&gt;$ &lt;/span&gt;docker pull postgres:latest

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How can I delete Docker images from my local machine?
&lt;/h3&gt;

&lt;p&gt;Watch out! I hope you're sure about this action, okay? Maybe it's not a good idea. Maybe you'll need such Docker images in the future.&lt;/p&gt;

&lt;p&gt;Ok, if you're really sure about it, don't forget to stop and delete the containers derived from the target Docker image, or you can use "brutal force" putting the "-f" flag at the command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker rmi postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How can I delete the Docker images that I'm not using from my local machine?
&lt;/h3&gt;

&lt;p&gt;Be careful, buddy! Don't delete Docker images that shouldn't be deleted. Did you?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to &lt;span class="k"&gt;continue&lt;/span&gt;? &lt;span class="o"&gt;[&lt;/span&gt;y/N] y
Deleted Images:
deleted: sha256:817f2d3d51eccb32a160cecca3b6bb95de017810498f1bb0a1d7627f59e3c5f9
deleted: sha256:f129d29273cc0b7aa597502f4dce816fbf219e186cc4d3469084574ec3add5ba
deleted: sha256:2afe8460604b177f834f0be1baacce9bbaf8b76dab822f9707154f317a106fc9
deleted: sha256:48a572b0b067213717f89cc0c69b2ed07f298e39eda2547de03e70b8ee5a7c38
deleted: sha256:8b502c3465d294c115f3362df39177b6c4126478773f6fc67a9cafbb2e2b6981
deleted: sha256:cf507dd0064138ab6667763c156a1faba8f62cc73a0d20d515096e0f9e874826
deleted: sha256:d52eacba2f4b050fb5cf846f120795cce83c70aa312c3928c1a9d1ae193580e1
deleted: sha256:35c1acf0e0075ecea7e1650b9ee37c4a2e119070ce6fcc8f82cd2f4a8a061eb1
deleted: sha256:5fed32dbbbd219cf0d7a3a3b372f1005f0132705c05a15e4a972e35d8bbdeed6
deleted: sha256:c91270ef2ff80bc858249a6a70904419b3da6c88faf68ebcc405e67fe579ddc6
deleted: sha256:93e69cdd16ed03440a0783cd1ff6892d3d7faf795315992726f5ea0977e35d8d
deleted: sha256:8b83b573f5dec4d579291deef5be1eccd0bf79ef41ea2e26961b5472b9f3fc75
deleted: sha256:9d9d3f04875ea561242877a370c072fd1fe1376004b4aa4967d0f1d1abdd1215
deleted: sha256:7c87e41d03431fdde0e13603d09a9276a945e4e7a79e34cd1019078d58b71c1d
deleted: sha256:07cab433985205f29909739f511777a810f4a9aff486355b71308bb654cdc868
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running Docker images
&lt;/h3&gt;

&lt;p&gt;The command is "docker run." Such a command has a lot of parameters, so I recommend that you  take a look at the command help for details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't worry about the high number of available parameters. Normally, the maintainers are accustomed to providing usage guides for its Docker images.&lt;/p&gt;

&lt;p&gt;In our sample, I'm starting a container based on the "postgres" Docker image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ $ &lt;/span&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; some-postgres &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysecretpassword &lt;span class="nt"&gt;-d&lt;/span&gt; postgres
Unable to find image &lt;span class="s1"&gt;'postgres:latest'&lt;/span&gt; locally
latest: Pulling from library/postgres
d121f8d1c412: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;9f045f1653de: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;fa0c0f0a5534: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;54e26c2eb3f1: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;cede939c738e: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;69f99b2ba105: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;218ae2bec541: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;70a48a74e7cf: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;c0159b3d9418: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;353f31fdef75: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;03d73272c393: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;8f89a54571bf: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;4885714928b5: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;3060b8f258ec: Pull &lt;span class="nb"&gt;complete 
&lt;/span&gt;Digest: sha256:0171a93d62342d2ab2461069609175674d2a1809a1ad7ce9ba141e2c09db1156
Status: Downloaded newer image &lt;span class="k"&gt;for &lt;/span&gt;postgres:latest
2cb420e36c116f72df282bc22920d04855b6e0ada9fe23b89d05747af3062829
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What does the "Pulling from..." output mean?
&lt;/h3&gt;

&lt;p&gt;It happens during the initial process when the Docker engine recognizes that it's missing the requested Docker image in the local machine. Once the requested Docker image is on the local machine, the next process will happen pretty quickly!&lt;/p&gt;

&lt;h2&gt;
  
  
  What containers are running?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
2cb420e36c11        postgres            &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   26 seconds ago      Up 9 seconds        5432/tcp            some-postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you want to see all containers that you have created on your local machine? Add the "-a" flag at the "docker ps" command.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'd like to stop my active containers. How can I do it?
&lt;/h2&gt;

&lt;p&gt;You need to use or the "ID"s or the "NAMES" of the active containers and perform the command below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: It's possible to stop many containers with one command only. You'll need just to provide the "ID"s or "NAMES" of the target containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker stop &amp;lt;CONTAINER ID&amp;gt; &amp;lt;CONTAINER NAME&amp;gt; &amp;lt;CONTAINER ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
757c0dd2d3dc        postgres            &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   8 seconds ago       Up 5 seconds        5432/tcp            some-postgres-other
b3f3199c2ef4        postgres            &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   25 seconds ago      Up 22 seconds       5432/tcp            some-postgres

&lt;span class="nv"&gt;$ &lt;/span&gt;docker stop 757c0dd2d3dc some-postgres
757c0dd2d3dc
some-postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  I want to delete my containers. How can I do it?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: It's possible to delete many containers with one command only. You'll just need to provide the "ID"s or "NAMES" of the target containers.&lt;/p&gt;

&lt;p&gt;One more thing: if it is what you need to do, don't forget to stop the containers that are running. Or you can use the "brutal force" mode by using the "-f" flag.&lt;/p&gt;

&lt;p&gt;Use the "ID"s or the "NAMES" of the containers that you want to delete, and perform the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;CONTAINER ID&amp;gt; &amp;lt;CONTAINER NAME&amp;gt; &amp;lt;CONTAINER ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
757c0dd2d3dc        postgres            &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   8 seconds ago       Up 5 seconds        5432/tcp            some-postgres-other
b3f3199c2ef4        postgres            &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   25 seconds ago      Up 22 seconds       5432/tcp            some-postgres

&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 757c0dd2d3dc some-postgres
757c0dd2d3dc
some-postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Great! The container is up and running. How can I access it?
&lt;/h2&gt;

&lt;p&gt;During the Docker installation, by default, it's installed with three networks: "bridge," "none," and "host." Also, by default, it uses the "bridge" network for communication between the container and the host.&lt;/p&gt;

&lt;p&gt;Docker lets you create a custom network, but it's beyond the scope of this article! Sorry. Lol.&lt;/p&gt;

&lt;h3&gt;
  
  
  Listing the configured networks at Docker:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network &lt;span class="nb"&gt;ls
&lt;/span&gt;NETWORK ID          NAME                DRIVER              SCOPE
93ec2c8226b5        bridge              bridge              &lt;span class="nb"&gt;local
&lt;/span&gt;a2cd7ddae279        host                host                &lt;span class="nb"&gt;local
&lt;/span&gt;518332f330ee        none                null                &lt;span class="nb"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Inspecting a network configuration:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network &amp;lt;NETWORK ID or NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: inspecting the "bridge" network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network inspect bridge
&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"bridge"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Id"&lt;/span&gt;: &lt;span class="s2"&gt;"93ec2c8226b57b9eb6080e9580d68247a7a109174b14a78041820aa27772a2d2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Created"&lt;/span&gt;: &lt;span class="s2"&gt;"2020-10-02T10:02:24.548224386-03:00"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Scope"&lt;/span&gt;: &lt;span class="s2"&gt;"local"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Driver"&lt;/span&gt;: &lt;span class="s2"&gt;"bridge"&lt;/span&gt;,
        &lt;span class="s2"&gt;"EnableIPv6"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"IPAM"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Driver"&lt;/span&gt;: &lt;span class="s2"&gt;"default"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Options"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"Config"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="s2"&gt;"Subnet"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.0/16"&lt;/span&gt;,
                    &lt;span class="s2"&gt;"Gateway"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.1"&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Internal"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"Attachable"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"Ingress"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"ConfigFrom"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Network"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"ConfigOnly"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"Containers"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"eec4785fe9d22b9abb1aa78f3dda6f36de3b988ec6b8f6ac08428481f1e64e61"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"some-postgres"&lt;/span&gt;,
                &lt;span class="s2"&gt;"EndpointID"&lt;/span&gt;: &lt;span class="s2"&gt;"d2d60a278eb15177ed2dbbb393b19b93a80ebb6a16693ba820221d252822d5e9"&lt;/span&gt;,
                &lt;span class="s2"&gt;"MacAddress"&lt;/span&gt;: &lt;span class="s2"&gt;"02:42:ac:11:00:02"&lt;/span&gt;,
                &lt;span class="s2"&gt;"IPv4Address"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.2/16"&lt;/span&gt;,
                &lt;span class="s2"&gt;"IPv6Address"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Options"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"com.docker.network.bridge.default_bridge"&lt;/span&gt;: &lt;span class="s2"&gt;"true"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.bridge.enable_icc"&lt;/span&gt;: &lt;span class="s2"&gt;"true"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.bridge.enable_ip_masquerade"&lt;/span&gt;: &lt;span class="s2"&gt;"true"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.bridge.host_binding_ipv4"&lt;/span&gt;: &lt;span class="s2"&gt;"0.0.0.0"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.bridge.name"&lt;/span&gt;: &lt;span class="s2"&gt;"docker0"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.driver.mtu"&lt;/span&gt;: &lt;span class="s2"&gt;"1500"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Labels"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Accessing an active container:
&lt;/h2&gt;

&lt;p&gt;Inspect the network configurations of the container that you want to access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker container inspect &amp;lt;CONTAINER ID or CONTAINER NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now, you will know the IP address and port of the container that you're trying to connect:&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker container inspect some-postgres
&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Id"&lt;/span&gt;: &lt;span class="s2"&gt;"eec4785fe9d22b9abb1aa78f3dda6f36de3b988ec6b8f6ac08428481f1e64e61"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Created"&lt;/span&gt;: &lt;span class="s2"&gt;"2020-10-06T06:32:28.041545362Z"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Path"&lt;/span&gt;: &lt;span class="s2"&gt;"docker-entrypoint.sh"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Args"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;"postgres"&lt;/span&gt;
        &lt;span class="o"&gt;]&lt;/span&gt;,
        &lt;span class="s2"&gt;"State"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Status"&lt;/span&gt;: &lt;span class="s2"&gt;"running"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Running"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
            &lt;span class="s2"&gt;"Paused"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"Restarting"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"OOMKilled"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"Dead"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"Pid"&lt;/span&gt;: 161922,
            &lt;span class="s2"&gt;"ExitCode"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"Error"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"StartedAt"&lt;/span&gt;: &lt;span class="s2"&gt;"2020-10-06T06:32:33.738235112Z"&lt;/span&gt;,
            &lt;span class="s2"&gt;"FinishedAt"&lt;/span&gt;: &lt;span class="s2"&gt;"0001-01-01T00:00:00Z"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Image"&lt;/span&gt;: &lt;span class="s2"&gt;"sha256:817f2d3d51eccb32a160cecca3b6bb95de017810498f1bb0a1d7627f59e3c5f9"&lt;/span&gt;,
        &lt;span class="s2"&gt;"ResolvConfPath"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/containers/eec4785fe9d22b9abb1aa78f3dda6f36de3b988ec6b8f6ac08428481f1e64e61/resolv.conf"&lt;/span&gt;,
        &lt;span class="s2"&gt;"HostnamePath"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/containers/eec4785fe9d22b9abb1aa78f3dda6f36de3b988ec6b8f6ac08428481f1e64e61/hostname"&lt;/span&gt;,
        &lt;span class="s2"&gt;"HostsPath"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/containers/eec4785fe9d22b9abb1aa78f3dda6f36de3b988ec6b8f6ac08428481f1e64e61/hosts"&lt;/span&gt;,
        &lt;span class="s2"&gt;"LogPath"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/containers/eec4785fe9d22b9abb1aa78f3dda6f36de3b988ec6b8f6ac08428481f1e64e61/eec4785fe9d22b9abb1aa78f3dda6f36de3b988ec6b8f6ac08428481f1e64e61-json.log"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"/some-postgres"&lt;/span&gt;,
        &lt;span class="s2"&gt;"RestartCount"&lt;/span&gt;: 0,
        &lt;span class="s2"&gt;"Driver"&lt;/span&gt;: &lt;span class="s2"&gt;"overlay2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Platform"&lt;/span&gt;: &lt;span class="s2"&gt;"linux"&lt;/span&gt;,
        &lt;span class="s2"&gt;"MountLabel"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
        &lt;span class="s2"&gt;"ProcessLabel"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
        &lt;span class="s2"&gt;"AppArmorProfile"&lt;/span&gt;: &lt;span class="s2"&gt;"docker-default"&lt;/span&gt;,
        &lt;span class="s2"&gt;"ExecIDs"&lt;/span&gt;: null,
        &lt;span class="s2"&gt;"HostConfig"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Binds"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"ContainerIDFile"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"LogConfig"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"Type"&lt;/span&gt;: &lt;span class="s2"&gt;"json-file"&lt;/span&gt;,
                &lt;span class="s2"&gt;"Config"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;,
            &lt;span class="s2"&gt;"NetworkMode"&lt;/span&gt;: &lt;span class="s2"&gt;"default"&lt;/span&gt;,
            &lt;span class="s2"&gt;"PortBindings"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
            &lt;span class="s2"&gt;"RestartPolicy"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"no"&lt;/span&gt;,
                &lt;span class="s2"&gt;"MaximumRetryCount"&lt;/span&gt;: 0
            &lt;span class="o"&gt;}&lt;/span&gt;,
            &lt;span class="s2"&gt;"AutoRemove"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"VolumeDriver"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"VolumesFrom"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"CapAdd"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"CapDrop"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"Capabilities"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"Dns"&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
            &lt;span class="s2"&gt;"DnsOptions"&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
            &lt;span class="s2"&gt;"DnsSearch"&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
            &lt;span class="s2"&gt;"ExtraHosts"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"GroupAdd"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"IpcMode"&lt;/span&gt;: &lt;span class="s2"&gt;"private"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Cgroup"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"Links"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"OomScoreAdj"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"PidMode"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"Privileged"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"PublishAllPorts"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"ReadonlyRootfs"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"SecurityOpt"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"UTSMode"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"UsernsMode"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"ShmSize"&lt;/span&gt;: 67108864,
            &lt;span class="s2"&gt;"Runtime"&lt;/span&gt;: &lt;span class="s2"&gt;"runc"&lt;/span&gt;,
            &lt;span class="s2"&gt;"ConsoleSize"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                0,
                0
            &lt;span class="o"&gt;]&lt;/span&gt;,
            &lt;span class="s2"&gt;"Isolation"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"CpuShares"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"Memory"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"NanoCpus"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"CgroupParent"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"BlkioWeight"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"BlkioWeightDevice"&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
            &lt;span class="s2"&gt;"BlkioDeviceReadBps"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"BlkioDeviceWriteBps"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"BlkioDeviceReadIOps"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"BlkioDeviceWriteIOps"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"CpuPeriod"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"CpuQuota"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"CpuRealtimePeriod"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"CpuRealtimeRuntime"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"CpusetCpus"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"CpusetMems"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"Devices"&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
            &lt;span class="s2"&gt;"DeviceCgroupRules"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"DeviceRequests"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"KernelMemory"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"KernelMemoryTCP"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"MemoryReservation"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"MemorySwap"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"MemorySwappiness"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"OomKillDisable"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"PidsLimit"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"Ulimits"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"CpuCount"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"CpuPercent"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"IOMaximumIOps"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"IOMaximumBandwidth"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"MaskedPaths"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"/proc/asound"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/acpi"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/kcore"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/keys"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/latency_stats"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/timer_list"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/timer_stats"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/sched_debug"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/scsi"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/sys/firmware"&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;,
            &lt;span class="s2"&gt;"ReadonlyPaths"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"/proc/bus"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/fs"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/irq"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/sys"&lt;/span&gt;,
                &lt;span class="s2"&gt;"/proc/sysrq-trigger"&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"GraphDriver"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Data"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"LowerDir"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/overlay2/5f06b2f1ac9aff28d4227a9b0d5472e1add96c5bedd1bf25fd449f687d759da5-init/diff:/var/lib/docker/overlay2/7a7a896bb660e0d85fc80ab24e4d794cbf2af41f519cb607a708973c298e2da5/diff:/var/lib/docker/overlay2/e42f3b8dc605a19bcd411d1cb3f71cd2e4f52de86f5864bb07813a7a4f8cf2d9/diff:/var/lib/docker/overlay2/c1116b15cef241d04b9374b62726a829638298e1300000c4fce8066bd4a16c33/diff:/var/lib/docker/overlay2/c0dc7953db526a9d9588bbb9e01234864a7d7b74569e2bd196bb415ce83a4652/diff:/var/lib/docker/overlay2/34aa317f049518d3cf909ba2713379ed2ea734a0a11c3a8a175457b78b723dad/diff:/var/lib/docker/overlay2/f4da5c06e47acb75946e2e78d9cff87285b10a35b0387097795a35eac873bafd/diff:/var/lib/docker/overlay2/4f6667cd7c9a083f0ce8889af4c9a3d02b81dfa86fc2bb367b4ba37bf6dc8dc3/diff:/var/lib/docker/overlay2/e3072ad80c0aba2e0f7314a2363c5acb838832a5c65fcc2c34c84e0d92705d39/diff:/var/lib/docker/overlay2/b9206a652ec537817c9e8f443cc42df902ed40f88656526b3dfc47c3fbab2ae1/diff:/var/lib/docker/overlay2/257013dddd1be7e7b400158d86b4ef28bbe7fa052e119df7f0ecf26210c872fa/diff:/var/lib/docker/overlay2/0fcdb3f15729db9f0a07f0789f61d6723e26073516ff98e6c27eec81ed4477c1/diff:/var/lib/docker/overlay2/edc83f533c47bd2985fdcd298e56c394f9055494d357ade0f751c3f1b2ac2a7f/diff:/var/lib/docker/overlay2/2ec83a49325b92d51ff07ac5ccf7dd80ef2d5484eb580dcd4e7f6d5c44cf0619/diff:/var/lib/docker/overlay2/3354771de57d6715ddaf7a05dde8f3bd32a49f89f28be06dd2a05a65e43d9960/diff"&lt;/span&gt;,
                &lt;span class="s2"&gt;"MergedDir"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/overlay2/5f06b2f1ac9aff28d4227a9b0d5472e1add96c5bedd1bf25fd449f687d759da5/merged"&lt;/span&gt;,
                &lt;span class="s2"&gt;"UpperDir"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/overlay2/5f06b2f1ac9aff28d4227a9b0d5472e1add96c5bedd1bf25fd449f687d759da5/diff"&lt;/span&gt;,
                &lt;span class="s2"&gt;"WorkDir"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/overlay2/5f06b2f1ac9aff28d4227a9b0d5472e1add96c5bedd1bf25fd449f687d759da5/work"&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;,
            &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"overlay2"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Mounts"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
            &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"Type"&lt;/span&gt;: &lt;span class="s2"&gt;"volume"&lt;/span&gt;,
                &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"d062384bcf57694686350a4e140e784abed87b46d5daa6025ac524a3f2d216e0"&lt;/span&gt;,
                &lt;span class="s2"&gt;"Source"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/volumes/d062384bcf57694686350a4e140e784abed87b46d5daa6025ac524a3f2d216e0/_data"&lt;/span&gt;,
                &lt;span class="s2"&gt;"Destination"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/postgresql/data"&lt;/span&gt;,
                &lt;span class="s2"&gt;"Driver"&lt;/span&gt;: &lt;span class="s2"&gt;"local"&lt;/span&gt;,
                &lt;span class="s2"&gt;"Mode"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
                &lt;span class="s2"&gt;"RW"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
                &lt;span class="s2"&gt;"Propagation"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;]&lt;/span&gt;,
        &lt;span class="s2"&gt;"Config"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Hostname"&lt;/span&gt;: &lt;span class="s2"&gt;"eec4785fe9d2"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Domainname"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"User"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"AttachStdin"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"AttachStdout"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"AttachStderr"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"ExposedPorts"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"5432/tcp"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;,
            &lt;span class="s2"&gt;"Tty"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"OpenStdin"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"StdinOnce"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"Env"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"POSTGRES_PASSWORD=mysecretpassword"&lt;/span&gt;,
                &lt;span class="s2"&gt;"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/postgresql/13/bin"&lt;/span&gt;,
                &lt;span class="s2"&gt;"GOSU_VERSION=1.12"&lt;/span&gt;,
                &lt;span class="s2"&gt;"LANG=en_US.utf8"&lt;/span&gt;,
                &lt;span class="s2"&gt;"PG_MAJOR=13"&lt;/span&gt;,
                &lt;span class="s2"&gt;"PG_VERSION=13.0-1.pgdg100+1"&lt;/span&gt;,
                &lt;span class="s2"&gt;"PGDATA=/var/lib/postgresql/data"&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;,
            &lt;span class="s2"&gt;"Cmd"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"postgres"&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;,
            &lt;span class="s2"&gt;"Image"&lt;/span&gt;: &lt;span class="s2"&gt;"postgres"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Volumes"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"/var/lib/postgresql/data"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;,
            &lt;span class="s2"&gt;"WorkingDir"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"Entrypoint"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"docker-entrypoint.sh"&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;,
            &lt;span class="s2"&gt;"OnBuild"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"Labels"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
            &lt;span class="s2"&gt;"StopSignal"&lt;/span&gt;: &lt;span class="s2"&gt;"SIGINT"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"NetworkSettings"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Bridge"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"SandboxID"&lt;/span&gt;: &lt;span class="s2"&gt;"a1c7ed40f3afa66570a953d169831da9cc2a3fb3467036883f2b0ea4c4acbdae"&lt;/span&gt;,
            &lt;span class="s2"&gt;"HairpinMode"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
            &lt;span class="s2"&gt;"LinkLocalIPv6Address"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"LinkLocalIPv6PrefixLen"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"Ports"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"5432/tcp"&lt;/span&gt;: null
            &lt;span class="o"&gt;}&lt;/span&gt;,
            &lt;span class="s2"&gt;"SandboxKey"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/run/docker/netns/a1c7ed40f3af"&lt;/span&gt;,
            &lt;span class="s2"&gt;"SecondaryIPAddresses"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"SecondaryIPv6Addresses"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"EndpointID"&lt;/span&gt;: &lt;span class="s2"&gt;"d2d60a278eb15177ed2dbbb393b19b93a80ebb6a16693ba820221d252822d5e9"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Gateway"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.1"&lt;/span&gt;,
            &lt;span class="s2"&gt;"GlobalIPv6Address"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"GlobalIPv6PrefixLen"&lt;/span&gt;: 0,
            &lt;span class="s2"&gt;"IPAddress"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.2"&lt;/span&gt;,
            &lt;span class="s2"&gt;"IPPrefixLen"&lt;/span&gt;: 16,
            &lt;span class="s2"&gt;"IPv6Gateway"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
            &lt;span class="s2"&gt;"MacAddress"&lt;/span&gt;: &lt;span class="s2"&gt;"02:42:ac:11:00:02"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Networks"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"bridge"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="s2"&gt;"IPAMConfig"&lt;/span&gt;: null,
                    &lt;span class="s2"&gt;"Links"&lt;/span&gt;: null,
                    &lt;span class="s2"&gt;"Aliases"&lt;/span&gt;: null,
                    &lt;span class="s2"&gt;"NetworkID"&lt;/span&gt;: &lt;span class="s2"&gt;"93ec2c8226b57b9eb6080e9580d68247a7a109174b14a78041820aa27772a2d2"&lt;/span&gt;,
                    &lt;span class="s2"&gt;"EndpointID"&lt;/span&gt;: &lt;span class="s2"&gt;"d2d60a278eb15177ed2dbbb393b19b93a80ebb6a16693ba820221d252822d5e9"&lt;/span&gt;,
                    &lt;span class="s2"&gt;"Gateway"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.1"&lt;/span&gt;,
                    &lt;span class="s2"&gt;"IPAddress"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.2"&lt;/span&gt;,
                    &lt;span class="s2"&gt;"IPPrefixLen"&lt;/span&gt;: 16,
                    &lt;span class="s2"&gt;"IPv6Gateway"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
                    &lt;span class="s2"&gt;"GlobalIPv6Address"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
                    &lt;span class="s2"&gt;"GlobalIPv6PrefixLen"&lt;/span&gt;: 0,
                    &lt;span class="s2"&gt;"MacAddress"&lt;/span&gt;: &lt;span class="s2"&gt;"02:42:ac:11:00:02"&lt;/span&gt;,
                    &lt;span class="s2"&gt;"DriverOpts"&lt;/span&gt;: null
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case above, the IP is 172.17.0.2, and the exposed port is 5432 under the TCP protocol.&lt;/p&gt;

&lt;p&gt;With the required information, we can test to see if the container is accessible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;telnet 172.17.0.2 5432
Trying 172.17.0.2...
Connected to 172.17.0.2.
Escape character is &lt;span class="s1"&gt;'^]'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way to get the same information in order to obtain the exposed container’s port is by using the “docker ps” command...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
eec4785fe9d2        postgres            &lt;span class="s2"&gt;"docker-entrypoint.s…"&lt;/span&gt;   33 minutes ago      Up 33 minutes       5432/tcp            some-postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and with the “docker network inspect bridge” command, we get the container’s IP from the network that it’s connected to. In this case, the bridge network is the default network. Check it out below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker network inspect bridge
&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"bridge"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Id"&lt;/span&gt;: &lt;span class="s2"&gt;"93ec2c8226b57b9eb6080e9580d68247a7a109174b14a78041820aa27772a2d2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Created"&lt;/span&gt;: &lt;span class="s2"&gt;"2020-10-02T10:02:24.548224386-03:00"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Scope"&lt;/span&gt;: &lt;span class="s2"&gt;"local"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Driver"&lt;/span&gt;: &lt;span class="s2"&gt;"bridge"&lt;/span&gt;,
        &lt;span class="s2"&gt;"EnableIPv6"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"IPAM"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Driver"&lt;/span&gt;: &lt;span class="s2"&gt;"default"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Options"&lt;/span&gt;: null,
            &lt;span class="s2"&gt;"Config"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="s2"&gt;"Subnet"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.0/16"&lt;/span&gt;,
                    &lt;span class="s2"&gt;"Gateway"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.1"&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Internal"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"Attachable"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"Ingress"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"ConfigFrom"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Network"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"ConfigOnly"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
        &lt;span class="s2"&gt;"Containers"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"eec4785fe9d22b9abb1aa78f3dda6f36de3b988ec6b8f6ac08428481f1e64e61"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"some-postgres"&lt;/span&gt;,
                &lt;span class="s2"&gt;"EndpointID"&lt;/span&gt;: &lt;span class="s2"&gt;"d2d60a278eb15177ed2dbbb393b19b93a80ebb6a16693ba820221d252822d5e9"&lt;/span&gt;,
                &lt;span class="s2"&gt;"MacAddress"&lt;/span&gt;: &lt;span class="s2"&gt;"02:42:ac:11:00:02"&lt;/span&gt;,
                &lt;span class="s2"&gt;"IPv4Address"&lt;/span&gt;: &lt;span class="s2"&gt;"172.17.0.2/16"&lt;/span&gt;,
                &lt;span class="s2"&gt;"IPv6Address"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Options"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"com.docker.network.bridge.default_bridge"&lt;/span&gt;: &lt;span class="s2"&gt;"true"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.bridge.enable_icc"&lt;/span&gt;: &lt;span class="s2"&gt;"true"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.bridge.enable_ip_masquerade"&lt;/span&gt;: &lt;span class="s2"&gt;"true"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.bridge.host_binding_ipv4"&lt;/span&gt;: &lt;span class="s2"&gt;"0.0.0.0"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.bridge.name"&lt;/span&gt;: &lt;span class="s2"&gt;"docker0"&lt;/span&gt;,
            &lt;span class="s2"&gt;"com.docker.network.driver.mtu"&lt;/span&gt;: &lt;span class="s2"&gt;"1500"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Labels"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  I'd like to modify or install something at the container only. Is it possible?
&lt;/h2&gt;

&lt;p&gt;Yeah, it is! &lt;/p&gt;

&lt;p&gt;In my humble opinion, I think that the recommendation is to create your Docker image based on a "Dockerfile" that will be built with the "docker build" command, but sometimes, you just want to access a given container in order to customize it or be able to perform some commands there.&lt;/p&gt;

&lt;p&gt;I'm used to verifying if the container has BASH or SH installed. If the answer is, "Yes," then I'll perform the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; eec4785fe9d2 bash
root@eec4785fe9d2:/#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've tried many times to use the "docker attach" command, but I'm used to typing the "exit" command instead of pressing CTRL+P and CTRL+Q. At least, in this way, my container will keep running! 😜&lt;/p&gt;

&lt;h2&gt;
  
  
  Oh, no... is there an easier way to use Docker?
&lt;/h2&gt;

&lt;p&gt;It is for our happiness, YES!!!&lt;/p&gt;

&lt;p&gt;We've got an official tool called &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Also, we've got &lt;a href="https://docs.docker.com/engine/reference/commandline/stack_deploy/" rel="noopener noreferrer"&gt;Docker Swarm&lt;/a&gt; that is a native cluster tool for Docker:&lt;/p&gt;

&lt;p&gt;Both of them were created to help us manage multiple containers.&lt;/p&gt;

&lt;p&gt;One more point: both support configuration files based on &lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;the "Docker Compose file" specification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's create a YAML file that follows the Docker Compose specification to describe all containers that we want to be able to execute. As mentioned before, the same file can be used by both tools, but there are caveats: there are configuration features that are only supported by one tool instead of another one and vice-versa. Therefore, pay attention if you want to interoperate such a file.&lt;/p&gt;

&lt;p&gt;Here's my sample "docker-componse.yml" file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.1'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15432:5432"&lt;/span&gt;

  &lt;span class="na"&gt;adminer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;adminer&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8080:8080&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention to the &lt;strong&gt;"sevices:db:ports"&lt;/strong&gt; property: such property configures the ports that will be exposed. In my sample, it is defined that the 15432 port at the localhost will be redirected to the 5432 port of the &lt;strong&gt;"db"&lt;/strong&gt; container (our postgres server).&lt;/p&gt;

&lt;p&gt;The "services:adminer" property describes another container. It will be a client that will be used for us to access the Postgres server through the browser. &lt;/p&gt;

&lt;p&gt;One interesting property is the &lt;strong&gt;"services:adminer:depends_on."&lt;/strong&gt; It means that the &lt;strong&gt;"adminer"&lt;/strong&gt; container will be started if and only if the &lt;strong&gt;"db"&lt;/strong&gt; container is running.&lt;/p&gt;

&lt;p&gt;I'm accustomed to using the Docker Compose tool. Then we will go ahead and show you basic commands to use it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting the containers with Docker Compose:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PS&lt;/strong&gt;: the "-f " option is necessary if the YAML file name is different than "docker-compose.yml" or "docker-compose.yaml" and/or if such a file is on a different directory than the directory on which you are trying to perform the commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
Creating network &lt;span class="s2"&gt;"dearrudam_default"&lt;/span&gt; with the default driver
Creating dearrudam_db_1 ... &lt;span class="k"&gt;done
&lt;/span&gt;Creating dearrudam_adminer_1 ... &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A curious detail: the name of the current directory will be used as the prefix name of the containers and configurations described in the Docker Compose file.&lt;/p&gt;

&lt;p&gt;Take a look below. I'm accessing the "adminer" container through my browser: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhnxtiqc4kujne617v7ni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhnxtiqc4kujne617v7ni.png" alt="Alt Text" width="645" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Destroying containers with Docker Compose:
&lt;/h2&gt;

&lt;p&gt;The command below stops and destroys all containers described in the configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker-compose down
Stopping dearrudam_adminer_1 ... &lt;span class="k"&gt;done
&lt;/span&gt;Stopping dearrudam_db_1      ... &lt;span class="k"&gt;done
&lt;/span&gt;Removing dearrudam_adminer_1 ... &lt;span class="k"&gt;done
&lt;/span&gt;Removing dearrudam_db_1      ... &lt;span class="k"&gt;done
&lt;/span&gt;Removing network dearrudam_default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  One more important point!
&lt;/h2&gt;

&lt;p&gt;If you want to keep the data of the container after the container stops, take a look at the "docker volume" commands, okay?&lt;/p&gt;

&lt;h1&gt;
  
  
  Summarizing...
&lt;/h1&gt;

&lt;p&gt;I am very thankful for the opportunity to create this article, and I'd like to thank you, the reader, for coming this far! I am sorry for any misunderstandings!&lt;/p&gt;

&lt;p&gt;Also, I'd like to thank my English teacher James Zarrello for helping me with this article translation. Thank you, James!&lt;/p&gt;

&lt;p&gt;I'd like to pay attention to these commands because I'm using them every day, and I will be happy if you can provide me with any other good usage suggestions!&lt;/p&gt;

&lt;p&gt;Indeed, Docker goes beyond the simple usage that I've described in this article. Docker has consolidated a standardization of the distribution of containerized solutions and solves many deployment issues like the famous one "in my machine works" and others in the cloud world. &lt;/p&gt;

&lt;p&gt;Learning Docker in a thorough way is very worthwhile. There are many interesting points that this article didn't show for sure!&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article! Looking forward to the feedback!&lt;/p&gt;

&lt;p&gt;See you later!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
