O que é reflexão
"A reflexão permite que os programas em execução na JVM detectem e modifiquem o comportamento do tempo de execução". Esse conceito é frequentemente confundido com a introspecção. Aqui estão as explicações desses dois termos na Wikipedia:
Exemplo de introspecção: a instância do operador é usada para detectar se um objeto pertence a uma classe específica.
if (obj instanceof Dog) {cão d = (cão) obj; D.Bark ();}Exemplo de reflexão: o método Class.ForName () pode obter o objeto de classe correspondente através do nome da classe ou interface (uma string ou nome totalmente qualificado). O método forname aciona a inicialização da classe.
// Use a classe de reflexão <?> C = classe.ForName ("ClassPath.and.ClassName"); Objeto Dog = C.NewInstance (); Método M = C.getDecLaredMethod ("Bark", nova classe <?> [0]); M.Voke (Dog);Em Java, a reflexão está mais próxima da introspecção porque você não pode alterar a estrutura de um objeto. Embora algumas APIs possam ser usadas para modificar a visibilidade de métodos e propriedades, elas não podem modificar estruturas.
Reflexo de matrizes
Qual é o uso da reflexão de uma matriz? Quando você precisa usar o reflexo das matrizes? Vamos dar uma olhada no seguinte código:
Número inteiro [] nums = {1, 2, 3, 4}; Objeto [] objs = nums; // pode ser convertido automaticamente em inteiro [] para objetar [] objeto obj = nums; // Inteiro [] é obviamente um objeto int [] ids = {1, 2, 3, 4}; // objeto [] objs2 = ids; // o int [] não pode ser convertido para objeto [] objeto obj2 = ids; // int [] é um objetoO exemplo acima mostra que um tipo básico de matriz unidimensional só pode ser considerado como um objeto, não como um objeto [].
int [] [] intarray = {{1, 2}, {3, 4}}; Objeto [] OA = INTARRAY; Objeto obj = intarray; // Integer [] [] integerRArray = IntRarray; int [] [] não inteiro [] [] Integer [] [] integerRaRray2 = new Integer [] [] {{1, 2}, {3, 4}}; Objeto [] [] OA2 = integerRArray2; Objeto [] OA3 = integerRArray2; Objeto obj2 = integerRArray2;A partir do exemplo acima, podemos ver que a variedade de dois dígitos de Java é uma variedade de matrizes. Vamos dar uma olhada no exemplo de refletir uma matriz:
pacote cn.zq.array.reflect; importar java.lang.reflect.array; importar java.util.arrays; importar java.util.random; classe pública ArrayReflect {public static void main (string [] args) {aleather rand = novo aleatório (47); int [] is = new int [10]; for (int i = 0; i <is.length; i ++) {é [i] = rand.nextint (100); } System.out.println (IS); System.out.println (Arrays.asList (IS)); /*As duas saídas acima são strings semelhantes a "[[i@14318bb]", que não podem exibir o conteúdo armazenado na matriz. Obviamente, usamos o Traversal para produzir o conteúdo na matriz*/ System.out.println ("-1. Traversal da matriz imprimindo-"); for (int i = 0; i <is.length; i ++) {System.out.print (é [i]+""); } System.out.println (); System.out.println ("-2. Traversal para a matriz por impressão-"); Objeto obj = is; // converte a matriz int-dimensional para objeto system.out.println ("obj isarray:" + obj.getclass (). Isarray ()); for (int i = 0; i <array.getLength (obj); i ++) {int num = array.getInt (obj, i); // Você também pode usar esse método comumente usado para obter o valor da posição de índice correspondente // Valor do objeto = Array.get (obj, i); // Se a matriz armazena o tipo básico, o tipo de invólucro correspondente ao sistema de tipo básico.out.print (num + ""); }}}Saída:
[I@14318bb [[i@14318bb] - -1. Imprima a matriz atravessando a matriz por meios convencionais-58 55 93 61 61 29 68 0 22 7 --2. Imprima a matriz atravessando a matriz atravessando a matriz atravessando o Array- Obj Isarray: True 58 55 93 61 61 29 68 0 22 7
O exemplo acima primeiro cria uma matriz unidimensional de int e depois preenche aleatoriamente um número inteiro de 0 ~ 100. Em seguida, produza diretamente a matriz através do método System.out.println () ou use o método Arrays.asList (se não for uma matriz unidimensional de tipos básicos, esse método pode ser convertido para listar como esperado e, se for uma matriz bidimensional, não pode ser convertida para listar como esperamos). A matriz é convertida para listar e depois a saída, e a passagem não é o resultado da saída que esperamos. Em seguida, o conteúdo da matriz são emitidos em um método de travessia de matriz regular e, em seguida, trata int [] como um objeto e use a reflexão para atravessar seu conteúdo. Class.esArray () pode ser usado para determinar se um objeto é uma matriz. Se for uma matriz, as informações relevantes da matriz são obtidas através do java.lang.reflect.array, uma classe de ferramentas que reflete a matriz. Esta classe usa alguns métodos GET para obter o comprimento da matriz, cada versão usada para obter o índice correspondente da matriz unidimensional de tipos básicos, um método geral para obter o valor (matriz de objetos, índice int), um método para definir o valor e dois métodos para criar instâncias de matriz. Através da classe de ferramentas de reflexão da matriz, é fácil usar a reflexão da matriz para escrever código geral sem ter que julgar qual tipo básico de matriz é a matriz fornecida.
pacote cn.zq.array.reflect; importar java.lang.reflect.array; classe pública newArrayInstance {public static void main (string [] args) {objeto o = array.newInstance (int.class, 20); int [] is = (int []) o; System.out.println ("is.length =" + is.length); Objeto o2 = array.newInstance (int.class, 10, 8); int [] [] ISS = (int [] []) O2; System.out.println ("ISS.Length =" + ISS.Length + ", ISS [0] .LENGHT =" + ISS [0] .Length); }} is.length = 20 ISS.Length = 10, ISS [0] .LENGHT = 8 Array passou 2 métodos para criar uma matriz
Objeto NewInstance (classe <?> ComponentType, Int Length), crie uma matriz de comprimento especificado com base na classe fornecida. Se a int.class for fornecida como acima, o comprimento é 10, o que é equivalente a novo int [10];
Objeto NewInstance (classe <?> ComponentType, int ... dimensões), cria uma matriz com base na classe e dimensões fornecidas. As dimensões do parâmetro variável são usadas para especificar o comprimento de cada dimensão da matriz. Como no exemplo acima, é equivalente à criação de uma matriz bidimensional de novo int [10] [8], mas não pode criar uma matriz multidimensional com diferentes comprimentos de cada dimensão. Através do primeiro método de criar uma matriz, você pode criar uma matriz como essa. Objeto O = Array.NewInstance (int []. Classe, 20) pode ser usado para criar uma matriz bidimensional, que é equivalente a objeto O = new int [20] [];
Obviamente, é raro usar o exemplo acima para criar uma matriz, mas é realmente redundante. Por que não criar uma matriz diretamente através do novo? A reflexão cria uma matriz não apenas mais rápida que a nova, mas também o programa escrito não é fácil de ler, por isso não é tão direto quanto novo. De fato, é realmente raro criar matrizes através da reflexão. Que tipo de necessidades anormais existem para usar a reflexão para criar matrizes!
Como alguns obstáculos foram encontrados ao emitir uma variedade de tipos básicos, o seguinte usará a reflexão da matriz para implementar uma classe de ferramentas para obter a saída desejada:
pacote cn.zq.util; importar java.io.byteArrayOutputStream; importar java.io.printstream; importar java.lang.reflect.array; public class Print {public static void print (object obj) {print (obj, system.out); } public static void print (object obj, printStream Out) {out.println (getPrintString (obj)); } public static void println () {print (System.out); } public static void println (printStream out) {out.println (); } public static void printnb (object obj) {printnb (obj, system.out); } public static void printnb (object obj, printStream Out) {out.print (getPrintString (obj)); } public static PrintStream Format (formato de string, objeto ... objetos) {retornar formato (System.out, formato, objetos); } public static PrintStream Format (PrintStream Out, String Format, Object ... Objects) {Object [] handleObjects = new Object [Objects.Length]; for (int i = 0; i <objetos.length; i ++) {objeto objeto = objetos [i]; if (object == null || isPrimitiveWrapper (object)) {handleObjects [i] = object; } else {byteArrayOutputStream bos = new ByteArrayOutputStream (); PrintStream ps = new PrintStream (BOS); printnb (objeto, ps); ps.close (); handleObjects [i] = new String (bos.tobytearray ()); }} out.format (formato, handleObjects); retornar; } /*** Determine se um determinado objeto é uma classe de invólucro do tipo básico. * @param o Objeto dado o objeto * @return Se for uma classe de wrapper de tipos primitivos, retorne sim, caso contrário, retorne nº */ private estático booleano isPrimitiveWrapper (objeto o) {return o Instância do void || o Instância de booleano || o Instância do caractere || o Instância de byte || o Instância de curta || o Instância de número inteiro || o Instância de longa || o Instância de flutuar || o Instância do dobro; } public static string getPrintString (object obj) {stringbuilder resultado = new StringBuilder (); if (obj! = null && obj.getclass (). isarray ()) {resultado.append ("["); int len = array.getLength (obj); for (int i = 0; i <len; i ++) {objeto value = array.get (obj, i); resultado.Append (getPrintString (valor)); if (i! = len - 1) {resultado.append (","); }} resultado.append ("]"); } else {resultado.append (string.valueof (obj)); } return result.toString (); }}A classe de ferramenta de impressão acima fornece alguns métodos estáticos práticos para saída e fornece algumas versões sobrecarregadas. Você pode escrever algumas versões sobrecarregadas com base em suas preferências pessoais, apoiando a impressão de tipos básicos de matrizes unidimensionais e matrizes multidimensionais. Veja os seguintes exemplos do teste da ferramenta de impressão:
pacote cn.zq.array.reflect; importar estático cn.zq.util.print.print; importar java.io.printstream; importar estático cn.zq.util.print.*; classe pública PrintTest {STATTIC Class Person {private Static int contat; private final int id = contador ++; public string tostring () {return getClass (). getSImpleName () + id; }} public static void main (string [] args) lança exceção {print ("-imprimir não-arraia--"); print (novo objeto ()); print ("-Imprima a matriz unidimensional de tipos básicos-"); int [] is = new int [] {1, 22, 31, 44, 21, 33, 65}; impressão (é); print ("-Imprima matriz bidimensional de tipos básicos-"); int [] [] ISS = new int [] [] {{11, 12, 13, 14}, {21, 22,}, {31, 32, 33}}; impressão (ISS); imprimir ("-Imprima uma matriz unidimensional de tipos não bastos--"); Pessoa [] pessoas = nova pessoa [10]; for (int i = 0; i <PERSONS.LENGLE; I ++) {PESSONS [i] = new Person (); } impressão (pessoas); impressão (pessoas); imprimir ("-Imprima uma matriz bidimensional de tipos não primitivos-"); Pessoa [] [] pessoas2 = nova pessoa [] [] {{new Person ()}, {nova pessoa (), new Person ()}, {new Person (), New Pessoa (), New Pessoa (), New Pessoa (),},}; impressão (pessoas2); imprimir ("-imprima uma matriz vazia--"); print (new int [] {}); print ("-Imprima uma matriz com valores nulos--"); Objeto [] objetos = new Object [] {new Person (), null, new Object (), New Integer (100)}; impressão (objetos); print ("-Imprima matriz bidimensional para casos especiais-"); Objeto [] [] objeto2 = novo objeto [3] []; objetos2 [0] = novo objeto [] {}; objetos2 [2] = objetos; impressão (objetos2); print ("-Saia o resultado da matriz unidimensional para o arquivo-"); PrintStream Out = new PrintStream ("out.c"); tente {print (iss, out); } finalmente {out.close (); } print ("-Format Output-"); formato (" %-6d %s %b %s", 10086, "é", verdadeiro, ISS); /** * Alguns métodos comumente usados das classes de ferramentas impressos estão listados acima, * Existem também alguns métodos não listados, verifique você mesmo. */}} Saída:
--Print non-array -- java.lang.Object@61de33 --Print one-dimensional array of basic types -- [1, 22, 31, 44, 21, 33, 65] --Print two-dimensional array of basic types -- [[11, 12, 13, 14], [21, 22], [31, 32, 33]] --Print one-dimensional array of non-base type -- [Person0, Person1, Person2, Pessoa3, Person4, Person5, Person6, Person7, Person8, Pessoa9]-Impressa Bidimensional Matriz de Tipo Não-Base-[[Person10], [Person11, Pessoa12], [Pessoa13, Pessoa14, Person15]-Print ARAY-[]-PRIRANG com NULL-[ -Print Bidimensional Array em casos especiais-[[], null, [Person16, null, java.lang.object@ca0b6, 100]]-Impressa o resultado da matriz unidimensional em um arquivo--saída de formato-10086 é verdadeira [11, 13, 13, 14], [21, 22],
Arquivo de saída:
Pode-se observar que a classe de ferramentas de impressão já tem a capacidade de imprimir tipos básicos de matrizes unidimensionais e matrizes multidimensionais. De um modo geral, a classe de ferramentas acima é bastante prática, para não escrever um código manualmente toda vez que você deseja ver o conteúdo da matriz. Isso seria muito problemático. Basta usar a classe de ferramentas de impressão no futuro. Quão conveniente.
A classe de ferramentas acima funciona muito bem, mas se houver um requisito: forneça uma matriz (e talvez outros contêineres), você pode criar uma lista para mim. Então, o que devemos fazer? De fato, Arrays.asList nem sempre obtém os resultados que esperamos. Embora o Java5 adicione genéricos, ele tem limitações e não pode ser tão geral quanto os modelos C ++. É precisamente porque existem tipos básicos em Java. Mesmo que haja um mecanismo de embalagem automático, ele não pode ser usado com genéricos. O tipo de parâmetro deve ser de um determinado tipo, não um tipo básico. Aqui está uma solução para a sua própria:
pacote cn.zq.util; importar java.lang.reflect.array; importar java.util.arraylist; importar java.util.arrays; importar java.util.enumeration; importar java.util.iterator; importar java.util.list; importar java.util.map; public class collectionUtils {public static list <?> aslist (object obj) {return converttolist (MakeIterator (obj)); } public static <t> list <t> converttolist (iterator <t> iterator) {if (iterator == null) {return null; } List <t> list = new ArrayList <T> (); while (iterator.hasnext ()) {list.add (iterator.Next ()); } Lista de retorno; } @Suppresswarnings ({"RawTypes", "desmarcado"}) public static iterator <?> MakeIterator (object obj) {if (obj instância de iterator) {return (iterator <?>) Obj; } if (obj == null) {return null; } if (obj instanceof map) {obj = ((map <?,?>) obj) .EntrySet (); } Iterator <?> Iterator = null; if (obj instância de iterable) {iterator = ((iterable <?>) obj) .iterator (); } else if (obj.getclass (). isarray ()) {// objeto [] objs = (objeto []) obj; // ou matrizes de tipos primitivos não podem ser convertidos como esta lista ArrayList = new ArrayList (Array.getLength (obj)); for (int i = 0; i <array.getLength (obj); i ++) {list.add (array.get (obj, i)); } iterator = list.iterator (); } else if (obj instanceof enumeração) {iterator = new Enumationiterator ((enumeração) obj); } else {iterator = arrays.aslist (obj) .iterator (); } retornar iterador; } Classe estática pública Enumeração <t> implementa o iterador <t> {enumeração privada <t> enumeração; public EnumationIterator (enumeração <t> enumeração) {this.enumeration = enumeração; } public boolean hasNext () {return enumeração.hasmoreElements (); } public t next () {return enumeração.nextElement (); } public void REMOT () {THROW NEW UNSUPPORTEDOPERATIONECCECCECTION (); }}}Código de teste:
pacote cn.zq.array.reflect; importar java.util.iterator; importar java.util.list; importar cn.zq.array.reflect.printtest.person; importar cn.zq.util.CollectionUtils; public class collectionutilstest {public static void main (string [] args) {System.out.println ("--- Matriz básica do tipo um dimensional--"); int [] nums = {1, 3, 5, 7, 9}; List <?> List = collectionUtils.asList (nums); System.out.println (list); System.out.println ("-não básico do tipo um-dimensional-"); Pessoa [] pessoas = nova pessoa [] {new Pessoa (), nova pessoa (), nova pessoa (),}; List <Pesso> PersonList = (List <Pesso>) collectionUtils.asList (Pessoas); System.out.println (PersonList); System.out.println (PersonList); System.out.println ("-iterator--"); Iterator <SOYS> iterator = PERSONLIST.IITERATOR (); List <Pesso> PersonList2 = (List <Soper>) collectilutils.asList (iterator); System.out.println (PERSOLLIST2); }}Saída:
-Array Basic Tipo One-Dimensional-- [1, 3, 5, 7, 9]-Non-Basic Tipo One-Dimensional Matriz-- [Pessoa0, Person1, Person2] --Iterator-- [Person0, Person1, Person2]
Na biblioteca de classes de contêineres Java, ela pode ser dividida em coleta, mapa e matriz. Como o iterador (e a enumeração inicial da interface legado) é a interface geral de todos os contêineres e a interface de coleta é da Iterable (o iterador dessa interface retornará um iterador), essas situações são processadas uma a uma no método MakeIterator. Para tipos de mapa, apenas o método de entrada () precisa ser chamado. Para classes que implementam a interface iterável (incluindo a coleta), ligue para o iterator () para obter diretamente o objeto iterador. Para tipos de enumeração, use o adaptador enumeração para adaptação. Para matrizes, use a reflexão da matriz para atravessar a matriz na ArrayList e ligue para o método Arrays.asList () para criar uma lista para outros tipos. A Coleção também fornece alguns outros métodos para converter e você pode adicionar os métodos necessários conforme necessário.
Resumo: A reflexão da matriz fornece métodos mais convenientes e flexíveis para projetos onde as matrizes podem aparecer, para não escrever declarações de julgamento mais problemáticas. Essa flexibilidade paga o preço do desempenho, e realmente não é necessário usar a reflexão da matriz quando a reflexão da matriz não é necessária. O uso de reflexões da matriz é diferente no desenvolvimento real. Escolha se deseja usar as reflexões da matriz de acordo com as necessidades. A melhor maneira é explorar o caminho através da prática, escrever da maneira que você pensa e melhorar constantemente na prática.