Explicação detalhada da reflexão de Java
Este artigo ainda usa pequenos exemplos para ilustrar, porque sempre sinto que o caso é o melhor; caso contrário, se você apenas ler a teoria, não a entenderá depois de lê-la. No entanto, é recomendável que você olhe para a teoria depois de ler o artigo e ter uma melhor compreensão.
O texto principal começa abaixo.
[Caso 1] Obtenha o pacote completo e o nome da classe através de um objeto
pacote reflete; /*** Obtenha o nome completo do pacote e o nome da classe através de um objeto**/classe Demo {// outros códigos ...} classe Hello {public static void main (string [] args) {Demo demo = new Demo (); System.out.println (Demo.getClass (). GetName ()); }}【Resultado em execução】: reflete.Demo
Adicione uma frase: todos os objetos das classes são na verdade instâncias de classe.
【Caso 2】 Objeto de classe instanciada
pacote reflete; classe Demo {// outros códigos ...} classe Hello {public static void main (string [] args) {class <?> Demo1 = null; Classe <?> Demo2 = null; Classe <?> Demo3 = null; tente {// geralmente tente usar este formulário Demo1 = Class.ForName ("Reflice.Demo"); } catch (Exceção e) {e.printStackTrace (); } Demo2 = new Demo (). getClass (); Demo3 = Demo.class; System.out.println ("Nome da classe"+Demo1.getName ()); System.out.println ("Nome da classe"+Demo2.getName ()); System.out.println ("Nome da classe"+Demo3.getName ()); }}【Resultados da operação】:
Classe namereflect.demo
Classe namereflect.demo
Classe namereflect.demo
[Caso 3] Instanciar objetos de outras classes através da aula
Objetos instantados construindo não parâmetros
pacote reflete; classe Pessoa {public string getName () {retorna nome; } public void setName (nome da string) {this.name = name; } public int getage () {Age de retorno; } public void setage (int Age) {this.age = Age; } @Override public string tostring () {return "["+this.name+""+this.age+"]"; } nome de string privado; private Int Age; } classe Hello {public static void main (string [] args) {class <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } Pessoa por = nulo; tente {per = (pessoa) Demo.newInstance (); } catch (instantiationException e) {// TODO BLOCO DE CAPAGEM AUTOMENTADO E.PRINTSTACKTRACE (); } catch (ilegalAccessException e) {// TODO BLOCO DE CATAGEM AUTOGERATO E.PRINTSTACKTRACE (); } per.setName ("rollen"); per.setage (20); System.out.println (PER); }}【Resultados da operação】:
[Rollen 20]
Mas observe que, quando cancelamos o construtor padrão sem parâmetros pessoalmente, por exemplo, depois de definirmos apenas um construtor com parâmetros, ocorrerá um erro:
Por exemplo, eu defini um construtor:
Pessoa pública (nome da string, Int Age) {this.age = Age; this.name = nome; }Em seguida, continue executando o programa acima, e ele aparecerá:
java.lang.InstantiationException: reflete.person
em java.lang.class.newinstance0 (classe.java:340)
em java.lang.class.newinstance (classe.java:308)
em reflete.hello.main (hello.java:39)
Exceção no thread "Main" java.lang.nullpointerException
em reflete.hello.main (hello.java:47)
Portanto, quando você escreve objetos que usam classe para instanciar outras classes, você deve definir seu próprio construtor sem parâmetros.
[Case] CHAMADOS Construtores em outras classes através da classe (você também pode criar objetos de outras classes através da classe dessa maneira)
pacote reflete; importar java.lang.reflect.Constructor; classe PERSON {public Person () {} public Person (Nome da String) {this.name = Name; } pessoa pública (Int Age) {this.age = Age; } pessoa pública (nome da string, Int Age) {this.age = Age; this.name = nome; } public string getName () {return name; } public int getage () {Age de retorno; } @Override public string tostring () {return "["+this.name+""+this.age+"]"; } nome de string privado; private Int Age;} classe Hello {public static void main (string [] args) {classe <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } Pessoa per1 = nulo; Pessoa per2 = nulo; Pessoa per3 = nulo; Pessoa per4 = nulo; // obtenha todos os construtores construtores <?> Contras [] = Demo.getConstructors (); tente {per1 = (pessoa) contras [0] .NewInstance (); per2 = (pessoa) contras [1] .NewInstance ("rollen"); per3 = (pessoa) contras [2] .NewInstance (20); per4 = (pessoa) contras [3] .NewInstance ("rollen", 20); } catch (Exceção e) {e.printStackTrace (); } System.out.println (PER1); System.out.println (PER2); System.out.println (PER3); System.out.println (PER4); }}【Resultados da operação】:
[NULL 0]
[Rollen 0]
[NULL 20]
[Rollen 20]
【Caso】
Retorna a interface implementada por uma classe:
pacote reflete; Interface China {public static final string name = "rollen"; public static int idade = 20; public void dizchina (); public void SayHello (nome da string, INT AGE);} classe Pessoa implementa a China {public Person () {} public pessoa (sexo de string) {this.sex = sexo; } public string getSex () {return Sex; } public void SetSex (sexo de string) {this.sex = sexo; } @Override public void Saychina () {System.out.println ("Hello, China"); } @Override public void SayHello (nome da string, Int Age) {System.out.println (Nome+""+Age); } sexo privado de string;} classe hello {public static void main (string [] args) {classe <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } // Salvar todas as interfaces classe <?> INTES [] = Demo.getInterfaces (); for (int i = 0; i <aTes.Length; i ++) {System.out.println ("Interface implementada"+INTES [i] .getName ()); }}}【Resultados da operação】:
Interface implementada refletir.china
(Observe que os exemplos a seguir usarão a classe Pessoa deste exemplo; portanto, para salvar o espaço, não coletaremos mais a parte do código da pessoa aqui, apenas o código da classe principal olá)
【Caso】: Obtenha a classe pai em outras classes
classe Hello {public static void main (string [] args) {class <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } // Obtenha a classe pai <?> Temp = Demo.getSuperclass (); System.out.println ("A classe pai herdada é:"+temp.getName ()); }}【Resultados de execução】
A classe pai herdada é: java.lang.object
【Caso】: Obtenha todos os construtores em outras classes
Este exemplo requer a adição de importação java.lang.reflect.* No início do programa;
Em seguida, escreva a classe principal como:
classe Hello {public static void main (string [] args) {class <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } Construtor <?> CONS [] = Demo.getConstructors (); for (int i = 0; i <cont.Length; i ++) {System.out.println ("Construtor:"+Cons [i]); }}}【Resultados da operação】:
Método de construção: public reflet.Person ()
Construtor: Public Reflice.person (java.lang.string)
Mas os leitores cuidadosos descobrirão que o construtor acima não possui modificadores como público ou privado
Vamos obter o modificador no exemplo seguinte
classe Hello {public static void main (string [] args) {class <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } Construtor <?> CONS [] = Demo.getConstructors (); for (int i = 0; i <cont.Length; i ++) {classe <?> p [] = contras [i] .getParameterTypes (); System.out.print ("Construtor:"); int mo = contras [i] .getModifiers (); System.out.print (modifier.toString (MO)+""); System.out.print (contras [i] .getName ()); System.out.print ("("); para (int j = 0; j <p.Length; ++ j) {System.out.print (p [j] .getName ()+"arg"+i); if (j <p.Println) {System.out.print (",");}} System.out.println ("); }}【Resultados da operação】:
Construtor: public reflet.person () {}
Construtor: public reflet.person (java.lang.string arg1) {}
Às vezes, pode haver exceções em um método, haha. Vamos dar uma olhada:
classe Hello {public static void main (string [] args) {class <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } Método método [] = Demo.getMethods (); for (int i = 0; i <métod.Length; ++ i) {classe <?> returnType = método [i] .getReturntype (); Classe <?> Para [] = método [i] .getParameterTypes (); int temp = método [i] .getModifiers (); System.out.print (modifier.toString (temp)+""); System.out.print (returnType.getName ()+""); System.out.print (método [i] .getName ()+""); System.out.print ("("); para (int j = 0; j <para.length; ++ j) {System.out.print (para [j] .getName ()+""+"arg"+j); if (j <para.le.length-1) {System.out.print ("");}}}} if (Exce.Length> 0) {System.out.print (") lança"); for (int k = 0; k <exce.length; ++ k) {System.out.print (Exce [k] .getName ()+""); if (k <exce.length-1) {System.out.print (","); }}} else {System.out.print (")"); } System.out.println (); }}}【Resultados da operação】:
public java.lang.string getSex ()
public void Setsex (java.lang.string arg0)
Public Void Saychina ()
public void dizhello (java.lang.string arg0, int arg1)
Public Final Native Void Wait (Long Arg0) lança java.lang.interruptedException
Public Final Void Wait () lança java.lang.interruptedException
Public Final Void Wait (Long Arg0, int arg1) lança java.lang.interruptedException
Public boolean é igual (java.lang.Object arg0)
public java.lang.string tostring ()
public nativo int hashcode ()
Final público nativo java.lang.class getClass ()
Public Final Native Void Notify ()
Public Final Native Void NotifyAll ()
[Case] Em seguida, vamos obter todas as propriedades de outras classes. Finalmente, vou resolvê -los juntos, isto é, para obter toda a estrutura de uma aula através da aula
classe Hello {public static void main (string [] args) {class <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } System.out.println("=========================================================================================== =============================================================================================================== =============================================================================================================== ======================================================= doc Modificador de permissão Int MO = Campo [i] .getModifiers (); System.out.println("====================================================================================== =========================================================================================================== ========================================================================================================== =========================================================================================================== arquivado1 = Demo.getFields (); for (int j = 0; j <filed1.length; j ++) {// Modificador de permissão int mo = filed1 [j] .getModifiers (); String priv = modifier.toString (MO); // classe de tipo de propriedade <?> Type = filed1 [j] .gettype (); System.out.println (priv + "" + type.getName () + "" + filed1 [j] .getName () + ";"); }}}【Resultados da operação】:
===================================================
private java.lang.string sexo;
===========================================================
Public Static final java.lang.string Nome;
Idade final estática pública;
[Caso] De fato, métodos em outras classes também podem ser chamados por meio de reflexão:
classe Hello {public static void main (string [] args) {class <?> Demo = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } tente {// chamando o método Saychina no método da classe Pessoa Método = Demo.getMethod ("Saychina"); Method.inVoke (Demo.NewInstance ()); // chamando o método Sayhello da pessoa = Demo.getMethod ("Sayhello", String.class, int.class); Method.inVoke (Demo.NewInstance (), "Rollen", 20); } catch (Exceção e) {e.printStackTrace (); }}}【Resultados da operação】:
Olá, China
Rollen 20
【Caso】 Conjunto de chamadas e métodos de outras classes
classe Hello {public static void main (string [] args) {class <?> Demo = null; Objeto obj = null; tente {Demo = Class.ForName ("Reflice.Person"); } catch (Exceção e) {e.printStackTrace (); } tente {obj = Demo.newInstance (); } catch (Exceção e) {e.printStackTrace (); } setter (obj, "sexo", "masculino", string.class); getter (obj, "sexo"); } / ** * @param obj * objeto de operação * @param att * atributos da operação * * / public static void getter (object obj, string att) {try {método método = obj.getclass (). getMethod ("get" + att); System.out.println (Method.inVoke (OBJ)); } catch (Exceção e) {e.printStackTrace (); }} / ** * @param obj * objeto da operação * @param att * atributos da operação * @param value * set valor * @param tipo * atributos do parâmetro * * / public static void setter (object obj, string att, valor do objeto, classe <?> type) {try {métod method = obj.get, (string att, string, get, get, get). método.invoke (obj, valor); } catch (Exceção e) {e.printStackTrace (); }}} // Classe final【Resultados da operação】:
macho
【Caso】 Operação por reflexão
classe Hello {public static void main (string [] args) lança exceção {class <?> Demo = null; Objeto obj = null; Demo = Class.ForName ("Reflice.Person"); obj = Demo.NewInstance (); Campo de campo = Demo.getDecLaredfield ("sexo"); field.setAccessible (true); field.set (obj, "masculino"); System.out.println (field.get (obj)); }} // Classe final[Caso] Obtenha e modifique as informações da matriz através da reflexão:
importar java.lang.reflect.*; classe hello {public static void main (string [] args) {int [] temp = {1,2,3,4,5}; Classe <?> Demo = temp.getClass (). GetComponentType (); System.out.println ("Tipo de matriz:"+Demo.getName ()); System.out.println ("comprimento da matriz"+array.getLength (temp)); System.out.println ("Primeiro elemento da matriz:"+Array.get (temp, 0)); Array.set (temp, 0, 100); System.out.println ("Após modificar o primeiro elemento da matriz é:"+Array.get (temp, 0)); }}【Resultados da operação】:
Tipo de matriz: int
Comprimento da matriz 5
O primeiro elemento da matriz: 1
Após a modificação, o primeiro elemento da matriz é: 100
【Caso】 Modifique o tamanho da matriz através da reflexão
classe hello {public static void main (string [] args) {int [] temp = {1,2,3,4,5,6,7,8,9}; int [] newTemp = (int []) Arrayinc (temp, 15); impressão (newtemp); System.out.println ("============================================================================================================================================================================================================ ============================================================================================================= dúvida String []) Arrayinc (ATR, 8); System.arraycopy (Obj, 0, Newarr, 0, CO); Array.getLength (obj);【Resultados da operação】:
O comprimento da matriz é: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 ===========================================
O comprimento da matriz é: 8
ABC nulo nulo nulo nulo nulo
Agente dinâmico
[Case] Primeiro, vamos dar uma olhada em como obter o carregador de classe:
classe teste {} classe Hello {public static void main (string [] args) {test t = new test (); System.out.println ("ClassLoader"+t.getclass (). GetClassLoader (). GetClass (). GetName ()); }}【Saída do programa】:
Classe carregador sol.misc.launcher $ appClassLoader
De fato, existem três tipos de carregadeiras de classe em Java.
1) Larota de classe de bootstrap Este carregador é escrito em C ++ e raramente é visto no desenvolvimento geral.
2) O carregador de classe de extensão é usado para carregar classes estendidas, geralmente correspondendo às classes no diretório JRE/LIB/EXT
3) O AppClassLoader carrega a classe especificado pelo ClassPath e é o carregador mais comumente usado. É também o carregador padrão em Java.
Se você deseja concluir um proxy dinâmico, primeiro precisará definir uma subclasse da interface InvocationHandler e a operação específica do proxy foi concluída.
pacote reflete; importar java.lang.reflect.*; // Defina o assunto da interface do projeto {public string diz (nome da string, int age);} // Defina a classe real da classe realSubject implementa o assunto {@Override public string diz (nome da string, int ad) {Nome de retorno + "" + Age; }} classe myInvocationHandler implementa InvocationHandler {objeto privado obj = null; public Object bind (objeto obj) {this.obj = obj; return proxy.newproxyInstance (obj.getclass (). getClassLoader (), obj .getclass (). getInterfaces (), isto); } @Override Public Object Invoke (proxy do objeto, método do método, objeto [] args) lança arremesso {objeto temp = métod.invoke (this.obj, args); retornar temp; }} classe hello {public static void main (string [] args) {myInvocationHandler Demo = new MyInvocationHandler (); Assunto sub = (sujeito) Demo.bind (novo realSubject ()); String info = sub.say ("rollen", 20); System.out.println (info); }}【Resultados da operação】:
Rollen 20
O ciclo de vida de uma classe
Depois que uma aula é compilada, a próxima etapa é começar a usar a classe. Se você deseja usar uma classe, é definitivamente inseparável da JVM. Durante a execução do programa, a JVM é concluída nessas três etapas: carregando, vinculação e inicialização.
O carregamento de classe é feito através de um carregador de classe. O carregador carrega o arquivo binário do arquivo .class na área do método JVM e cria um objeto java.lang.class descrevendo esta classe na área de heap. Usado para encapsular dados. Mas a mesma classe só será carregada pelo carregador de classe antes
Os links são para montar dados binários em um estado que possa ser executado.
O link é dividido em três estágios: verificação, preparação e análise
A verificação é geralmente usada para confirmar se esse arquivo binário é adequado para a JVM atual (versão).
A preparação é para alocar espaço de memória para membros estáticos. e defina valores padrão
Parsing refere -se ao processo de conversão do código no pool constante como referência direta até que todas as referências simbólicas possam ser usadas pelo programa de corrida (estabeleça uma correspondência completa)
Após a conclusão, o tipo é inicializado. Após a inicialização, o objeto da classe pode ser usado normalmente. Depois que um objeto não for mais usado, ele será coletado de lixo. Livre espaço.
Quando nenhuma referência aponta para o objeto de classe, ele será desinstalado, encerrando o ciclo de vida da classe
Use reflexão para o modo de fábrica
Vamos dar uma olhada no modo de fábrica se você não precisar de reflexão:
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html
/ *** @author rollen-holt Modo de padrão de design*/ interface frut {public abstract void eat ();} classe Apple implementa frutas {public void eat () {System.out.println ("Apple"); }} classe laranja implementa a fruta {public void Eat () {System.out.println ("Orange"); }} // Construa a classe de fábrica //, em outras palavras, se precisarmos apenas modificar a classe de fábrica ao adicionar outras instâncias na futura classe de fábrica {public static frutinStance (string fruitname) {fruit f = null; if ("Apple" .Equals (FruitName)) {f = new Apple (); } if ("laranja" .equals (fruitname)) {f = new Orange (); } retornar f; }} classe hello {public static void main (string [] a) {fruit f = factory.getInstance ("laranja"); façanha(); }}Dessa forma, quando adicionamos uma subclasse, precisamos modificar a classe de fábrica. Se adicionarmos muitas subclasses, mudaremos muito.
Agora vamos dar uma olhada no mecanismo de reflexão utilizando:
pacote reflete; Interface Fruit {public abstrate void eat ();} classe Apple implementa frutas {public void eat () {System.out.println ("Apple"); }} classe laranja implementa a fruta {public void Eat () {System.out.println ("Orange"); }} classe fábrica {public static fruit getInstance (string className) {fruit f = null; tente {f = (fruit) class.ForName (ClassName) .NewInstance (); } catch (Exceção e) {e.printStackTrace (); } retornar f; }} classe hello {public static void main (string [] a) {fruit f = factory.getInstance ("reflete.apple"); if (f! = null) {f.eat (); }}}Agora, mesmo se adicionarmos tantas subclasses, a classe de fábrica não precisa ser modificada.
Embora o amor acima possa obter uma instância da interface através da reflexão, ele precisa passar no pacote completo e no nome da classe. Além disso, os usuários não podem saber quantas subclasses podem ser usadas em uma interface; portanto, configuramos as subclasses necessárias na forma de arquivos de atributo.
Vamos dar uma olhada: Modo de fábrica combinando arquivos de atributo
Primeiro, crie um arquivo de recursos de frutas.properties.
O conteúdo é:
Apple = reflete.apple
laranja = reflete.orange
Em seguida, escreva o código de classe principal:
pacote reflete; importar java.io.*; importar java.util.*; Interface Fruit {public abstrate void eat ();} classe Apple implementa frutas {public void eat () {System.out.println ("Apple"); }} classe laranja implementa a fruta {public void Eat () {System.out.println ("Orange"); }} // Operação da classe do arquivo de propriedade init {public static Properties getPro () lança fileNotfoundException, ioexception {Properties pro = new Properties (); Arquivo f = novo arquivo ("fruit.properties"); if (f.Exists ()) {pro.load (new FileInputStream (f)); } else {pro.setProperty ("Apple", "reflet.apple"); pro.setProperty ("laranja", "reflet.orange"); pro.store (new FileOutputStream (f), "classe de frutas"); } retornar pro; }} classe fábrica {public static fruit getInstance (string className) {fruit f = null; tente {f = (fruit) class.ForName (ClassName) .NewInstance (); } catch (Exceção e) {e.printStackTrace (); } retornar f; }} classe hello {public static void main (string [] a) lança fileNotfoundException, ioexception {Properties pro = init.getPro (); fruta f = fábrica.getInstance (pro.getProperty ("Apple")); if (f! = null) {f.eat (); }}}【Run Result】: Apple
O exposto acima é uma explicação detalhada do mecanismo de reflexão Java. Continuaremos a adicionar informações relevantes no futuro. Obrigado pelo seu apoio a este site!