Classe com um campo privado
Todos vocês sabem muito bem sobre modificadores de acesso de campo. E se um campo tiver o modificador privado , não podemos acessá-lo de fora.
public class Person {
private int age;
public String nickname;
public Person(int age, String nickname) {
this.age = age;
this.nickname = nickname;
}
}
Vamos verificar a acessibilidade em nossa classe Main :
public class Main {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.nickname);
// System.out.println(person.age); No access to the field
}
}
Não temos acesso aoidadecampo, mas temos reflexão. :) E com sua ajuda podemos acessar e trabalhar com campos privados.
Obtendo um campo privado de um objeto usando reflexão
Vamos obter um array de todos os campos da nossa classe usando o método getDeclaredFields() . Ele retorna um objeto Field com o qual podemos trabalhar e modificar:
public static void main(String[] args) {
Field[] fields = Person.class.getDeclaredFields();
List<String> actualFieldNames = getFieldNames(fields);
actualFieldNames.forEach(System.out::println);
}
static List<String> getFieldNames(Field[] fields) {
List<String> fieldNames = new ArrayList<>();
for (Field field : fields)
fieldNames.add(Modifier.toString(field.getModifiers()) + " " + field.getName());
return fieldNames;
}
apelido público
No método getFieldNames , obtemos dois campos de nossa classe. O método getModifiers retorna o modificador do nosso campo e getName retorna seu nome. Agora vamos tentar modificar e acessar este campo. Primeiro, vamos tentar obter dados de um campo público:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "CodeGym");
Field field = Person.class.getDeclaredField("nickname");
String nickname = (String) field.get(person);
System.out.println(nickname);
System.out.println(person.nickname);
}
CodeGym
Podemos acessar o campo tanto com a ajuda da reflexão quanto usando nossa referência ao objeto. Tudo é bom! Vamos passar para um campo privado.
Mudaremos o nome do campo solicitado para nosso privadoidadecampo:
public static void main(String[]args)throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "CodeGym");
Field field = Person.class.getDeclaredField("age");
int age =(int)field.get(person);
System.out.println(age);
// System.out.println(person.age);
}
Não temos acesso através do objeto criado, então tente usar a reflexão. Obtemos um erro:
IllegalAccessException
Obtemos um IllegalAccessException . Vamos dar uma olhada no que tem dentro:
Vamos tentar descobrir.
Uma IllegalAccessException é lançada quando um aplicativo tenta criar reflexivamente uma instância (diferente de uma matriz), definir ou obter um campo ou invocar um método, quando o método atualmente em execução não tem acesso à definição da classe, campo, método ou construtor.
Os métodos aqui também lançam essa exceção. Para evitar essa exceção, usaremos um método especial para acessar o campo privado.
setAccessible(sinalizador booleano)
Este método permite evitar verificações de acesso de segurança para um campo ou classe. Podemos passar true ou false para o método para determinar se as verificações de acesso de segurança serão executadas para o campo. Vamos tentar corrigir nosso código:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "CodeGym");
Field field = Person.class.getDeclaredField("age");
field.setAccessible(true);
int age = (int) field.get(person);
System.out.println("The current value is " + age);
}
Vejamos o resultado:
Ótimo! Recebemos informações sobre nossa turma. Vamos também tentar alterar nosso campo atribuindo um novo valor a ele:
public static void main(String[]args)throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "CodeGym");
Field field = Person.class.getDeclaredField("age");
field.setAccessible(true);
field.set(person, 19);
int age =(int)field.get(person);
System.out.println("The current value is " + age);
}
Depois de mudar nosso campo, obtemos:
Vamos tentar chamar setAccessible(false) .
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "CodeGym");
Field field = Person.class.getDeclaredField("age");
field.setAccessible(true);
field.set(person, 19);
field.setAccessible(false);
System.out.println("The current value is " + field.get(person));
}
Depois de restaurar a acessibilidade para false , encontramos nossa exceção novamente quando tentamos chamar o método get :
Portanto, tenha cuidado ao trabalhar com campos privados e não se esqueça de que a reflexão é uma ferramenta muito poderosa!
GO TO FULL VERSION