<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.caelum.com.br &#187; arrays</title>
	<atom:link href="http://blog.caelum.com.br/tag/arrays/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.caelum.com.br</link>
	<description>blog dos desenvolvedores da Caelum</description>
	<lastBuildDate>Thu, 09 Feb 2012 13:04:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Não posso descobrir nem instanciar tipos genéricos! Porque?</title>
		<link>http://blog.caelum.com.br/nao-posso-descobrir-nem-instanciar-tipos-genericos-porque/</link>
		<comments>http://blog.caelum.com.br/nao-posso-descobrir-nem-instanciar-tipos-genericos-porque/#comments</comments>
		<pubDate>Mon, 28 Apr 2008 23:38:45 +0000</pubDate>
		<dc:creator>Paulo Silveira</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[arrays]]></category>
		<category><![CDATA[erasure]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[reificação]]></category>
		<category><![CDATA[tipagem]]></category>
		<category><![CDATA[tipos]]></category>

		<guid isPermaLink="false">http://blog.caelum.com.br/2008/04/28/nao-posso-descobrir-nem-instanciar-tipos-genericos-porque/</guid>
		<description><![CDATA[São incontáveis os posts no GUJ com uma pergunta semelhante: &#8220;Posso extrair o nome de um tipo genérico?&#8220;, &#8220;Não consigo extrair tipo do genérico!&#8220;, &#8220;Utilizando generics para instanciar objetos&#8220;, entre outros. Curioso que esse tipo de pergunta tem aumentado muito nos últimos tempos, identificando um possível crescimento no uso do Java 5 em diante. Já <a href="http://blog.caelum.com.br/nao-posso-descobrir-nem-instanciar-tipos-genericos-porque/#more-208'" class="more-link">more &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>São incontáveis os posts no GUJ com uma pergunta semelhante: &#8220;<a href="http://guj.com.br/java/87606-extrair-nome-do-tipo-generico">Posso extrair o nome de um tipo genérico?</a>&#8220;, &#8220;<a href="http://guj.com.br/java/87532-generics---nao-consigo-instanciar-o-tipo">Não consigo extrair tipo do genérico!</a>&#8220;, &#8220;<a href="http://www.guj.com.br/java/82372-utilizando-o-generics-para-instanciar-objetos">Utilizando generics para instanciar objetos</a>&#8220;, entre outros. Curioso que esse tipo de pergunta tem aumentado muito nos últimos tempos, identificando um possível crescimento no uso do Java 5 em diante. Já era a hora!</p>
<p>Eu já havia postado sobre isso quando falei de <a href="http://blog.caelum.com.br/2007/04/08/generics-inferencia-de-tipos-e-reificacao-no-java-7/">reificação de tipos parametrizados</a>, mas de uma maneira mais geral.</p>
<p>A questão básica é a seguinte: Se eu tenho um tipo genérico, que recebe um tipo parametrizado <code>T</code> como argumento, eu posso instanciar <code>T</code> de alguma forma?</p>
<p>Quem sabe tentar assim:</p>
<pre class="brush: java; title: ; notranslate">
class Dao&lt;T&gt; {
  public T cria() {
    return new T();
  }
}
</pre>
<p>Essa forma não funciona. Você não tem garantias sobre os construtores que o tipo <code>T</code> possui. E então se tentarmos assim:</p>
<pre class="brush: java; title: ; notranslate">
class Dao&lt;T&gt; {
  public T cria() {
    return T.class.newInstance();
  }
}
</pre>
<p>Aqui a sintaxe até poderia ser possível, mas infelizmente o java não sabe quem é <code>T</code> nem mesmo em tempo de execução. Nem mesmo com manipulação de bytecode ou qualquer outro recurso. Isso porque o compilador &#8220;apaga&#8221; essa informação depois de utilizada: é a tal da mal falada <strong><a href="http://download.oracle.com/javase/tutorial/java/generics/erasure.html">erasure</a></strong>. </p>
<p><strong>Qual seria a vantagem da erasure?</strong></p>
<p>Antes de mais nada: erasure não serve para poder rodar código do Java 5 em VMs Java 1.4 ou menor! Não é esse o objetivo.</p>
<p>Quando a JSR14 do generics foi proposta, eles queriam mais que compatibilidade para trás em relação a compilação, eles queriam também a possibilidade de migrar o código antigo para poder usar código novo: uma <code>ArrayList</code> precisa poder ser passada como argumento para alguém que receba <code>List&lt;QualquerClasse&gt;</code> como argumento!  </p>
<p>Para ilustrar a situação, imagine que eu tenho uma aplicação grande <strong>X</strong> que usasse a classe  <code>ArrayList</code> em muitos lugares (como a grande maioria das aplicações). Essa aplicação <strong>X</strong> usa a biblioteca <strong>B</strong>, que recebe <code>List</code> como argumento em muitos de seus métodos. Se um dia a bibioteca <strong>B</strong> passasse a usar <code>List</code> genérica, gostaríamos que a aplicação <strong>X</strong> atualizasse <strong>B</strong> sem maiores problemas: sem precisar recompilar nada, nem trocar nada no código fonte. O <a href="http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html">Neal Gafter escreveu muito sobre isso</a> pouco antes da release do Java 5, dada as inúmeras críticas que eles estavam recebendo.</p>
<p>Se o Java tivesse optado por outra maneira de implementar generics, teria ou quebrado compatibilidade com o uso não genérico de classes que viraram genéricas, ou precisaria criar classes paralelas as atuais, praticamente copiadas e coladas, só que estas genéricas, tornando as antigas deprecated ou legadas.</p>
<p><strong>Como o .NET resolveu o mesmo problema?</strong></p>
<p>O .NET seguiu essa segunda forma, e criou uma hierarquia quase que paralela de coleções dentro do name space <code>System.Collections.Generic</code>.</p>
<p>A <a href="http://msdn2.microsoft.com/en-us/library/system.collections.ilist.aspx">IList</a> é a interface que define as operações em uma lista não genérica, e a <a href="http://msdn2.microsoft.com/en-us/library/system.collections.arraylist.aspx">ArrayList</a> é sua implementação mais comumente usada. Quando entrou generics no .NET eles criaram uma outra interface para a lista, com mesmo nome, só que genérica: a <a href="http://msdn2.microsoft.com/en-us/library/5y536ey6.aspx">IList&lt;T&gt;</a>.</p>
<p>A classe <a href="http://msdn2.microsoft.com/en-us/library/6sh2ey19.aspx">List</a> já é a implementação da interface genérica, e é ela quem você vai usar em vez de <code>ArrayList</code>. Ela possui uma definição bem estranha:</p>
<pre class="brush: csharp; title: ; notranslate">
public class List : IList, ICollection, IEnumerable, IList, ICollection, IEnumerable
</pre>
<p>Ela implementa tanto a lista genérica como a não genérica. O .NET tem um recurso que nós não temos, que faz com que apesar dessa lista também implementar a interface não genérica, você só consegue invocar os métodos não genéricos (que trabalham com <code>Object</code>) se estiver se referenciando a ela explicitamente como uma lista não genérica, como o código abaixo:</p>
<pre class="brush: csharp; title: ; notranslate">
IList x = new List&lt;String&gt;();
x.Add(2);
</pre>
<p>Apesar desse código compilar, no .NET temos essa informação dos tipos genéricos em tempo de execução, o que fará gerar uma exceção:</p>
<p><code>System.ArgumentException: The value "2" is not of type "System.String" e cannot be used in this generic collection<br />
</code></p>
<p>No Java teríamos apenas um <em>unchecked warning</em> na linha da declaração da referência, e uma possível <code>ClassCastException</code> mais a frente no código.</p>
<p>Aqui a vantagem é você poder passar uma <code>List</code> genérica para um código .NET antigo, que recebe como argumento uma <code>IList</code> não genérica. Além disso, no .NET você pode sim descobrir quem é <code>T</code> em tempo de execução:</p>
<pre class="brush: csharp; title: ; notranslate">
class ClasseGenerica&lt;T&gt; {
  void metodo() {  Console.WriteLine(typeof(T)); }
}
</pre>
<p><strong>Em resumo</strong>: o sistema de generics do .NET é realmente seguro, não temos como burlá-lo através de <em>unchecked casts</em>, como ocorre em Java. O Java novamente sacrificou alguns recursos interessantes em favor a compatibilidade de versões e interoperabilidade entre classes genéricas e as não genéricas já existentes. Cada um com sua vantagem. Como citei no outro artigo, existem algumas idéias de <a href="http://gafter.blogspot.com/2006/11/reified-generics-for-java.html">dar suporte a tipos genéricos reificados no Java</a>, ao mesmo tempo que outros ficariam ainda com a erasure, sendo que você pode escolher qual o que te agrada para aquela classe genérica em particular. Talvez ter as duas opções adicione ainda mais complexidade a tipagem genérica do Java, mas eu particularmente gosto da idéia.</p>
<p>Mais uma vez um post que era para ser sucinto ficou longo. Agradeço ao Rafael Steil e Rodrigo Kumpera pela colaboração, e ao Lucas Cavalcanti e Guilherme Moreira pedindo para que fosse elaborado um post mais completo sobre esse assunto tão pertinente.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.caelum.com.br/nao-posso-descobrir-nem-instanciar-tipos-genericos-porque/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>

