Linguagem de Programação Flashcards
Vantagens das coleções genéricas
<p><strong>Exemplo:</strong></p>
<p><code>List<<span>int</span>> numeros = <span>new</span> List<<span>int</span>>();</code><br></br><code>numeros.Add(<span>10</span>);</code><br></br><code>numeros.Add(<span>"Texto"</span>); <span>// Erro de compilação!</span></code></p>
<br></br>
<ul>
<li>Evita erros de <strong>casting</strong> (conversão de tipo) em tempo de execução.
<ul>
<li>Como a lista foi declarada como <code>List<int></code>, tentar adicionar uma string gera erro na compilação.</li>
</ul>
</li>
<li>Melhor legibilidade e manutenção do código
<ul>
<li>O uso de tipos explícitos torna o código mais compreensível, pois deixa claro que tipo de dado a coleção deve conter.</li>
</ul>
</li>
<li>Eliminação da necessidade de conversões explícitas
<ul>
<li>Nas coleções não genéricas, frequentemente é necessário fazer <strong>casting</strong> ao recuperar um item, o que pode levar a exceções em tempo de execução.</li>
</ul>
</li>
<li>Melhor desempenho
<ul>
<li>Como não há conversões de tipo em tempo de execução, o uso de coleções genéricas melhora a eficiência do código.</li>
</ul>
</li>
</ul>
O que são tipos genéricos?
<p>Tipos genéricos são um recurso da programação orientada a objetos que permite criar classes, interfaces e métodos que podem operar com <strong>diferentes tipos de dados</strong> sem perder segurança de tipo. Eles são amplamente utilizados para aumentar a <strong>reutilização de código</strong> e evitar a necessidade de conversões explícitas.</p>
<br></br>
<p>Exemplo:</p>
<p><code>// Definição de uma classe genérica com um parâmetro de tipo T</code><br></br><code>public class Caixa<T> {</code><br></br><code>private T objeto;</code></p>
<p><code>public void setObjeto(T objeto) {</code><br></br><code>this.objeto = objeto;</code><br></br><code>}</code></p>
<p><code>public T getObjeto() {</code><br></br><code>return objeto;</code><br></br><code>}</code><br></br><code>}</code></p>
<p><code>// Uso da classe genérica</code><br></br><code>public class Main {</code><br></br><code>public static void main(String[] args) {</code><br></br><code></code></p>
<p><code>Caixa<String> caixaDeTexto = new Caixa<>();</code><br></br><code>caixaDeTexto.setObjeto("Olá, Genéricos!");</code><br></br><code>System.out.println(caixaDeTexto.getObjeto()); // Saída: Olá, Genéricos!</code></p>
<p><code>Caixa<Integer> caixaDeNumeros = new Caixa<>();</code><br></br><code>caixaDeNumeros.setObjeto(42);</code><br></br><code>System.out.println(caixaDeNumeros.getObjeto()); // Saída: 42</code><br></br><code>}</code><br></br><code>}</code></p>
Exemplo de coleção não genérica
List<String> lista = new ArrayList<>();
lista.add("Texto");
String texto = lista.get(0); // Sem necessidade de casting</String>
Como funciona o Garbage Collector?
<p>O Garbage Collector segue um processo básico:</p>
<ol>
<li><strong>Alocação de memória</strong> → Quando um objeto é criado, ele é armazenado na memória heap gerenciado. Não é o heap nativo/principal do sistema operacional.</li>
<li><strong>Verificação de referências</strong> → O GC identifica quais objetos ainda estão sendo usados pelo programa.</li>
<li><strong>Coleta de lixo</strong> → Objetos sem referências são removidos da memória para liberar espaço.</li>
</ol>
Quando o Garbage Collector é acionado?
<p>O GC pode ser acionado automaticamente pelo <strong>runtime da linguagem</strong> quando a memória disponível está baixa ou quando o sistema decide que é um bom momento para otimizar a memória. Em algumas linguagens, o GC pode ser chamado manualmente, mas isso não é recomendado na maioria dos casos.</p>
Como funciona o profilling?
<ol>
<li><strong>Instrumentação</strong>
<ol>
<li>O código é modificado para incluir medições de tempo de execução.</li>
<li>Exemplo: Adicionar <code>System.nanoTime()</code> em Java para medir tempos de execução.</li>
</ol>
</li>
<li><strong>Amostragem (Sampling)</strong>
<ol>
<li>O profiler monitora periodicamente quais funções estão sendo executadas, sem modificar o código.</li>
<li>Menos impacto no desempenho, mas pode perder detalhes de execuções rápidas.</li>
</ol>
</li>
<li><strong>Tracing (Rastreamento)</strong>
<ol>
<li>Registra cada chamada de função e evento do programa, capturando informações detalhadas.</li>
<li>Pode gerar grandes volumes de dados e impactar a performance.</li>
</ol>
</li>
<li><strong>Heap & Memory Profiling</strong>
<ol>
<li>Analisa <strong>uso de memória</strong> e possíveis <strong>vazamentos de memória</strong>.</li>
<li>Mede alocações e desalocações de objetos.</li>
</ol>
</li>
</ol>
O que é profilling?
<p><strong>Profiling</strong> é uma técnica usada para analisar o desempenho de um programa, <strong>identificando gargalos</strong> e otimizando o uso de recursos, <strong>como CPU, memória e operações de entrada/saída (I/O)</strong>.</p>