Quando comecei a aprender Java, era muito difícil entender o que era reflexão.
Alguns livros, mesmo os mais clássicos, explicam as coisas de uma forma que deixa as pessoas confusas. Talvez eu seja muito estúpido.
Além disso, diz-se online que o mecanismo de reflexão precisa ser usado com frequência ao aprender frameworks no futuro, o que sempre deixa as pessoas um pouco desconfortáveis.
Acabei de assistir acidentalmente alguns capítulos e vídeos explicando a reflexão e acho que posso entender um pouco melhor.
Agora decidi trabalhar muito, ler e escrever ao mesmo tempo, e registrar aqui alguns conteúdos e operações principais.
Acho que, para uma pessoa estúpida como eu, talvez a melhor maneira de aprender seja repetindo
Quando encontro algo que não entendo, paro e aprendo tudo de novo. Embora desperdice muito tempo, também tem algum efeito sobre mim.
Meu entendimento é: a chamada reflexão serve para restaurar as informações completas da classe com base em um objeto já instanciado.
Pelo menos para mim, acho que o benefício que isso traz é que me permite entender a orientação a objetos de baixo para cima.
x_x Aqui eu odeio aquelas cabeças grossas de novo, elas mataram todas as minhas células cerebrais.
Classe classeSe você quiser completar a reflexão, você deve entender a classe Class
Exemplo 1: Obtenha o nome do pacote e o nome da classe por meio do objetoteste de classe {
}
demonstração de classe pública {
public static void main(String[] args) {
Teste t = novo Teste();
System.out.println(t.getClass());
System.out.println(t.getClass().getName());
}
}
Os resultados da compilação são os seguintes, basta prestar atenção em como o pacote é compilado.
O método getClass() aqui é herdado da classe Object por padrão.
Em Java, a classe Object é a classe pai de todas as classes. Da mesma forma, os objetos instanciados de todas as classes também são instâncias da classe Class.
Portanto, isso envolverá os conceitos de transformação ascendente e transformação descendente
Os genéricos também seguirão aqui devido à insegurança dos lançamentos descendentes.
(Mas o que eu quero dizer é que o design genérico aqui é muito deslumbrante! Droga, o design da sintaxe de todo o Java também é deslumbrante, super nojento!!!)
Exemplo 2: Instanciação da classe ClassComo a classe Class não tem construtor, a maneira de instanciar a classe Class é um pouco especial. Existem três maneiras:
Object.getClass()}
demonstração de classe pública {
public static void main(String[] args) {
//Método 1:
Teste t = novo Teste();
Classe<? estende Teste> c1 = t.getClass();
System.out.println(c1);
//Método 2:
//Para evitar especificidade, a classe Test não é usada aqui, mas a classe String na biblioteca java é usada.
Classe<String> c2 = String.class;
System.out.println(c2);
//Método 3:
//o método forName() lançará uma exceção
Classe<?> c3 = nulo;
tentar {
c3 = Class.forName("Teste");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c3);
}
}
Existe um método na classe Class chamado newInstance(), que pode ser usado para criar uma nova instância do objeto da classe Class
Como dizer isso? O conteúdo contido no objeto Class é a classe refletida. Precisamos construir uma nova instância (novo objeto) dessa classe.
Exemplo 3: Construindo objeto sem parâmetros da classe Class //Gera uma referência para uma string
String s = nulo;
tentar {
//Downcast do objeto construído para a classe String
//método newInstance() lançará exceção
s = (String) c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("Comprimento da string: " + s.length());
}
}
Isto constrói um novo objeto em uma forma sem parâmetros, assim como no modo normal
Construir um novo objeto através do construtor sem argumentos é o mesmo que
Sabemos que além dos construtores sem parâmetros, também existem construtores parametrizados em uma classe.
Então, como construir objetos na forma de parâmetros em reflexão? Continue lendo
Exemplo 4: Objeto construído parametrizado da classe Class demonstração de classe pública {
//Os métodos a seguir lançam muitas exceções Por uma questão de compactação do código, eles são lançados diretamente na máquina virtual aqui.
public static void main(String[] args) lança exceção {
Classe<?> c = nulo;
tentar {
c = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
char[] ch = {'h','e','l','l','o'};
String s = nulo;
//Obtém o construtor parametrizado do objeto Class. Os parâmetros entre colchetes são escritos como: type.class.
Construtor<?> con = c.getConstructor(char[].class);
//Use este método de construção para construir um novo objeto string, o parâmetro é um array char
s = (String) con.newInstance(ch);
System.out.println("String construída: " + s);
}
}
Ainda usamos a classe String como exemplo, porque a classe String é usada com mais frequência e é mais fácil de entender.
O que precisa ser observado aqui é que o construtor precisa ser obtido usando o método getConstructor()
Quanto ao tipo de parâmetro, é: original type.class
Outro ponto é que tendo ou não parâmetros, o método de construção aqui utilizado deve existir na classe original.
Então, como podemos saber informações detalhadas, como método construtor, método comum, classe pai herdada e assim por diante na classe original? Continue lendo
Obtenha a estrutura da classePara obter a estrutura de uma classe através da reflexão, precisamos importar um novo pacote java.lang.reflect
Exemplo 5: Obtenha o construtor de uma classe demonstração de classe pública {
//Os métodos a seguir lançam muitas exceções Por uma questão de compactação do código, eles são lançados diretamente na máquina virtual aqui.
public static void main(String[] args) lança exceção {
Classe<?> c = nulo;
tentar {
c = Class.forName("java.lang.Boolean");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//O método getConstructors() aqui retorna um array Construtor
Construtor<?>[] cons = c.getConstructors();
//Você mesmo pode escrever o método de impressão. Por conveniência, eu uso Arrays.toString() para fazer isso.
System.out.println(Arrays.toString(cons));
}
}
demonstração de classe pública {
public static void main(String[] args) lança exceção {
Classe<?> c = nulo;
tentar {
c = Class.forName("java.lang.Boolean");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Classe<?>[] in = c.getInterfaces();
System.out.println(Arrays.toString(in));
}
}
demonstração de classe pública {
public static void main(String[] args) lança exceção {
Classe<?> c = nulo;
tentar {
c = Class.forName("java.lang.Boolean");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Método[] m = c.getMethods();
//Ok, desta vez serei misericordioso e escreverei uma lista de impressão.
for (int i = 0; i < m.comprimento; i++) {
System.out.println(m[i]);
}
}
}
classe Pessoa {
nome da string privada;
idade interna privada;
}
demonstração de classe pública {
public static void main(String[] args) lança exceção {
Classe<?> c = nulo;
tentar {
c = Class.forName("Pessoa");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Campo[] f = c.getDeclaredFields();
for (int i = 0; i < f.length; i++) {
System.out.println(f[i]);
}
}
}
O método getDeclaredFielsd() pode obter todas as propriedades e getFields() só pode obter propriedades públicas.
Exemplo 10: Obtenha o valor do atributo nesta classe classe Pessoa {
nome da string pública;
idade interna privada;
public Person(String nome, int idade) {
este.nome = nome;
esta.idade = idade;
}
}
demonstração de classe pública {
public static void main(String[] args) lança exceção {
Pessoa p = new Pessoa("zhangsan",12);
Classe<?> c = p.getClass();
//Obtém o valor do atributo público
Campo f1 = c.getField("nome");
//get(p) indica qual valor do objeto deve ser obtido
String str = (String) f1.get(p);
System.out.println("Nome: " + str);
//Obtém o valor do atributo privado
Campo f2 = c.getDeclaredField("idade");
//idade é uma propriedade privada, então defina a verificação de segurança como verdadeira
f2.setAccessible(verdadeiro);
int idade = (int) f2.get(p);
System.out.println("Idade: " + idade);
}
}
Falando francamente, não encontrei nenhum conhecimento em Java que possa cegar meus olhos de titânio.
Toda vez, tenho que escrever um monte de sintaxe tediosa para implementar um gadget, ou então tenho que chamar a API desesperadamente e lançar exceções desesperadamente.
Faça com que o código que não é compacto o suficiente se torne complicado
Se gosto de uma linguagem, suas próprias características devem me impressionar antes que eu possa usá-la para fazer alguma coisa.
Obviamente, Java não me deixa feliz. Talvez muitos programadores como eu sejam forçados a usar Java.
Apenas para apaziguar meu coração solitário de codificação, leia abaixo
Exemplo de aplicação de reflexão 11: modificar atributos por meio de reflexão classe Pessoa {
nome da string privada;
pessoa pública (nome da string) {
este.nome = nome;
}
string pública paraString() {
return "Nome: " + this.name;
}
}
demonstração de classe pública {
public static void main(String[] args) lança exceção {
Pessoa p = new Pessoa("王二狗");
System.out.println(p);
Classe<?> c = p.getClass();
//Define as propriedades a serem modificadas
Campo f = c.getDeclaredField("nome");
f.setAccessible(verdadeiro);
//Modifica as propriedades e passa o objeto e o valor a ser definido
f.set(p, "Zhang Erdan");
System.out.println(p);
}
}
classe Pessoa {
impressão pública void(int i) {
System.out.println("Estou escrevendo números: " + i);
}
public static void dizer(String str) {
System.out.println("Estou dizendo: " + str);
}
}
demonstração de classe pública {
public static void main(String[] args) lança exceção {
Pessoa p = new Pessoa();
Classe<?> c = p.getClass();
//O método getMethod() precisa passar o nome do método e o tipo de parâmetro
Método m1 = c.getMethod("print", int.class);
//invoke() significa chamar e precisa passar objetos e parâmetros
m1.invoke(p, 10);
Método m2 = c.getMethod("dizer", String.class);
//O nulo aqui significa não chamado pelo objeto, ou seja, um método estático
m2.invoke(null, "sua irmã");
}
}
Aqui está uma demonstração de um método parametrizado normal e um método estático
Agora que todos os parâmetros estão escritos, aqueles sem parâmetros são ainda mais simples. Basta passar um objeto diretamente.
Exemplo 13: Manipulação de matrizes por meio de reflexão demonstração de classe pública {
public static void main(String[] args) lança exceção {
int[] arr = {1,2,3,4,5};
Classe<?> c = arr.getClass().getComponentType();
System.out.println("Tipo de array: " + c.getName());
int len = Array.getLength(arr);
System.out.println("Comprimento da matriz: " + len);
System.out.print("Percorrer o array: ");
for (int i = 0; i < len; i++) {
System.out.print(Array.get(arr, i) + " ");
}
System.out.println();
//modifica matriz
System.out.println("O primeiro elemento antes da modificação: " + Array.get(arr, 0));
Array.set(arr, 0, 3);
System.out.println("O primeiro elemento modificado: " + Array.get(arr, 0));
}
}
Por enquanto, isso é tudo. O livro que li também inclui a aplicação da reflexão no modo de fábrica.
Nada mais é do que substituí-lo pelo método forName().
Sou iniciante em Java e odeio a sintaxe e o design nojentos do Java.
Isso tudo é para o Android, para estabelecer as bases e se adaptar ao trabalho futuro.