<?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; reflection</title>
	<atom:link href="http://blog.caelum.com.br/tag/reflection/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>O recurso de method missing em Scala</title>
		<link>http://blog.caelum.com.br/o-recurso-de-method-missing-em-scala/</link>
		<comments>http://blog.caelum.com.br/o-recurso-de-method-missing-em-scala/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 13:55:48 +0000</pubDate>
		<dc:creator>Alberto Souza</dc:creator>
				<category><![CDATA[Inovação]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[dinamico]]></category>
		<category><![CDATA[linguagem]]></category>
		<category><![CDATA[method missing]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[stub]]></category>
		<category><![CDATA[tipagem]]></category>

		<guid isPermaLink="false">http://blog.caelum.com.br/?p=4536</guid>
		<description><![CDATA[Um dos argumentos de quem gosta de linguagens estaticamente tipadas é a ajuda fornecida pelo compilador no momento da escrita de código. Erros como invocação de métodos que não existem e assinatura errada são facilmente evitados. O mesmo não é encontrado nas linguagens mais dinâmicas, como Ruby, onde os testes de unidade podem trazer essa <a href="http://blog.caelum.com.br/o-recurso-de-method-missing-em-scala/#more-4536'" class="more-link">more &#187;</a>]]></description>
			<content:encoded><![CDATA[<p style="float:right; margin:0 0 10px 15px; width:240px;">
		<img src="http://caelum.wpengine.netdna-cdn.com/wp-content/uploads/2011/09/method_missing.jpg" width="240" />
		</p><p>Um dos argumentos de quem gosta de linguagens estaticamente tipadas é a ajuda fornecida pelo compilador no momento da escrita de código. Erros como invocação de métodos que não existem e assinatura errada são facilmente evitados. O mesmo não é encontrado nas linguagens mais dinâmicas, como Ruby, onde os testes de unidade podem trazer essa garantia. Entretanto, a dinamicidade dessas linguagens permite que escrevamos códigos que não são possiveis nas estaticamente tipadas, como Java.</p>
<p><a href="http://caelum.wpengine.netdna-cdn.com/wp-content/uploads/2011/09/method_missing.jpg"><img src="http://caelum.wpengine.netdna-cdn.com/wp-content/uploads/2011/09/method_missing.jpg" alt="" title="method_missing" width="518" height="156" class="aligncenter size-full wp-image-4559" /></a></p>
<p>Por exemplo, uma feature muito utilizada pelos códigos escritos em Ruby é o <em>method missing</em>. Talvez apareça até em excesso em alguns projetos,  sendo o caso mais conhecido o próprio <a href="http://www.caelum.com.br/curso/rr-71-ruby-on-rails/"> Rails</a>, principalmente para escrever DSLs.  Um desses usos é poder buscar por todas as propriedades das classes de modelo. Normalmente teríamos que criar métodos como <code>buscaPorNome</code>, <code>buscaPorEmail </code>ou combinações destes para atingir esse objetivo. Só que no framework ganhamos métodos prontos como <code>Pessoa.findByNome</code> ou <code>Pessoa.findByEmail</code>. O ponto é que esses métodos não existem na classe, mas o Rails permite que a invocação seja realizada e, caso o método não exista, será invocado o  <code>method_missing(nomeDoMetodoInvocado,argumentosPassados) </code>. Dessa forma conseguimos ganhar esses comportamentos já prontos.</p>
<p>Scala, a partir da versão 2.9, possui um recurso com o mesmo objetivo do <code>method_missing</code>. Para exemplificar vamos utilizar uma agenda de contatos. Queremos que nossa agenda seja capaz de buscar contatos através de algumas propriedades da nossa classe. Uma implementação inicial seria como a que segue:</p>
<pre class="brush: scala; title: ; notranslate">
   class AgendaPadrao {
     def findByNome(nome:String) = {
       // implementacao padrao
     }

     def findByEmail(email:String) = {
       // implementacao padrao
     }

   }
</pre>
<p>Aqui caímos no problema mencionado acima, caso queiramos adicionar novas buscas precisamos adicionar novos métodos. Uma outra possibilidade seria recorrer ao paradigma funcional, para receber o critério de busca como parâmetro, já que o Scala também suporta essa abordagem. Porém, a ideia é tentar resolver da mesma forma que o Rails, queremos dar a possibilidade de alguém conseguir invocar na nossa agenda métodos como: <code>findByNome</code>, <code>findByEmail</code> ou qualquer outra. O primeiro passo a fazer é herdar de uma <a href="http://www.scala-lang.org/node/126">trait</a> chamada <a href="http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/scala/Dynamic.html">Dynamic</a>. É uma trait apenas de marcação, assim como <code>Serializable</code> no Java. Em seguida implementamos um método <code>applyDynamic</code>. O código é o que segue:</p>
<pre class="brush: scala; title: ; notranslate">
   class Agenda extends Dynamic {
       def applyDynamic(fakeMethodName: String)(args: Any*) = {
           &quot;metodo %s com parametros %s&quot;.format(fakeMethodName,args)
       }
   }
</pre>
<p>Agora já podemos chamar qualquer método na nossa classe, existindo ou não. Vamos realizar a implementação usando o padrão <code>findByPropriedade</code>. Vamos usar um pouco de expressões regulares para conseguir identificar a propriedade que está sendo usada para realizar a busca. Também precisaremos de reflection para invocar o método que retorna o valor da propriedade na nossa classe:</p>
<pre class="brush: scala; title: ; notranslate">
   class Agenda extends Dynamic {
       def applyDynamic(fakeMethodName: String)(args: Any*) = {
          val FindBy = &quot;&quot;&quot;(findBy)(\w+)&quot;&quot;&quot;.r
          val found = fakeMethodName match {
              case Like(_, property) =&gt; {
               val realMethodName = lowerFirstLetter(property)
               contatos.filter(c =&gt; invokeMethod[String](c,realMethodNAme).(c,realMethodName).startsWith(args(0).toString))
              }
          }
          found
      }
   }
</pre>
<p>Ainda podemos evoluir nossa implementação de method missing para suportar mais buscas. O exemplo completo do código pode ser encontrado <a href="https://gist.github.com/1176751">aqui</a>. Usamos uma implementação baseada em listas, mas a mesma poderia ser levada para dentro de um <em>DAO </em>permitindo buscas diretamente no banco de dados. Importante notar que precisamos tratar o caso que nenhum padrão for encontrado, para dar feedback para quem fez a invocação informando que aquele método não existe. Nesse caso  lançamos uma exception. Um outro ponto a ser observado é a perda da checagem em tempo de compilação, agora só descobrimos que um método não existe quando rodamos o programa, explicitando mais ainda a importância dos testes de unidade.</p>
<p>E vocês, o que acham dessa feature? O que acham dessa aproximação do estaticamente tipado ao dinâmico?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.caelum.com.br/o-recurso-de-method-missing-em-scala/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mirror DSL: facilitando o uso da API de reflection</title>
		<link>http://blog.caelum.com.br/mirror-dsl-facilitando-o-uso-da-api-de-reflection/</link>
		<comments>http://blog.caelum.com.br/mirror-dsl-facilitando-o-uso-da-api-de-reflection/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 15:25:32 +0000</pubDate>
		<dc:creator>Jonas Abreu</dc:creator>
				<category><![CDATA[Inovação]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[dsl]]></category>
		<category><![CDATA[mirror]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[vidageek]]></category>

		<guid isPermaLink="false">http://blog.caelum.com.br/?p=426</guid>
		<description><![CDATA[No último domingo foi feito o primeiro release público do projeto Mirror (versão 1.2). O Mirror é um projeto que tem por objetivo facilitar o uso da Java Reflection API, removendo boa parte da burocracia (como as diversas checked exceptions que são lançadas) e utilizando uma DSL para melhorar a legibilidade do código. Com essa <a href="http://blog.caelum.com.br/mirror-dsl-facilitando-o-uso-da-api-de-reflection/#more-426'" class="more-link">more &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>No último domingo foi feito o primeiro release público do projeto Mirror (versão 1.2).</p>
<p>O <a href="http://projetos.vidageek.net/mirror/" target="_blank">Mirror</a> é um projeto que tem por objetivo facilitar o uso da <a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/package-summary.html" target="_blank">Java Reflection API</a>, removendo boa parte da burocracia (como as diversas checked exceptions que são lançadas) e utilizando uma <a href="http://en.wikipedia.org/wiki/Domain-specific_language" target="_blank">DSL</a> para melhorar a legibilidade do código.</p>
<p>Com essa remoção de burocracia e a DSL, é possível transformar o seguinte código:</p>
<pre class="brush: java; title: ; notranslate">
Field toSet = null;
for (Field f : target.getClass().getDeclaredFields()) {
    if (f.getName().equals(&quot;field&quot;)) {
        toSet = f;
    }
}
if (toSet != null &amp;&amp; ((toSet.getModifiers() &amp; Modifier.STATIC) == 0)
        &amp;&amp; ((toSet.getModifiers() &amp; Modifier.FINAL) == 0)) {
    toSet.setAccessible(true);
    toSet.set(target, value);
}
</pre>
<p>em algo mais legível e expressivo: </p>
<pre class="brush: java; title: ; notranslate">
Mirror.on(target).set().field(&quot;fieldName&quot;).withValue(value);
</pre>
<p>Atualmente o Mirror possui suporte para lidar com as operações reflectivas mais comuns (como instanciar objetos, invocar métodos, ler ou escrever atributos, etc). Ele foi desenvolvido por Adriano Almeida, Diego Feitosa e eu, todos consultores/instrutores aqui da Caelum, enquanto enfretavamos problemas comuns no dia a dia.</p>
<p>Esperamos que possa ser útil para vocês também!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.caelum.com.br/mirror-dsl-facilitando-o-uso-da-api-de-reflection/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Novo Treinamento FJ-16: Laboratório Java com Swing, XML e Testes</title>
		<link>http://blog.caelum.com.br/novo-treinamento-fj-16-laboratorio-java-swing-xml-testes/</link>
		<comments>http://blog.caelum.com.br/novo-treinamento-fj-16-laboratorio-java-swing-xml-testes/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 06:01:47 +0000</pubDate>
		<dc:creator>Sérgio Lopes</dc:creator>
				<category><![CDATA[Caelum]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[graficos]]></category>
		<category><![CDATA[jfreechart]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[log4j]]></category>
		<category><![CDATA[refatoração]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[swing]]></category>
		<category><![CDATA[testes]]></category>
		<category><![CDATA[treinamentos]]></category>
		<category><![CDATA[unit test]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://blog.caelum.com.br/?p=254</guid>
		<description><![CDATA[Depois de aprender bem o Java, uma pergunta comum de alunos e de usuários do GUJ é: como adquirir experiência e boas práticas? Com esse intuito criamos um novo treinamento, onde desenvolvemos uma aplicação desktop com Swing, que faz análise técnica da bolsa de valores, através de gráficos, usando como fonte uma base XML. É <a href="http://blog.caelum.com.br/novo-treinamento-fj-16-laboratorio-java-swing-xml-testes/#more-254'" class="more-link">more &#187;</a>]]></description>
			<content:encoded><![CDATA[<p style="float:right; margin:0 0 10px 15px; width:240px;">
		<img src="http://www.caelum.com.br/imagens/cursos/fj16-icon.jpg" width="240" />
		</p><p><img src="http://www.caelum.com.br/imagens/cursos/fj16-icon.jpg" alt="FJ-16 Laboratório Swing" align="left"/>Depois de aprender bem o Java, uma pergunta comum de alunos e de usuários do GUJ é: <strong>como adquirir experiência e boas práticas</strong>? Com esse intuito criamos um <a href="http://www.caelum.com.br/curso/fj-16-laboratorio-java-testes-xml-design-patterns/">novo treinamento</a>, onde desenvolvemos uma aplicação desktop com Swing, que faz análise técnica da bolsa de valores, através de gráficos, usando como fonte uma base XML. É o <a href="http://www.caelum.com.br/curso/fj-16-laboratorio-java-testes-xml-design-patterns/"><strong>FJ-16: Laboratório Java com Swing, XML e Testes</strong></a>.</p>
<p><center><img src="http://farm4.static.flickr.com/3206/2763062024_a9e5e695aa.jpg" width="420"  alt="FJ16" /></center></p>
<p>O mais interessante é que, durante o desenvolvimento da aplicação, aprendemos a aplicar diversos <strong>design patterns</strong> (como o Decorator entre indicadores), utilizamos <strong>testes</strong> unitários com JUnit, conhecemos as ferramentas <strong>Ant</strong> e <strong>Maven</strong>,  aplicamos <strong>reflection</strong> e <strong>anotações</strong>, além de sempre estar <strong>refatorando </strong>o código inúmeras vezes.</p>
<p>Nesse treinamento, são colocados em prática também diversos conceitos da linguagem que usamos no dia-a-dia, como manipulação de <strong>datas</strong>, de <strong>XML</strong>, classes anônimas, classes internas, uso do <strong>log4J</strong>, entre outros.</p>
<p>Veja a ementa completa na <a href="http://www.caelum.com.br/curso/fj-16-laboratorio-java-testes-xml-design-patterns/">página do treinamento</a>. Temos turmas agendadas para final de agosto e começo de setembro. Entre em <a href="http://www.caelum.com.br/contato">contato</a> conosco para mais informações.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.caelum.com.br/novo-treinamento-fj-16-laboratorio-java-swing-xml-testes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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>

