Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

Esta é uma postagem traduzida por IA.

제이온

[Effective Java] Item 6. Evite a criação de objetos desnecessários

  • Idioma de escrita: Coreana
  • País de referência: Todos os países country-flag

Selecionar idioma

  • Português
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

Texto resumido pela IA durumis

  • Criar instâncias de String ou Boolean usando a palavra-chave new é um desperdício de memória, portanto, é melhor declará-las como literais ou usar o método Boolean.valueOf().
  • O método String.matches() usa expressões regulares, o que pode causar problemas de desempenho, portanto, é melhor armazenar em cache a instância Pattern para reutilização.
  • Quando um objeto de visualização é retornado, como o método keySet(), é mais seguro usar uma cópia defensiva para retornar um novo objeto.

Quando criar objetos desnecessários

Usando new String()

String a = new String("hi");
String b = new String("hi");


As strings a, b e c conterão todas a string "hi". No entanto, como os endereços referenciados por essas três strings são todos diferentes, ocorre um desperdício de alocação de memória separada para os mesmos dados.


Untitled


Portanto, ao declarar strings, você deve usar literais em vez da palavra-chave new.


String a = "hi";
String b = "hi";


O código acima usa apenas uma instância. Além disso, usando esse método, garante que todos os códigos que usam o literal de string "hi" dentro da mesma JVM reutilizarão o mesmo objeto. Isso ocorre devido à característica do pool de constantes Java.


Usando new Boolean()

O código acima cria uma instância Boolean usando o construtor que recebe uma string como parâmetro. Boolean só pode ser true ou false, e criar uma instância toda vez é um desperdício de memória. Portanto, é melhor usar o método de fábrica estático Boolean.valueOf().



Usando String.matches()

É melhor usar cache e reutilizar se o custo de criação for alto, mas nem sempre podemos saber o custo do objeto que estamos criando. Por exemplo, se quisermos escrever um método que verifica se uma string fornecida é um numeral romano válido, usar uma expressão regular é a maneira mais fácil, como esta.


public static boolean isRomanNumeral(String s) {
    return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");


No entanto, String.matches() é um método problemático em termos de desempenho. A instância Pattern criada internamente por esse método para expressões regulares é usada uma vez e descartada, tornando-se um alvo de coleta de lixo imediatamente. Se essa expressão regular for usada repetidamente com alta frequência, o custo de criação e descarte da mesma instância Pattern aumentará. Portanto, é melhor armazenar em cache a instância Pattern com antecedência e reutilizá-la sempre que o método isRomanNumeral() for chamado.


public class RomanNumerals {

    private static final Pattern ROMAN = Pattern.compile(
        "^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");

    public static boolean isRomanNumeral(String s) {
        return ROMAN.matcher(s).matches();
    }


Observação

Em todos os exemplos acima, criamos todos os objetos desnecessários em cache como objetos imutáveis. Isso ocorre porque é seguro reutilizá-los. No entanto, existem casos em que a ideia de reutilizar como um objeto imutável é contrária à intuição.


Um adaptador (visualização) é um objeto que delega o trabalho real para um objeto de back-end e atua como uma segunda interface. O adaptador só precisa gerenciar o objeto de back-end, portanto basta criar um adaptador para cada objeto de back-end.


Por exemplo, o método keySet() da interface Map retorna uma visualização Set que contém todas as chaves dentro do objeto Map. Os usuários podem pensar que uma nova instância Set é criada a cada chamada do método keySet(), mas ao observar o conteúdo real da implementação do JDK, uma instância Set mutável é retornada sempre.


Isso ocorre porque, embora a instância Set retornada seja mutável, as funções executadas são todas as mesmas e todas as instâncias Set representam a instância Map. Portanto, não importa se o keySet() criar várias visualizações de objetos, mas não há necessidade nem benefício.


public class UsingKeySet {

    public static void main(String[] args) {
        Map menu = new HashMap<>();
        menu.put("Burger", 8);
        menu.put("Pizza", 9);

        Set names1 = menu.keySet();
        Set names2 = menu.keySet();

        names1.remove("Burger");
        System.out.println(names1.size()); // 1
        System.out.println(names2.size()); // 1
    }


Portanto, se você modificar a instância names1 como acima, a instância names2 também será afetada.


No entanto, pessoalmente, acredito que o valor retornado pelo método keySet() deve usar uma cópia de segurança defensiva e retornar um novo objeto a cada vez. Se a instância Set recebida pelo método keySet() também estiver sendo usada em outro lugar e houver código que altere o estado dessa instância, não poderemos ter certeza sobre o valor da instância Set e da instância Map atualmente em uso.


Além disso, a menos que o keySet() seja usado excessivamente, a interface Set não ser criada a cada vez não terá um impacto mortal no desempenho. Acredito que é melhor criar a interface Set como um objeto imutável para que ela seja mantida e manutenida de forma estável.


Autoboxing

Autoboxing é uma técnica que converte automaticamente tipos básicos e tipos wrapper para frente e para trás quando um programador mistura os dois. No entanto, o autoboxing apenas confunde a distinção entre tipos básicos e tipos wrapper, não a elimina completamente.


public static long sum() {
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    return sum;


Não há problemas com a lógica, mas o código é muito ineficiente em termos de desempenho. Isso ocorre devido ao tipo sum e ao tipo i no loop for.


O tipo sum é Long e o tipo i é long. Ou seja, o tipo long i cria uma nova instância Long a cada vez que é adicionado a sum durante a iteração do loop. Como resultado, você deve usar tipos básicos em vez de tipos wrapper e ter cuidado para que o autoboxing não seja usado sem querer.


Pontos a serem lembrados

Evite criar objetos desnecessários não significa simplesmente que você deve evitar criar objetos porque o custo de criação de objetos é alto.


Especialmente no JVM atual, criar e coletar objetos pequenos gerados desnecessariamente não é uma tarefa muito pesada. Portanto, a menos que seja um objeto muito caro, como uma conexão de banco de dados, não crie um pool de objetos personalizado.


Além disso, lembre-se que o dano causado ao reutilizar objetos quando uma cópia de segurança defensiva é necessária é muito maior do que o dano causado ao criar objetos desnecessários repetidamente. Os efeitos colaterais da criação repetida afetam apenas a forma do código e o desempenho, mas o fracasso da cópia de segurança defensiva leva diretamente a bugs e problemas de segurança.


Fonte

제이온
제이온
제이온
제이온
[Effective Java] Item 1: Considere métodos de fábrica estáticos em vez de construtores Os métodos de fábrica estáticos são uma maneira flexível e eficiente de criar instâncias em vez de construtores. Eles podem ter um nome, retornar instâncias que atendem a condições específicas e melhorar o desempenho por meio do cache. Ao contrário do pad

27 de abril de 2024

[Effective Java] Item 5: Use dependency injection instead of explicitly specifying resources Se uma classe depender de recursos externos, é melhor não usar singletons e classes de utilitário estáticas. A injeção de dependência pode ser usada para melhorar a flexibilidade, reusabilidade e facilidade de teste da classe, e o padrão de fábrica pode s

28 de abril de 2024

[Effective Java] Item 2: Considere um construtor se você tiver muitos parâmetros Ao criar objetos com muitos parâmetros, o padrão de construtor pode tornar o código mais limpo e legível. Crie um objeto de construtor com parâmetros obrigatórios e use métodos setter para definir parâmetros opcionais e, em seguida, chame o método build()

27 de abril de 2024

[Javascript] Estrutura do Objeto (V8) O Objeto JavaScript no motor V8 é otimizado como uma estrutura dependendo do estado, alternando entre o modo Rápido e o modo Dicionário, que funciona como um mapa hash. O modo Rápido é rápido quando as chaves e valores são quase fixos, mas quando uma nova
곽경직
곽경직
곽경직
곽경직
곽경직

18 de março de 2024

Como a Rust previne bugs de simultaneidade Rust é uma linguagem poderosa que resolve os desafios da programação concorrente. Seu sistema de tipos e modelo de propriedade garantem a transferência e o compartilhamento de dados seguros entre threads. Padrões de mutabilidade interna, como Mutex, Chann
곽경직
곽경직
곽경직
곽경직
곽경직

28 de março de 2024

Ideias para melhorar o programa de negociação automatizada Este artigo apresenta ideias para melhorar as funcionalidades do programa de negociação automatizada de Grid Trading, sugerindo a inclusão de gerenciamento de grandes eventos, lógica de gerenciamento de investimentos, funcionalidade de posição curta, entr
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마
(로또 사는 아빠) 살림 하는 엄마

21 de abril de 2024

[Não graduado, sobrevivendo como desenvolvedor] 16. Dicas para criar um portfólio de desenvolvedor júnior Desenvolvedores juniores (especialmente aqueles sem formação em informática) precisam explicar claramente os serviços ou funcionalidades desenvolvidos no seu portfólio, além das tecnologias utilizadas. Por exemplo, em um projeto de "comunidade para candid
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 de abril de 2024

[Não graduado, sobrevivendo como desenvolvedor] 14. Resumo do conteúdo da entrevista técnica frequente para desenvolvedores juniores Guia de preparação para entrevista técnica para desenvolvedores juniores. Área de memória principal, estrutura de dados, RDBMS e NoSQL, orientação de procedimentos e orientação de objetos, sobreposição e sobrecarga, algoritmo de substituição de página, pr
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 de abril de 2024

[Concorrência] Operação Atômica: Memory Fence e Memory Ordering Esta postagem de blog explica como considerar a ordem da memória em operações atômicas e a importância das opções de ordenamento. Ele explica as várias opções de ordenamento, como Relaxado, Adquirir, Lançar, AcqRel e SecCst, junto com os prós e contras de
곽경직
곽경직
곽경직
곽경직
곽경직

12 de abril de 2024