(1). Tipos de interface relacionados à reflexão + genéricos.
java.lang.reflect.Type: interface pai comum para todos os tipos na linguagem java
java.lang.reflect.ParameterizedType
java.lang.reflect.GenericArrayType
java.lang.reflect.WildcardType
1. Digite subinterface direta
Quatro tipos de interfaces: ParameterizedType, GenericArrayType, TypeVariable e WildcardType
ParameterizedType: representa um tipo parametrizado, como Collection
GenericArrayType: representa um tipo de array cujo tipo de elemento é um tipo parametrizado ou variável de tipo
TypeVariable: é a interface pai comum para vários tipos de variáveis
WildcardType: representa uma expressão do tipo curinga, como ?, ? estende Número, ? super Inteiro [curinga é uma palavra: é "curinga"]
2. O tipo implementa subclasses diretamente: Classe classe
3. Interface java.lang.reflect.Type
Todos os tipos de Type referem-se a: tipos brutos (tipos brutos) [correspondentes a Class], tipos parametrizados (tipos parametrizados) [correspondentes a ParameterizedType], tipos de array (tipos de array) [correspondentes a GenericArrayType], variáveis de tipo (variáveis de tipo) [ correspondente a TypeVariable ], tipos de dados básicos (primitivetypes) [ainda correspondendo a Class]
4. Interface java.lang.reflect.ParameterizedType
O significado do tipo de interface ParameterizedType
Representa um tipo parametrizado. Por exemplo: um tipo parametrizado como Map
Obtenha o tipo real no tipo parametrizado<>
Instrução do código-fonte: Type[] getActualTypeArguments();
[Nota] Não importa quantos níveis de aninhamento <> existam em <>, este método remove apenas o <> mais externo e o conteúdo restante é usado como o valor de retorno deste método.
método E estático público IV (
ArrayList> al1,
ArrayList al2,
ArrayList al3,
ArrayListextends Número> al4,
ArrayList al5){}
Então cada um de seus parâmetros é geralmente do tipo paramétrico.
{1}. Para ArrayList>, após retornar por meio de getActualTypeArguments(), após remover o <> mais externo, o tipo restante é ArrayList. Portanto, o tipo de retorno para este parâmetro é ParameterizedType.
{2} Para ArrayList, após retornar por meio de getActualTypeArguments(), após remover o <> mais externo, o tipo restante é E. Portanto, o tipo de retorno para este parâmetro é TypeVariable.
{3} Para ArrayList, após retornar por meio de getActualTypeArguments(), após remover o <> mais externo, o tipo restante é String. Portanto o tipo de retorno para este parâmetro é Classe.
{4}. Para ArrayListextends Number>, após retornar por meio de getActualTypeArguments(), após remover o <> mais externo, o tipo restante é? Portanto, o tipo de retorno para este parâmetro é WildcardType.
{5}. Para ArrayList, após retornar por meio de getActualTypeArguments(), após remover o <> mais externo, o tipo restante é E[]. Portanto, o tipo de retorno para este parâmetro é GenericArrayType.
Portanto, é possível obter parâmetros reais de vários tipos, portanto, para fins de unificação, o array de classe pai direto Type[] é usado para recepção.
4. Interface java.lang.reflect.GenericArrayType
O significado do tipo de interface GenericArrayType
Representa um tipo de matriz genérico. Por exemplo: método void(ArrayList[] al){…}
[Nota] <> não pode aparecer na inicialização do array, ou seja, <> não pode aparecer após o novo array, caso contrário o javac não passará. Mas é perfeitamente adequado como variável de referência ou parâmetro de um método.
Obtenha o tipo de elementos em uma matriz genérica
Declaração do código-fonte: Digite getGenericComponentType();
[Nota] Não importa quantos [] estejam justapostos da esquerda para a direita, este método remove apenas o [] mais à direita e o conteúdo restante é usado como o valor de retorno deste método.
Por que o tipo de valor de retorno é Type?
método E estático públicoV(String[] p1,E[] p2,ArrayList[] p3,E[][] p4){}{1}. Para String[], após retornar por getComponentType(), após remover o [] mais à direita, o tipo restante é String. Portanto o tipo de retorno para este parâmetro é Class
{2}. Para E[], após retornar por getComponentType(), após remover o [] mais à direita, o tipo restante é E. Portanto o tipo de retorno para este parâmetro é TypeVariable
{3}. Para ArrayList[], após retornar por getComponentType(), após remover o [] mais à direita, o tipo restante é ArrayList. Portanto, o tipo de retorno para este parâmetro é ParameterizedType
{4} Para E[][], após retornar por getComponentType(), após remover o [] mais à direita, o tipo restante é E[]. Portanto, o tipo de retorno para este parâmetro é GenericArrayType
5. Interface java.lang.reflect.GenericArrayType
O significado do tipo de interface TypeVariable
Representa parâmetros de tipo ou também chamados de variáveis de tipo. Por exemplo: E in void method(E e){} é a variável de tipo
Obtém o tipo do limite superior qualificado genérico de uma variável de tipo
Instrução do código-fonte: Type[] getActualTypeArguments();
[Nota] Este é apenas o limite superior. A razão é que variáveis de tipo só podem usar extensões para limitar (múltiplos) limites quando são definidas. Super não pode ser usado, caso contrário a compilação não será aprovada. Ao mesmo tempo, extends fornece o limite superior das variáveis de tipo.
Por que o tipo de retorno é um array? Como as variáveis de tipo podem ser qualificadas com vários limites superiores por &, existem vários limites superiores, portanto, o tipo de valor de retorno é o tipo de matriz [].
Por exemplo o seguinte método:
public static estende Map& Cloneable&Serializable> E métodoVI(E e){…}O primeiro limite superior de E é Map, que é um tipo ParameterizedType
O segundo limite superior de E é Cloneable, que é do tipo Class
Portanto, para unificação, o tipo de elemento da matriz de valores de retorno é Tipo
6. Interface java.lang.reflect.WildcardType
O significado do tipo de interface WildcardType
Uma expressão que representa um tipo curinga.
Por exemplo, void printColl(ArrayListal);
[Nota] De acordo com os comentários da API acima: neste estágio, a expressão curinga aceita apenas um limite superior ou inferior. Isso é diferente de quando se define uma variável de tipo, que pode especificar vários limites superiores. Mas a API disse que, para manter a escalabilidade, o tipo de valor de retorno aqui é escrito em formato de array. Na verdade, o tamanho do array retornado agora é 1
Obtém o tipo do limite superior qualificado genérico de um objeto de expressão curinga
Instrução do código-fonte: Type[] getUpperBounds();
[Nota] Conforme mencionado acima, o tamanho do array em Type[] retornado neste estágio é 1. Escrito como Type[ ] é uma extensão para atualização de idioma.
Por exemplo o seguinte método:
{1}. public static voidprintColl(ArrayListextends ArrayList> al){}
A expressão curinga é: ? extendsArrayList, de modo que estende é seguido pelo limite superior de ?, e esse limite superior é o tipo ParameterizedType.
{2}. public static voidprintColl(ArrayListextends E> al){}
A expressão curinga é: ? estende E, de modo que estende é seguido pelo limite superior de ?, e esse limite superior é do tipo TypeVariable
{3}.public static voidprintColl(ArrayListextends E[]> al){}
A expressão curinga é: ? estende E[], de modo que estende é seguido pelo limite superior de ?, e esse limite superior é do tipo GenericArrayType
{4}.public static voidprintColl(ArrayListextends Number> al){}
A expressão curinga é: ? estende Número, de modo que estende é seguido pelo limite superior de ?, e esse limite superior é o tipo Classe.
Finalmente unificado em Type como o tipo de elemento do array.
7. A origem do Type e suas subinterfaces
1. Tipos antes do surgimento dos genéricos
Quando não há genéricos, existem apenas os chamados tipos primitivos. Neste momento, todos os tipos primitivos são abstraídos por meio da classe de arquivo de bytecode Classe Class. Um objeto concreto da classe Class representa um tipo primitivo especificado.
2. Tipos após o surgimento dos genéricos
Após o surgimento dos genéricos, os tipos de dados foram expandidos. De apenas tipos primitivos, tipos parametrizados, tipos de variáveis de tipo, tipos parametrizados qualificados genéricos (incluindo curingas + expressões qualificadas para curingas) e tipos de matriz genéricos foram expandidos.
3. A razão pela qual os tipos relacionados aos genéricos não podem ser unificados com os tipos originais na classe
[1]. [Causa do apagamento genérico]
Originalmente, os tipos recém-gerados + tipos primitivos deveriam ser unificados em seus respectivos objetos de tipo de arquivo de bytecode. Mas como os genéricos não eram originalmente um ingrediente do Java. Se genéricos forem realmente adicionados, isso envolverá a modificação do conjunto de instruções da JVM, o que é muito fatal.
[2]. [Como introduzir genéricos em Java]
Para aproveitar os genéricos sem realmente introduzi-los, Java usa um mecanismo de apagamento genérico para introduzir genéricos. Genéricos em Java são usados apenas pelo compilador javac para garantir a segurança dos dados e evitar o problema de conversão forçada de tipo. No entanto, uma vez concluída a compilação, todos os tipos relacionados aos genéricos são apagados.
[3].[A classe não pode expressar tipos relacionados a genéricos]
Portanto, tipos parametrizados relacionados a genéricos, tipos de variáveis de tipo, tipos parametrizados qualificados genéricos (incluindo curingas + expressões qualificadas para curingas) e tipos de matriz genéricos são todos retornados aos seus formatos originais e armazenados no arquivo de bytecode. depois que os genéricos foram apagados e não há nenhum arquivo de bytecode consistente com seu próprio tipo. Portanto, os tipos recentemente expandidos relacionados aos genéricos não podem ser unificados na classe Class.
(4). Representação de tipos relacionados a genéricos em Java.
Para operar esses tipos por meio de reflexão para atender às necessidades de desenvolvimento real, Java adicionou ParameterizedType, GenericArrayType, TypeVariable e WildcardType para representar tipos que não podem ser classificados na classe Class, mas têm o mesmo nome do tipo original.
(5). Introdução de Tipo: unificando tipos relacionados a genéricos e tipos primitivos Classe.
[Motivo para introduzir o Tipo]
Para a escalabilidade do programa, a interface Type foi finalmente introduzida como a interface pai geral para Class, ParameterizedType, GenericArrayType, TypeVariable e WildcardType. Desta forma, o parâmetro de tipo Type aceita os parâmetros reais dos cinco subtipos acima ou o tipo de valor de retorno é o parâmetro de tipo Type.
[A razão pela qual não existe método na interface Type]
Como pode ser visto acima, o surgimento do Tipo desempenha apenas o papel de melhorar a escalabilidade do programa por meio do polimorfismo e não tem outro efeito. Portanto, não há métodos no código-fonte da interface Type.