<?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: Java Efetivo (livro)</title>
    <description>The latest articles on DEV Community by Java Efetivo (livro) (@javaefetivo).</description>
    <link>https://dev.to/javaefetivo</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%2F1177998%2Fc71ffde4-62ae-4b6d-aa08-0cba551966e0.jpg</url>
      <title>DEV Community: Java Efetivo (livro)</title>
      <link>https://dev.to/javaefetivo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/javaefetivo"/>
    <language>en</language>
    <item>
      <title>Despedida e Links</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 13 Feb 2025 14:55:58 +0000</pubDate>
      <link>https://dev.to/javaefetivo/despedida-e-links-2jl5</link>
      <guid>https://dev.to/javaefetivo/despedida-e-links-2jl5</guid>
      <description>&lt;p&gt;Agradecemos imensamente a todes que estiveram conosco nessa jornada de estudos.&lt;/p&gt;

&lt;p&gt;Link da Playlist em Videos do Grupo de Estudos Java Efetivo:&lt;br&gt;
&lt;a href="https://youtube.com/playlist?list=PLAa4y8yJfr91RNSgHWliOsZkAU1_hNxim&amp;amp;si=gyQlX6EH5GTMv4xH" rel="noopener noreferrer"&gt;https://youtube.com/playlist?list=PLAa4y8yJfr91RNSgHWliOsZkAU1_hNxim&amp;amp;si=gyQlX6EH5GTMv4xH&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outros Links:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;YouTube da Comunidade:&lt;br&gt;
&lt;a href="https://www.youtube.com/@javagirlsjug" rel="noopener noreferrer"&gt;https://www.youtube.com/@javagirlsjug&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Playlists:&lt;br&gt;
Java para Iniciantes 1:&lt;br&gt;
&lt;a href="https://youtube.com/playlist?list=PLAa4y8yJfr92nHJAXS5Y2n-m7Nu5yHA5T&amp;amp;si=NCoC58Lc-q-HUJeG" rel="noopener noreferrer"&gt;https://youtube.com/playlist?list=PLAa4y8yJfr92nHJAXS5Y2n-m7Nu5yHA5T&amp;amp;si=NCoC58Lc-q-HUJeG&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Java para Iniciantes 2:&lt;br&gt;
&lt;a href="https://youtube.com/playlist?list=PLAa4y8yJfr91CNAKBNfV0HMBETn2oWbmD&amp;amp;si=I4s8xMWZgr9nhdbX" rel="noopener noreferrer"&gt;https://youtube.com/playlist?list=PLAa4y8yJfr91CNAKBNfV0HMBETn2oWbmD&amp;amp;si=I4s8xMWZgr9nhdbX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Links dos Resuminhos em Blogs no Dev.to:&lt;br&gt;
&lt;a href="https://dev.to/javaparainiciantes"&gt;https://dev.to/javaparainiciantes&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/javaefetivo"&gt;https://dev.to/javaefetivo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/psanrosa13"&gt;https://dev.to/psanrosa13&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Site da comunidade:&lt;br&gt;
&lt;a href="https://javagirlsjug.org" rel="noopener noreferrer"&gt;https://javagirlsjug.org&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
    </item>
    <item>
      <title>Serialização em Java na atualidade e novas abordagens em 2025</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 13 Feb 2025 14:45:48 +0000</pubDate>
      <link>https://dev.to/javaefetivo/serializacao-em-java-na-atualidade-e-novas-abordagens-1jff</link>
      <guid>https://dev.to/javaefetivo/serializacao-em-java-na-atualidade-e-novas-abordagens-1jff</guid>
      <description>&lt;p&gt;O padrão de proxy de serialização (recomendada pelo livro) ainda é uma solução válida e segura no Java, especialmente para classes com invariantes complexas ou que exigem imutabilidade real. No entanto, com as evoluções da linguagem e das práticas de desenvolvimento, há abordagens mais modernas e recomendadas para muitos cenários.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abordagens mais modernas para segurança na serialização e desserialização&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1- Evitar completamente a serialização nativa do Java (Serializable)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O próprio criador do Java (&lt;strong&gt;Joshua Bloch&lt;/strong&gt;) recomenda evitar Serializable devido aos riscos de segurança e complexidade.&lt;/li&gt;
&lt;li&gt;Em vez disso, é melhor utilizar formatos de serialização mais seguros, como JSON, XML ou Protobuf, que oferecem mais controle sobre o que está sendo serializado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Alternativas:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usar &lt;strong&gt;Jackson&lt;/strong&gt; (com.fasterxml.jackson.databind) para JSON.&lt;/li&gt;
&lt;li&gt;Utilizar &lt;strong&gt;Protocol Buffers (protobuf)&lt;/strong&gt; / Apache Avro para uma serialização mais eficiente e segura.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Links:&lt;br&gt;
&lt;a href="https://www.linkedin.com/pulse/o-linkedin-substituiu-json-por-protobuf-e-conseguiu-uma-deschamps-s2jkf/" rel="noopener noreferrer"&gt;https://www.linkedin.com/pulse/o-linkedin-substituiu-json-por-protobuf-e-conseguiu-uma-deschamps-s2jkf/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2- Uso de classes imutáveis e transient&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Objetos imutáveis são naturalmente mais seguros para serialização.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Usar Classes Imutáveis Modernas&lt;/strong&gt;&lt;br&gt;
Substitua tipos mutáveis (ex.: Date, ArrayList) por classes imutáveis do java.time (&lt;strong&gt;LocalDate&lt;/strong&gt;, Instant) ou coleções imutáveis (List.of(), Set.copyOf()).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Records (Java 16+)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public record Period(LocalDate start, LocalDate end) { 
    // Validação no construtor compacto
    public Period {
        if (end.isBefore(start)) throw new IllegalArgumentException();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simplifica a criação de classes imutáveis e elimina a necessidade de cópias defensivas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Marcar campos sensíveis como &lt;strong&gt;transient&lt;/strong&gt; impede que sejam serializados.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public final class SecureData implements Serializable {
    private static final long serialVersionUID = 1L;

    private final String publicData;
    private transient String sensitiveData; // Não será serializado

    public SecureData(String publicData, String sensitiveData) {
        this.publicData = publicData;
        this.sensitiveData = sensitiveData;
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3- ObjectInputFilter (Desde Java 9)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 9 introduziu o &lt;strong&gt;ObjectInputFilter&lt;/strong&gt;, que permite definir filtros de segurança para impedir ataques de desserialização de objetos inesperados ou perigosos.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
    "com.meusistema.SeguraClass;!*"
);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
ois.setObjectInputFilter(filter);

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

&lt;/div&gt;



&lt;p&gt;Benefício: Permite controlar quais classes podem ser desserializadas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4- Biblioteca Kryo (Mais segura e rápida)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kryo&lt;/strong&gt; é uma alternativa moderna e eficiente para serialização, sendo mais rápida e mais segura que a serialização padrão do Java.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kryo kryo = new Kryo();
Output output = new Output(new FileOutputStream("data.bin"));
kryo.writeObject(output, myObject);
output.close();

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

&lt;/div&gt;



&lt;p&gt;Leitura:&lt;br&gt;
&lt;a href="https://medium.com/@prekshaan95/kryo-serialization-and-deserialization-in-java-9e6da25e2a76" rel="noopener noreferrer"&gt;https://medium.com/@prekshaan95/kryo-serialization-and-deserialization-in-java-9e6da25e2a76&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Benefício: Melhor desempenho e segurança, usado em frameworks como Akka.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5- Serialização Customizada com writeObject() e readObject()&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
    throw new InvalidObjectException("Desserialização não permitida!");
}

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

&lt;/div&gt;



&lt;p&gt;Benefício: Bloqueia ataques de desserialização.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6- Serialização com Frameworks Seguros&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Spring Boot / Micronaut / Quarkus:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frameworks modernos evitam a serialização nativa do Java, preferindo JSON via REST APIs.&lt;/li&gt;
&lt;li&gt;Usam DTOs (Data Transfer Objects) imutáveis para transferência segura de dados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7- Padrão de Serialização Baseada em Construtores&lt;/strong&gt;&lt;br&gt;
Em vez de depender de proxies, use &lt;strong&gt;construtores ou factories&lt;/strong&gt; para reconstruir objetos após a desserialização:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Period implements Serializable {
    private final LocalDate start;
    private final LocalDate end;

    // Construtor público com validação
    public Period(LocalDate start, LocalDate end) {
        if (end.isBefore(start)) throw new IllegalArgumentException();
        this.start = start;
        this.end = end;
    }

    private Object readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        return new Period(start, end); // Reconstrução segura
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quando o Proxy de Serialização Ainda é Útil?&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cenários críticos&lt;/strong&gt;: Sistemas financeiros, APIs de segurança, onde a validação rigorosa é essencial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legado&lt;/strong&gt;: Projetos que não podem migrar para formatos modernos (ex.: sistemas embarcados, aplicações empresariais antigas).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comparativo: Proxy vs. Alternativas Modernas&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%2Ffmx2pjrg03k9u7jdh04r.jpg" 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%2Ffmx2pjrg03k9u7jdh04r.jpg" alt="Image description" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusão: Qual abordagem usar?&lt;/strong&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%2Fhst7x3feb5yep425e1bw.jpg" 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%2Fhst7x3feb5yep425e1bw.jpg" alt="Image description" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se a segurança for crítica, evite Serializable e use JSON ou Protobuf. Se ainda precisar usar Serializable, aplique ObjectInputFilter e classes imutáveis. &lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
    </item>
    <item>
      <title>Item 90: Pense em usar proxies de serialização em vez de instâncias serializadas</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Wed, 12 Feb 2025 23:42:34 +0000</pubDate>
      <link>https://dev.to/javaefetivo/item-90-pense-em-usar-proxies-de-serializacao-em-vez-de-instancias-serializadas-lmo</link>
      <guid>https://dev.to/javaefetivo/item-90-pense-em-usar-proxies-de-serializacao-em-vez-de-instancias-serializadas-lmo</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resumo do Item 90: Use Proxies de Serialização em vez de Instâncias Serializadas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problemas da Serialização Direta&lt;/strong&gt;&lt;br&gt;
Riscos de segurança e bugs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permite criar objetos sem passar por construtores normais.&lt;/li&gt;
&lt;li&gt;Violação de invariantes: Desserialização pode gerar instâncias inválidas.&lt;/li&gt;
&lt;li&gt;Ataques maliciosos: Streams de bytes manipuladas podem explorar vulnerabilidades.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;O que é o Padrão de Proxy de Serialização?&lt;/strong&gt;&lt;br&gt;
Objetivo: Substituir a serialização nativa por uma abordagem segura e controlada.&lt;/p&gt;

&lt;p&gt;Funcionamento:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cria uma classe proxy aninhada (serializável) que encapsula o estado da classe principal.&lt;/li&gt;
&lt;li&gt;Garante que apenas o proxy é serializado/desserializado, não a classe original.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implementação do Proxy de Serialização&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Criar a classe proxy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classe estática privada, serializável, com campos idênticos à classe principal.&lt;/li&gt;
&lt;li&gt;Construtor recebe a instância original e copia seus dados.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private static class SerializationProxy implements Serializable {
    private final Date start;
    private final Date end;

    SerializationProxy(Period p) {
        this.start = p.start;
        this.end = p.end;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Método writeReplace na classe principal:&lt;/strong&gt;&lt;br&gt;
Substitui a instância original pelo proxy durante a serialização.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private Object writeReplace() {
    return new SerializationProxy(this);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bloquear desserialização direta:&lt;/strong&gt;&lt;br&gt;
Adicionar readObject que lança exceção para evitar bypass do proxy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private void readObject(ObjectInputStream ois) throws InvalidObjectException {
    throw new InvalidObjectException("Use o proxy!");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Método readResolve no proxy:&lt;/strong&gt;&lt;br&gt;
Converte o proxy de volta em uma instância válida da classe principal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private Object readResolve() {
    return new Period(start, end); // Usa o construtor público
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vantagens do Padrão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Segurança reforçada:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elimina riscos de streams maliciosas e exposição de campos privados.&lt;/li&gt;
&lt;li&gt;Preserva imutabilidade: Campos final são mantidos sem restrições.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Flexibilidade:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permite alterar a implementação interna da classe sem quebrar compatibilidade (ex.: EnumSet).&lt;/li&gt;
&lt;li&gt;Simplicidade: Mais fácil de validar do que cópias defensivas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitações&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classes extensíveis: Não funciona bem se a classe pode ser herdada por usuários (viola encapsulamento).&lt;/li&gt;
&lt;li&gt;Grafos circulares: Pode causar ClassCastException em objetos com referências cíclicas.&lt;/li&gt;
&lt;li&gt;Desempenho: ~14% mais lento que serialização padrão (trade-off aceitável para segurança).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use proxies de serialização sempre que:&lt;/li&gt;
&lt;li&gt;A classe tem invariantes complexas.&lt;/li&gt;
&lt;li&gt;A segurança é crítica (ex.: dados sensíveis).&lt;/li&gt;
&lt;li&gt;Quer evitar códigos de validação/cópia defensiva manuais.&lt;/li&gt;
&lt;li&gt;Priorize este padrão sobre readObject/writeObject customizados para garantir robustez e imutabilidade real.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Chave: O proxy assegura que a desserialização sempre passa pelo construtor público, validando invariantes e bloqueando ataques!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Exemplos do Livro:&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%2Fzbr4hl3dtfxbv08cp8nf.jpg" 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%2Fzbr4hl3dtfxbv08cp8nf.jpg" alt="Image description" width="800" height="307"&gt;&lt;/a&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%2F5vncce4m0osq2qd0j09a.jpg" 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%2F5vncce4m0osq2qd0j09a.jpg" alt="Image description" width="800" height="139"&gt;&lt;/a&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%2Fefkcfb9ikzd0dzevll3d.jpg" 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%2Fefkcfb9ikzd0dzevll3d.jpg" alt="Image description" width="800" height="198"&gt;&lt;/a&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%2Frsz14dgrm3c2yfoz7i6g.jpg" 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%2Frsz14dgrm3c2yfoz7i6g.jpg" alt="Image description" width="800" height="133"&gt;&lt;/a&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%2F5dyhcn3peeytf3g758br.jpg" 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%2F5dyhcn3peeytf3g758br.jpg" alt="Image description" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Resumo - Item 89: Dê preferência aos tipos enum em vez do readResolve para controle de instância</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Wed, 12 Feb 2025 23:30:29 +0000</pubDate>
      <link>https://dev.to/javaefetivo/resumo-item-89-de-preferencia-aos-tipos-enum-em-vez-do-readresolve-para-controle-de-instancia-g3g</link>
      <guid>https://dev.to/javaefetivo/resumo-item-89-de-preferencia-aos-tipos-enum-em-vez-do-readresolve-para-controle-de-instancia-g3g</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problema do Singleton e Serialização&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Um singleton pode perder sua unicidade se for declarado como Serializable.&lt;/li&gt;
&lt;li&gt;A serialização cria uma nova instância ao desserializar, quebrando a restrição do singleton.&lt;/li&gt;
&lt;li&gt;O método readResolve pode ser usado para substituir a instância desserializada pela instância original.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Vulnerabilidade do readResolve&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se um singleton tiver campos não transientes, um invasor pode capturar uma referência à instância antes da execução do readResolve.&lt;/li&gt;
&lt;li&gt;Isso permite criar múltiplas instâncias do singleton, contornando a restrição de instância única.&lt;/li&gt;
&lt;li&gt;O ataque pode ser feito utilizando uma classe "ladra" que explora a desserialização circular para obter uma cópia do singleton antes que ele seja resolvido.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solução mais segura: Usar enum para Singletons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enums são implicitamente serializáveis e garantem que só existe uma única instância.&lt;/li&gt;
&lt;li&gt;O Java impede a criação de novas instâncias além das constantes declaradas no enum.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemplo seguro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public enum Elvis {
    INSTANCE;
    public void sing() { System.out.println("Love me tender"); }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quando ainda usar readResolve?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se a classe não pode ser um enum e precisa ser controlada por instância.&lt;/li&gt;
&lt;li&gt;Deve garantir que todos os campos de referência sejam transientes.&lt;/li&gt;
&lt;li&gt;O readResolve deve ter a acessibilidade adequada (privado em classes final).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prefira enum para singletons, pois é seguro e simples.&lt;/li&gt;
&lt;li&gt;Se precisar usar readResolve, tome precauções para evitar ataques.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Exemplos de códigos do livro:&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%2F88qcwf1celf8o7pyj4im.jpg" 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%2F88qcwf1celf8o7pyj4im.jpg" alt="Image description" width="800" height="198"&gt;&lt;/a&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%2F9bvd4szoi45gwbtz9pxc.jpg" 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%2F9bvd4szoi45gwbtz9pxc.jpg" alt="Image description" width="800" height="148"&gt;&lt;/a&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%2Fxnfcaagn3i3vwrvf1y1r.jpg" 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%2Fxnfcaagn3i3vwrvf1y1r.jpg" alt="Image description" width="800" height="288"&gt;&lt;/a&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%2F7jpfp6ya9fsuan0x8nvv.jpg" 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%2F7jpfp6ya9fsuan0x8nvv.jpg" alt="Image description" width="800" height="278"&gt;&lt;/a&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%2Fj9jgrvkpm7te9eu5w6r8.jpg" 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%2Fj9jgrvkpm7te9eu5w6r8.jpg" alt="Image description" width="800" height="548"&gt;&lt;/a&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%2Fvfengjqfd6olnuhxxptd.jpg" 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%2Fvfengjqfd6olnuhxxptd.jpg" alt="Image description" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Resumo do Item 88: Escreva métodos readObject defensivamente</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Wed, 12 Feb 2025 23:12:58 +0000</pubDate>
      <link>https://dev.to/javaefetivo/resumo-do-item-88-escreva-metodos-readobject-defensivamente-4mgf</link>
      <guid>https://dev.to/javaefetivo/resumo-do-item-88-escreva-metodos-readobject-defensivamente-4mgf</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problema da Desserialização sem Defesa&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uma classe pode ser tornada serializável apenas adicionando implements Serializable, mas isso pode comprometer suas invariantes.&lt;/li&gt;
&lt;li&gt;O método readObject age como um construtor público invisível, e precisa das mesmas precauções que um construtor tradicional.&lt;/li&gt;
&lt;li&gt;Se não for protegido, um invasor pode criar streams de bytes manipuladas para violar as invariantes da classe.&lt;/li&gt;
&lt;li&gt;Exemplo: uma classe Period pode ser manipulada para ter uma data final anterior à inicial.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ataque por Referência Mutável&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Um invasor pode fabricar uma stream de bytes que referencie os objetos mutáveis internos da classe.&lt;/li&gt;
&lt;li&gt;Ao modificar esses objetos (ex: Date), o estado da instância serializada pode ser alterado.&lt;/li&gt;
&lt;li&gt;Esse tipo de falha compromete a imutabilidade da classe, permitindo modificações após a criação.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Soluções para um readObject Seguro&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Cópia defensiva de objetos mutáveis&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sempre copie objetos mutáveis privados ao desserializar (Date, ArrayList, etc.).&lt;/li&gt;
&lt;li&gt;Exemplo: em vez de confiar em clone(), crie novas instâncias manualmente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verificação de invariantes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Após a cópia, verifique se os valores mantêm as regras da classe.&lt;/li&gt;
&lt;li&gt;Se alguma regra for violada, lance uma InvalidObjectException.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Evitar métodos sobrescrevíveis&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Durante a desserialização, não chame métodos que possam ser sobrescritos por subclasses.&lt;/li&gt;
&lt;li&gt;Isso evita execução de código antes que a classe tenha sido completamente carregada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Alternativa: Padrão de Proxy de Serialização&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sempre que possível, utilize serialização via proxy (Item 90).&lt;/li&gt;
&lt;li&gt;Esse padrão reduz a complexidade e minimiza riscos de falha na desserialização.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;br&gt;
Trate readObject como um construtor público: valide e proteja os dados.&lt;br&gt;
Desconfie da stream de bytes: ela pode ter sido manipulada por um invasor.&lt;br&gt;
Sempre copie defensivamente objetos mutáveis para garantir a integridade da classe.&lt;/p&gt;




&lt;p&gt;Exemplos de código do livro:&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%2Fc2qibyurp8lvlofp5q2p.jpg" 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%2Fc2qibyurp8lvlofp5q2p.jpg" alt="Image description" width="800" height="428"&gt;&lt;/a&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%2F8ojbas5peqcon1kzwje8.jpg" 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%2F8ojbas5peqcon1kzwje8.jpg" alt="Image description" width="800" height="667"&gt;&lt;/a&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%2Fbjx97yk09aci133ri77t.jpg" 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%2Fbjx97yk09aci133ri77t.jpg" alt="Image description" width="800" height="231"&gt;&lt;/a&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%2Frtd1hzfeupbhrjdhebkj.jpg" 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%2Frtd1hzfeupbhrjdhebkj.jpg" alt="Image description" width="800" height="714"&gt;&lt;/a&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%2Fokh4tvw6usnwsg26j8ld.jpg" 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%2Fokh4tvw6usnwsg26j8ld.jpg" alt="Image description" width="800" height="319"&gt;&lt;/a&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%2Fyl1gnegrc7uql5lxrhr8.jpg" 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%2Fyl1gnegrc7uql5lxrhr8.jpg" alt="Image description" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Item 87: Pense na possibilidade de usar uma forma serializada customizada</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 06 Feb 2025 19:50:50 +0000</pubDate>
      <link>https://dev.to/javaefetivo/item-87-pense-na-possibilidade-de-usar-uma-forma-serializada-customizada-ggf</link>
      <guid>https://dev.to/javaefetivo/item-87-pense-na-possibilidade-de-usar-uma-forma-serializada-customizada-ggf</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Problema da forma serializada padrão&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A forma serializada padrão pode tornar impossível substituir uma implementação descartável.&lt;/li&gt;
&lt;li&gt;Muitas classes da biblioteca Java, como BigInteger, sofreram com essa limitação.&lt;/li&gt;
&lt;li&gt;Deve-se avaliar se a forma serializada padrão é apropriada em termos de flexibilidade, desempenho e correção.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Quando a forma serializada padrão é aceitável?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quando a representação física do objeto é idêntica ao seu conteúdo lógico.&lt;/li&gt;
&lt;li&gt;Exemplo: uma classe Name com três String (sobrenome, primeiro nome e nome do meio).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Problemas ao usar a forma serializada padrão quando a representação física difere do conteúdo lógico&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Acopla a API pública à implementação interna, impedindo mudanças futuras.&lt;/li&gt;
&lt;li&gt;Aumenta o consumo de espaço, armazenando detalhes desnecessários.&lt;/li&gt;
&lt;li&gt;Pode ser ineficiente em tempo de execução, devido a percursos desnecessários no grafo do objeto.&lt;/li&gt;
&lt;li&gt;Pode causar overflow de pilha, especialmente em listas encadeadas grandes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Exemplo: Serialização de uma lista encadeada (StringList)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A forma serializada padrão armazenaria todos os nós e links internos, o que é ineficiente.&lt;/li&gt;
&lt;li&gt;Solução: armazenar apenas o número de elementos e suas String associadas.&lt;/li&gt;
&lt;li&gt;Isso reduz o espaço ocupado e melhora a performance da serialização.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Implementação de uma forma serializada customizada&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Criar os métodos &lt;strong&gt;writeObject&lt;/strong&gt; e &lt;strong&gt;readObject&lt;/strong&gt; para controlar a serialização.&lt;/li&gt;
&lt;li&gt;Utilizar o modificador transient para evitar serializar detalhes desnecessários.&lt;/li&gt;
&lt;li&gt;Sempre chamar defaultWriteObject e defaultReadObject para garantir compatibilidade futura.&lt;/li&gt;
&lt;li&gt;Documentar a API serializada com @serial (campos) e @serialData (métodos).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Problema ainda maior com tabelas hash&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A posição dos elementos depende do código hash da chave, que pode mudar entre execuções.&lt;/li&gt;
&lt;li&gt;Serializar a estrutura física de uma tabela hash poderia corromper suas invariantes.&lt;/li&gt;
&lt;li&gt;Solução: armazenar apenas os pares chave-valor e recriar a estrutura na desserialização.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Regras gerais para serialização eficiente&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declarar como transient qualquer campo que não faça parte do estado lógico do objeto.&lt;/li&gt;
&lt;li&gt;Evitar serializar campos derivados, cujo valor pode ser recalculado.&lt;/li&gt;
&lt;li&gt;Evitar serializar ponteiros para estruturas nativas da JVM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A forma serializada padrão deve ser aceita apenas se for adequada ao estado lógico do objeto.&lt;/li&gt;
&lt;li&gt;Para maior controle, use uma forma serializada customizada, garantindo eficiência e flexibilidade.&lt;/li&gt;
&lt;li&gt;Isso evita problemas futuros com manutenção, desempenho e compatibilidade da API serializada.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Exemplos do livro:&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%2Fqaybw7eafrhnwp7fmz9r.jpg" 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%2Fqaybw7eafrhnwp7fmz9r.jpg" alt="Image description" width="595" height="471"&gt;&lt;/a&gt;&lt;br&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%2Fg39zv3h2vughiay5j6fe.jpg" 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%2Fg39zv3h2vughiay5j6fe.jpg" alt="Image description" width="741" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&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%2Fzlqg0zaxq2q4yvcv5slk.jpg" 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%2Fzlqg0zaxq2q4yvcv5slk.jpg" alt="Image description" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Exercícios Práticos de Serialização</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 30 Jan 2025 17:42:12 +0000</pubDate>
      <link>https://dev.to/javaefetivo/exercicios-praticos-de-serializacao-1gen</link>
      <guid>https://dev.to/javaefetivo/exercicios-praticos-de-serializacao-1gen</guid>
      <description>&lt;p&gt;&lt;strong&gt;1.Criar uma classe simples serializável&lt;/strong&gt;&lt;br&gt;
Implemente Serializable e serialize/deserialize um objeto usando ObjectOutputStream e ObjectInputStream.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Testar a compatibilidade de versão&lt;/strong&gt;&lt;br&gt;
Serializar um objeto de uma versão antiga da classe e tentar desserializá-lo após uma mudança na estrutura da classe.&lt;br&gt;
Testar o comportamento do serialVersionUID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Criar uma forma serializada personalizada&lt;/strong&gt;&lt;br&gt;
Usar writeObject e readObject para definir manualmente a serialização de uma classe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Explorar riscos de segurança&lt;/strong&gt;&lt;br&gt;
Criar um objeto vulnerável a ataques via serialização (exemplo: permitir modificação de campos privados via desserialização).&lt;br&gt;
Corrigir a vulnerabilidade implementando readObject.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Comparar serialização com outras abordagens&lt;/strong&gt;&lt;br&gt;
Implementar persistência de um objeto com JSON (Gson, Jackson) e comparar com a serialização Java.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Faça uma classe serializável e demonstre a serialização e desserialização de um objeto dessa classe.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.*;

// Classe serializável
class Pessoa implements Serializable {
    private static final long serialVersionUID = 1L; // UID para manter compatibilidade
    private String nome;
    private int idade;

    public Pessoa(String nome, int idade) {
        this.nome = nome;
        this.idade = idade;
    }

    @Override
    public String toString() {
        return "Pessoa{nome='" + nome + "', idade=" + idade + "}";
    }
}

public class SerializacaoExemplo {
    public static void main(String[] args) {
        Pessoa pessoa = new Pessoa("João", 30);

        // Serializar objeto
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("pessoa.ser"))) {
            out.writeObject(pessoa);
            System.out.println("Objeto serializado com sucesso!");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Desserializar objeto
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("pessoa.ser"))) {
            Pessoa pessoaLida = (Pessoa) in.readObject();
            System.out.println("Objeto desserializado: " + pessoaLida);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;📌 Explicação: Esse código cria uma classe Pessoa serializável, salva um objeto em um arquivo e depois o lê de volta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Modifique a classe do exercício anterior para incluir um novo campo e demonstre o problema de compatibilidade ao desserializar um objeto antigo.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.*;

class Pessoa implements Serializable {
    private static final long serialVersionUID = 1L; // UID fixo para manter compatibilidade
    private String nome;
    private int idade;
    private String email; // Novo campo adicionado

    public Pessoa(String nome, int idade, String email) {
        this.nome = nome;
        this.idade = idade;
        this.email = email;
    }

    @Override
    public String toString() {
        return "Pessoa{nome='" + nome + "', idade=" + idade + ", email='" + email + "'}";
    }
}

public class SerializacaoProblema {
    public static void main(String[] args) {
        // Tentativa de desserializar um objeto criado antes da adição do campo 'email'
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("pessoa.ser"))) {
            Pessoa pessoaLida = (Pessoa) in.readObject();
            System.out.println("Objeto desserializado: " + pessoaLida);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;📌 Explicação: Se um objeto da versão anterior (sem email) for desserializado, pode causar InvalidClassException, pois o serialVersionUID e a estrutura da classe mudaram.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Corrija o problema do exercício anterior implementando uma forma serializada compatível usando serialVersionUID.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.*;

class Pessoa implements Serializable {
    private static final long serialVersionUID = 1L;
    private String nome;
    private int idade;
    private transient String email; // Campo transient não será serializado

    public Pessoa(String nome, int idade, String email) {
        this.nome = nome;
        this.idade = idade;
        this.email = email;
    }

    @Override
    public String toString() {
        return "Pessoa{nome='" + nome + "', idade=" + idade + "', email='" + (email != null ? email : "N/A") + "'}";
    }
}

public class SerializacaoCorrigida {
    public static void main(String[] args) {
        // Desserializar objeto antigo sem email
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("pessoa.ser"))) {
            Pessoa pessoaLida = (Pessoa) in.readObject();
            System.out.println("Objeto desserializado: " + pessoaLida);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;📌 Explicação: O campo email foi marcado como transient, o que impede sua serialização e mantém a compatibilidade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Demonstre como a serialização pode ser uma falha de segurança permitindo a modificação de um objeto privado.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.*;

class Usuario implements Serializable {
    private static final long serialVersionUID = 1L;
    private String nome;
    private String senha; // Senha não protegida!

    public Usuario(String nome, String senha) {
        this.nome = nome;
        this.senha = senha;
    }

    @Override
    public String toString() {
        return "Usuario{nome='" + nome + "', senha='" + senha + "'}";
    }
}

public class FalhaSeguranca {
    public static void main(String[] args) {
        Usuario usuario = new Usuario("admin", "1234");

        // Serializar usuário
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("usuario.ser"))) {
            out.writeObject(usuario);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Modificar o arquivo manualmente e desserializar (Simulando um ataque)
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("usuario.ser"))) {
            Usuario usuarioHackeado = (Usuario) in.readObject();
            System.out.println("Usuário comprometido: " + usuarioHackeado);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;📌 Explicação: A senha é armazenada em texto plano e pode ser extraída ou modificada por um invasor ao alterar o arquivo serializado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Corrija o problema de segurança do exercício anterior tornando os campos sensíveis transient e implementando writeObject() e readObject().&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.*;

class UsuarioSeguro implements Serializable {
    private static final long serialVersionUID = 1L;
    private String nome;
    private transient String senha; // Agora a senha não será serializada

    public UsuarioSeguro(String nome, String senha) {
        this.nome = nome;
        this.senha = senha;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeObject(encrypt(senha)); // Salva senha criptografada
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        senha = decrypt((String) in.readObject()); // Recupera senha descriptografada
    }

    private String encrypt(String senha) {
        return senha == null ? null : new StringBuilder(senha).reverse().toString(); // Simples inversão
    }

    private String decrypt(String senhaCriptografada) {
        return senhaCriptografada == null ? null : new StringBuilder(senhaCriptografada).reverse().toString();
    }

    @Override
    public String toString() {
        return "UsuarioSeguro{nome='" + nome + "', senha='" + senha + "'}";
    }
}

public class SegurancaCorrigida {
    public static void main(String[] args) {
        UsuarioSeguro usuario = new UsuarioSeguro("admin", "1234");

        // Serializar
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("usuarioSeguro.ser"))) {
            out.writeObject(usuario);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Desserializar
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("usuarioSeguro.ser"))) {
            UsuarioSeguro usuarioLido = (UsuarioSeguro) in.readObject();
            System.out.println("Usuário seguro: " + usuarioLido);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;📌 Explicação: O campo senha agora é transient, e os métodos writeObject() e readObject() aplicam uma criptografia simples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Comparar serialização com outras abordagens&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.1 Persistência usando Serialização Java&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.*;

// Classe serializável
class Pessoa implements Serializable {
    private static final long serialVersionUID = 1L;
    private String nome;
    private int idade;

    public Pessoa(String nome, int idade) {
        this.nome = nome;
        this.idade = idade;
    }

    @Override
    public String toString() {
        return "Pessoa{nome='" + nome + "', idade=" + idade + "}";
    }
}

public class SerializacaoJava {
    public static void main(String[] args) {
        Pessoa pessoa = new Pessoa("João", 30);

        // Serializar em arquivo
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("pessoa.ser"))) {
            out.writeObject(pessoa);
            System.out.println("Objeto serializado: " + pessoa);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Desserializar do arquivo
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("pessoa.ser"))) {
            Pessoa pessoaLida = (Pessoa) in.readObject();
            System.out.println("Objeto desserializado: " + pessoaLida);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;📌 Pontos positivos: Integrado ao Java, eficiente em binário.&lt;br&gt;
📌 Pontos negativos: Problemas de compatibilidade ao mudar a classe, não legível para humanos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.2 Persistência usando JSON com Gson&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.*;

// Classe normal sem Serializable
class PessoaGson {
    private String nome;
    private int idade;

    public PessoaGson(String nome, int idade) {
        this.nome = nome;
        this.idade = idade;
    }

    @Override
    public String toString() {
        return "PessoaGson{nome='" + nome + "', idade=" + idade + "}";
    }
}

public class PersistenciaGson {
    public static void main(String[] args) {
        PessoaGson pessoa = new PessoaGson("João", 30);
        Gson gson = new GsonBuilder().setPrettyPrinting().create();

        // Serializar em JSON
        try (FileWriter writer = new FileWriter("pessoa.json")) {
            gson.toJson(pessoa, writer);
            System.out.println("Objeto serializado em JSON:\n" + gson.toJson(pessoa));
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Desserializar do JSON
        try (Reader reader = new FileReader("pessoa.json")) {
            PessoaGson pessoaLida = gson.fromJson(reader, PessoaGson.class);
            System.out.println("Objeto desserializado: " + pessoaLida);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;📌 Pontos positivos: Legível, fácil de integrar com APIs e persistência de dados.&lt;br&gt;
📌 Pontos negativos: JSON ocupa mais espaço e é um pouco mais lento que binário.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.3 Persistência usando JSON com Jackson&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;

// Classe normal sem Serializable
class PessoaJackson {
    private String nome;
    private int idade;

    public PessoaJackson() {} // Jackson precisa de um construtor vazio

    public PessoaJackson(String nome, int idade) {
        this.nome = nome;
        this.idade = idade;
    }

    @Override
    public String toString() {
        return "PessoaJackson{nome='" + nome + "', idade=" + idade + "}";
    }
}

public class PersistenciaJackson {
    public static void main(String[] args) {
        PessoaJackson pessoa = new PessoaJackson("João", 30);
        ObjectMapper objectMapper = new ObjectMapper();

        // Serializar em JSON
        try {
            objectMapper.writeValue(new File("pessoa_jackson.json"), pessoa);
            System.out.println("Objeto serializado em JSON com Jackson");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Desserializar do JSON
        try {
            PessoaJackson pessoaLida = objectMapper.readValue(new File("pessoa_jackson.json"), PessoaJackson.class);
            System.out.println("Objeto desserializado: " + pessoaLida);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;📌 Pontos positivos: Alto desempenho, flexível, suporta diversas configurações.&lt;br&gt;
📌 Pontos negativos: Requer bibliotecas externas, pode exigir configurações extras.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.4 Comparação das abordagens&lt;/strong&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%2Frz4kedp9c4mmqwpp9wij.jpg" 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%2Frz4kedp9c4mmqwpp9wij.jpg" alt="Image description" width="743" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📌 Conclusão:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A serialização Java é eficiente, mas tem problemas de compatibilidade e não é legível.&lt;/li&gt;
&lt;li&gt;O Gson é simples, fácil de usar e ideal para APIs.&lt;/li&gt;
&lt;li&gt;O Jackson tem melhor desempenho e é mais configurável, sendo ótimo para grandes aplicações.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Item 86: Tenha cautela ao implementar a Serializable</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 30 Jan 2025 17:03:22 +0000</pubDate>
      <link>https://dev.to/javaefetivo/item-86-tenha-cautela-ao-implementar-a-serializable-258i</link>
      <guid>https://dev.to/javaefetivo/item-86-tenha-cautela-ao-implementar-a-serializable-258i</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Implementação Simples, Consequências Complexas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basta adicionar implements Serializable para tornar uma classe serializável.&lt;/li&gt;
&lt;li&gt;Serializar uma classe pode ter custos significativos a longo prazo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Impacto na Evolução da Classe&lt;/strong&gt;&lt;br&gt;
Uma vez serializável, sua forma serializada se torna parte da API pública.&lt;br&gt;
Alterações internas podem quebrar a compatibilidade com versões anteriores.&lt;br&gt;
É possível manter compatibilidade manualmente (ObjectOutputStream.putFields e ObjectInputStream.readFields), mas é complexo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Problemas com serialVersionUID&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cada classe serializável tem um identificador único (serialVersionUID).&lt;/li&gt;
&lt;li&gt;Se não for especificado manualmente, o compilador o gera automaticamente.&lt;/li&gt;
&lt;li&gt;Qualquer alteração na classe pode mudar esse ID, quebrando a compatibilidade e gerando InvalidClassException.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Riscos de Segurança&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serialização ignora construtores e pode burlar restrições da linguagem.&lt;/li&gt;
&lt;li&gt;Objetos podem ser criados com valores inválidos ou permitir acesso não autorizado.&lt;/li&gt;
&lt;li&gt;Dependência da desserialização padrão pode resultar em vulnerabilidades (ver Item 88).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Aumento na Complexidade de Testes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classes serializáveis precisam ser testadas entre diferentes versões.&lt;/li&gt;
&lt;li&gt;Quanto mais classes serializáveis, maior a matriz de testes necessária.&lt;/li&gt;
&lt;li&gt;Formas serializadas mal planejadas dificultam a evolução do código.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Quando Serializar é Necessário&lt;/strong&gt;&lt;br&gt;
Essencial para frameworks que exigem serialização.&lt;br&gt;
Útil em classes de valor (BigInteger, Instant) e coleções.&lt;br&gt;
Classes que representam processos ativos (ThreadPool) geralmente não devem ser serializáveis&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Serialização e Herança&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classes projetadas para herança geralmente não devem ser serializáveis.&lt;/li&gt;
&lt;li&gt;Interfaces raramente devem estender Serializable, pois impõem um fardo extra a implementações futuras.&lt;/li&gt;
&lt;li&gt;Exceções notáveis: Throwable (para propagação de exceções via RMI) e Component (para GUIs no Swing/AWT).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;8. Problemas com Classes Internas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classes internas não devem ser serializáveis devido a campos sintéticos não especificados.&lt;/li&gt;
&lt;li&gt;Classes membros estáticas podem implementar Serializable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;9. Alternativas à Serialização&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usar o padrão proxy de serialização (Item 90) para maior controle.&lt;/li&gt;
&lt;li&gt;Utilizar formatos como JSON ou XML para persistência e transmissão.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Capítulo 12: Serialização - Item 85: Prefira alternativas à serialização Java</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 30 Jan 2025 16:36:47 +0000</pubDate>
      <link>https://dev.to/javaefetivo/capitulo-12-serializacao-3jng</link>
      <guid>https://dev.to/javaefetivo/capitulo-12-serializacao-3jng</guid>
      <description>&lt;p&gt;A Serialização ainda é usada hoje, mas com muita cautela. Ela foi amplamente utilizada no passado para persistência de objetos e comunicação entre sistemas, mas devido a diversos problemas de segurança e eficiência, seu uso tem diminuído.&lt;/p&gt;

&lt;p&gt;Atualmente, frameworks modernos e tecnologias como JSON, XML, Protobuf e Avro são preferidos para troca de dados, pois são mais seguros, interoperáveis e eficientes. No entanto, a serialização Java ainda pode ser encontrada em sistemas legados e em aplicações que precisam de compatibilidade com tecnologias antigas.&lt;/p&gt;

&lt;p&gt;Se for realmente necessário usar serialização, recomenda-se adotar boas práticas de segurança, como filtragem de objetos e evitar desserialização de fontes não confiáveis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Atenção: Com as evoluções do Java e práticas modernas, existem alternativas mais seguras e eficientes para lidar com serialização/desserialização. Mas como estamos estudando o livro vamos considerar para aprender. VER NO TÓPICO FINAL SOBRE SERIALIZAÇÃO&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Item 85: Prefira alternativas à serialização Java&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que é Serialização?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Processo de transformar um objeto em uma sequência de bytes para armazenamento ou transmissão.&lt;/li&gt;
&lt;li&gt;Desserialização é o processo inverso, reconstruindo o objeto a partir dos bytes serializados.&lt;/li&gt;
&lt;li&gt;Utiliza a interface Serializable no Java.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Problemas da Serialização Java&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Superfície de Ataque Grande&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O método readObject atua como um "construtor mágico", podendo instanciar objetos inesperados.&lt;/li&gt;
&lt;li&gt;Qualquer classe que implemente Serializable pode ser um ponto de exploração.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Vulnerabilidades de Segurança&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Possibilidade de execução remota de código (RCE) ao desserializar objetos de origem desconhecida.&lt;/li&gt;
&lt;li&gt;Uso de gadgets (métodos chamados automaticamente durante a desserialização) para criar cadeias de ataque.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Bombas de Desserialização&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Objetos que exigem grande poder computacional para serem desserializados.&lt;/li&gt;
&lt;li&gt;Exemplo: HashSet profundamente aninhado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Exemplo de bomba de desserialização:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.*;
import java.util.HashSet;

public class DeserializationBomb {
    public static void main(String[] args) throws Exception {
        HashSet&amp;lt;Object&amp;gt; root = new HashSet&amp;lt;&amp;gt;();
        HashSet&amp;lt;Object&amp;gt; s1 = root;
        HashSet&amp;lt;Object&amp;gt; s2;

        for (int i = 0; i &amp;lt; 100; i++) {
            s2 = new HashSet&amp;lt;&amp;gt;();
            s1.add(s2);
            s1 = s2;
        }

        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("bomb.ser"))) {
            out.writeObject(root);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Alternativas à Serialização Java&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;JSON&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leve, legível e amplamente suportado.
Exemplo com Gson:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.google.gson.Gson;

class Pessoa {
    String nome;
    int idade;
}

public class JsonExample {
    public static void main(String[] args) {
        Gson gson = new Gson();
        Pessoa pessoa = new Pessoa();
        pessoa.nome = "João";
        pessoa.idade = 30;

        String json = gson.toJson(pessoa);
        System.out.println(json);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Protocol Buffers (Protobuf)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Binário e eficiente.&lt;/li&gt;
&lt;li&gt;Necessita da definição de esquemas .proto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Como Mitigar Riscos se a Serialização for Necessária&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Evite Desserialização de Dados Não Confiáveis&lt;/li&gt;
&lt;li&gt;Use Filtragem de Objetos (ObjectInputFilter desde Java 9)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ObjectInputFilter filter = info -&amp;gt; {
    if (info.serialClass() != null &amp;amp;&amp;amp; info.serialClass().getName().equals("MinhaClasseSegura")) {
        return ObjectInputFilter.Status.ALLOWED;
    }
    return ObjectInputFilter.Status.REJECTED;
};

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("objeto.ser"));
ois.setObjectInputFilter(filter);
Object obj = ois.readObject();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Utilize Lista Branca em vez de Lista Negra&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permita apenas classes explícitas na desserialização.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Evite ao máximo a Serialização Java em sistemas novos.&lt;/li&gt;
&lt;li&gt;Prefira formatos mais seguros e eficientes como JSON, Protobuf e Jackson.&lt;/li&gt;
&lt;li&gt;Se precisar desserializar objetos, use filtragem rigorosa para evitar ataques.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Exemplo do livro:&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%2Fdqutfo4ihmejmydz8y01.jpg" 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%2Fdqutfo4ihmejmydz8y01.jpg" alt="Image description" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Resumo Bônus: Threads Virtuais</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 16 Jan 2025 22:01:36 +0000</pubDate>
      <link>https://dev.to/javaefetivo/resumo-bonus-threads-virtuais-11gm</link>
      <guid>https://dev.to/javaefetivo/resumo-bonus-threads-virtuais-11gm</guid>
      <description>&lt;p&gt;As threads virtuais são um recurso introduzido no Java 19 como parte do projeto Loom. Elas são leves e otimizadas, permitindo uma abordagem mais eficiente para programação concorrente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. O que são Threads Virtuais?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Threads implementadas inteiramente em software.&lt;/li&gt;
&lt;li&gt;Criadas e gerenciadas pela JVM (Java Virtual Machine), não pelo sistema operacional.&lt;/li&gt;
&lt;li&gt;Muito mais leves que threads do sistema operacional.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Características das Threads Virtuais&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leveza: Cada thread virtual ocupa muito menos memória que uma thread tradicional.&lt;/li&gt;
&lt;li&gt;Altamente escaláveis: Permitem a execução de milhares (ou até milhões) de threads no mesmo processo.&lt;/li&gt;
&lt;li&gt;Integração com o modelo de threads existente: São compatíveis com o java.lang.Thread.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Benefícios&lt;/strong&gt;&lt;br&gt;
Programação mais simples: Utilizam o modelo tradicional de threads, sem necessidade de complexidade adicional (como pools de threads).&lt;br&gt;
Redução de bloqueios: Operações bloqueantes (como I/O) são tratadas de forma eficiente pela JVM.&lt;br&gt;
Eficiência de recursos: Consomem menos memória e tempo de CPU comparadas às threads tradicionais.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Como criar Threads Virtuais?&lt;/strong&gt;&lt;br&gt;
Utiliza a classe Thread.ofVirtual(), disponível no Java 19+:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var thread = Thread.ofVirtual().start(() -&amp;gt; {
    System.out.println("Thread virtual em execução!");
});

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

&lt;/div&gt;



&lt;p&gt;Alternativamente, use um executor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(() -&amp;gt; {
    System.out.println("Executando tarefa em thread virtual.");
});
executor.shutdown();

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Diferenças entre Threads Virtuais e Tradicionais&lt;/strong&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%2Fbzgxfe56550yrz8sigi6.jpg" 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%2Fbzgxfe56550yrz8sigi6.jpg" alt="Image description" width="800" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Casos de Uso&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aplicações de servidor com muitos clientes simultâneos (alta concorrência).&lt;/li&gt;
&lt;li&gt;Operações I/O intensivas (ex.: servidores HTTP).&lt;/li&gt;
&lt;li&gt;Substituição de pools de threads tradicionais.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Considerações e Limitações&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estado experimental: Ainda não recomendado para produção (Java 19 e 20).&lt;/li&gt;
&lt;li&gt;Compatibilidade: Algumas bibliotecas que usam operações bloqueantes podem não se beneficiar.&lt;/li&gt;
&lt;li&gt;Diagnóstico: Ferramentas de monitoramento precisam suportar threads virtuais.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Item 84: Não dependa do agendador de threads</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 16 Jan 2025 20:43:32 +0000</pubDate>
      <link>https://dev.to/javaefetivo/item-84-nao-dependa-do-agendador-de-threads-hcg</link>
      <guid>https://dev.to/javaefetivo/item-84-nao-dependa-do-agendador-de-threads-hcg</guid>
      <description>&lt;p&gt;&lt;strong&gt;1. O papel do agendador de threads&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Função: Determina quais threads executáveis devem rodar e por quanto tempo.&lt;/li&gt;
&lt;li&gt;Variedade: Políticas variam entre sistemas operacionais.&lt;/li&gt;
&lt;li&gt;Recomendação: Não dependa do comportamento do agendador para correção ou desempenho; isso compromete a portabilidade.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Estratégia para programas robustos&lt;/strong&gt;&lt;br&gt;
Manter threads executáveis equilibradas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O número médio de threads executáveis deve ser próximo ao número de processadores disponíveis.&lt;/li&gt;
&lt;li&gt;Evita sobrecarga no agendador e garante comportamento consistente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Threads não executáveis:&lt;/strong&gt;&lt;br&gt;
O número total de threads pode ser maior, mas as threads em espera (não executáveis) não afetam a carga.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Técnicas para gerenciar threads&lt;/strong&gt;&lt;br&gt;
Evitar espera-ativa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Threads não devem verificar constantemente o estado de um objeto compartilhado.&lt;/li&gt;
&lt;li&gt;Isso aumenta o uso do processador e prejudica a eficiência.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Diminuir o número de threads executáveis:&lt;/strong&gt;&lt;br&gt;
Dimensionar corretamente pools de threads no Executor Framework.&lt;br&gt;
Criar tarefas pequenas, mas não tão pequenas que a sobrecarga prejudique o desempenho.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Exemplo de má prática: espera-ativa&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SlowCountDownLatch {
    private int count;

    public SlowCountDownLatch(int count) {
        this.count = count;
    }

    public void await() {
        while (count &amp;gt; 0) {
            // Espera-ativa: utiliza o processador desnecessariamente
        }
    }

    public void countDown() {
        if (count &amp;gt; 0) {
            count--;
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problema:&lt;/strong&gt; Consome recursos excessivos, deixando o processador ocupado inutilmente.&lt;br&gt;
&lt;strong&gt;Alternativa:&lt;/strong&gt; Utilize CountDownLatch, que usa bloqueio eficiente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Evitar o uso de Thread.yield&lt;/strong&gt;&lt;br&gt;
Não confiável:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Funciona de forma inconsistente em diferentes implementações da JVM.&lt;/li&gt;
&lt;li&gt;Não resolve problemas de forma robusta ou portátil.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemplo incorreto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while (!condition) {
    Thread.yield(); // Tentativa de "ceder" a CPU para outras threads
}

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

&lt;/div&gt;



&lt;p&gt;Solução: Reestruturar o código para reduzir threads executáveis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Ajuste de prioridades de threads&lt;/strong&gt;&lt;br&gt;
Pouco portátil:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prioridades de threads variam entre sistemas operacionais e JVMs.
Uso recomendado:&lt;/li&gt;
&lt;li&gt;Melhorar qualidade de serviço em aplicações funcionais.
Evitar para corrigir problemas estruturais.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Conclusões&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não dependa do agendador para:&lt;/li&gt;
&lt;li&gt;Correção do programa.&lt;/li&gt;
&lt;li&gt;Otimização de desempenho.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Evite:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uso de Thread.yield.&lt;/li&gt;
&lt;li&gt;Ajustes excessivos de prioridade de threads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Melhor abordagem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reestruturar aplicações para manter um número equilibrado de threads executáveis.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Exemplo do livro:&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%2Fdd2c89bzd83ej33ogg5r.jpg" 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%2Fdd2c89bzd83ej33ogg5r.jpg" alt="Image description" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
    </item>
    <item>
      <title>Exemplos de código para os sincronizadores</title>
      <dc:creator>Java Efetivo (livro)</dc:creator>
      <pubDate>Thu, 09 Jan 2025 05:31:30 +0000</pubDate>
      <link>https://dev.to/javaefetivo/exemplos-de-codigo-para-os-sincronizadores-2e9l</link>
      <guid>https://dev.to/javaefetivo/exemplos-de-codigo-para-os-sincronizadores-2e9l</guid>
      <description>&lt;p&gt;Aqui estão exemplos de código para os sincronizadores mencionados no item 80, com explicações de uso para facilitar o estudo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. CountDownLatch: Barreira de uso único para coordenação de threads&lt;/strong&gt;&lt;br&gt;
O CountDownLatch permite que uma ou mais threads aguardem até que um conjunto de operações realizadas por outras threads seja concluído.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        int numberOfWorkers = 3;
        CountDownLatch latch = new CountDownLatch(numberOfWorkers);

        for (int i = 0; i &amp;lt; numberOfWorkers; i++) {
            new Thread(new Worker(latch, "Worker-" + i)).start();
        }

        System.out.println("Waiting for workers to finish...");
        latch.await(); // Aguarda todos os trabalhadores chamarem latch.countDown()
        System.out.println("All workers are done. Proceeding...");
    }

    static class Worker implements Runnable {
        private final CountDownLatch latch;
        private final String name;

        Worker(CountDownLatch latch, String name) {
            this.latch = latch;
            this.name = name;
        }

        @Override
        public void run() {
            System.out.println(name + " is working...");
            try {
                Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            System.out.println(name + " finished.");
            latch.countDown(); // Decrementa o contador
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Semaphore: Controle de acesso a recursos compartilhados&lt;/strong&gt;&lt;br&gt;
O Semaphore gerencia um conjunto de permissões para controlar o acesso a recursos limitados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    public static void main(String[] args) {
        int permits = 2; // Número de permissões disponíveis
        Semaphore semaphore = new Semaphore(permits);

        for (int i = 1; i &amp;lt;= 5; i++) {
            new Thread(new Task(semaphore, "Task-" + i)).start();
        }
    }

    static class Task implements Runnable {
        private final Semaphore semaphore;
        private final String name;

        Task(Semaphore semaphore, String name) {
            this.semaphore = semaphore;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                System.out.println(name + " is waiting for a permit...");
                semaphore.acquire(); // Adquire uma permissão
                System.out.println(name + " got a permit and is working...");
                Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho
                System.out.println(name + " is releasing a permit.");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                semaphore.release(); // Libera a permissão
            }
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. CyclicBarrier: Sincronização em pontos de barreira reutilizáveis&lt;/strong&gt;&lt;br&gt;
O CyclicBarrier sincroniza várias threads em um ponto comum (barreira). Ele pode ser reutilizado após todas as threads atingirem o ponto de barreira.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    public static void main(String[] args) {
        int numberOfThreads = 3;
        CyclicBarrier barrier = new CyclicBarrier(numberOfThreads, () -&amp;gt; {
            System.out.println("All threads have reached the barrier. Proceeding...");
        });

        for (int i = 0; i &amp;lt; numberOfThreads; i++) {
            new Thread(new Task(barrier, "Thread-" + i)).start();
        }
    }

    static class Task implements Runnable {
        private final CyclicBarrier barrier;
        private final String name;

        Task(CyclicBarrier barrier, String name) {
            this.barrier = barrier;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                System.out.println(name + " is performing some work...");
                Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho
                System.out.println(name + " reached the barrier.");
                barrier.await(); // Aguarda todas as threads chegarem à barreira
                System.out.println(name + " passed the barrier.");
            } catch (Exception e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Phaser: Sincronização avançada e dinâmica de threads&lt;/strong&gt;&lt;br&gt;
O Phaser é semelhante ao CyclicBarrier, mas suporta threads que entram e saem dinamicamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.concurrent.Phaser;

public class PhaserExample {
    public static void main(String[] args) {
        Phaser phaser = new Phaser(1); // Registra o "partida principal"

        for (int i = 0; i &amp;lt; 3; i++) {
            new Thread(new Task(phaser, "Task-" + i)).start();
        }

        // Avança para a próxima fase após garantir que todas as threads registradas concluíram
        System.out.println("Main thread waiting for phase 1 completion...");
        phaser.arriveAndAwaitAdvance();

        System.out.println("All tasks completed phase 1. Main thread moving to phase 2...");
        phaser.arriveAndDeregister(); // Desregistra a thread principal
    }

    static class Task implements Runnable {
        private final Phaser phaser;
        private final String name;

        Task(Phaser phaser, String name) {
            this.phaser = phaser;
            this.name = name;
            phaser.register(); // Registra a thread no Phaser
        }

        @Override
        public void run() {
            System.out.println(name + " is working on phase 1...");
            try {
                Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            System.out.println(name + " completed phase 1.");
            phaser.arriveAndAwaitAdvance(); // Indica chegada na fase atual e aguarda

            System.out.println(name + " is working on phase 2...");
            try {
                Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            System.out.println(name + " completed phase 2.");
            phaser.arriveAndDeregister(); // Indica chegada e desregistra
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;Esses exemplos ajudam a entender o funcionamento de cada sincronizador. Você pode experimentar ajustando os números de threads e tempos para observar os efeitos no comportamento de sincronização.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
  </channel>
</rss>
