Trabalhando com Métodos usando a Classe Method em Java
A classe Method
, do pacote java.lang.reflect
, representa um método de uma classe ou interface.
Ela fornece meios para inspecionar as definições dos métodos e chamá-los dinamicamente.
Principais métodos:
String getName()
: retorna o nome do método.Class[] getExceptionTypes()
: retorna, como um array de objetosClass
, os tipos de exceções que o método pode lançar.int getModifiers()
: retorna um valor inteiro cujos bits indicam os modificadores aplicados.int getParameterCount()
: retorna a quantidade de parâmetros do método.Class[] getParameterTypes()
: retorna um array de objetosClass
que representa os tipos dos parâmetros.Class getReturnType()
: retorna o tipo de retorno do método.Object invoke(Object obj, Object... args)
: chama o método representado, no objeto especificado, com os argumentos informados.
Obtendo Métodos
A classe Class
oferece métodos para acessar os métodos de uma classe:
Method[] getMethods()
: retorna um array com todos os métodos públicos da classe, incluindo os herdados de superclasses.Method[] getDeclaredMethods()
: retorna um array com todos os métodos definidos na classe, independentemente do modificador de acesso.Method getMethod(String name, Class... parameterTypes)
: retorna um método público com o nome e a lista de tipos de parâmetros especificados; a busca também inclui métodos herdados. Se não existir, lançaNoSuchMethodException
.Method getDeclaredMethod(String name, Class... parameterTypes)
: retorna um método definido na própria classe, independentemente do modificador de acesso. Se não existir, lançaNoSuchMethodException
.
Exemplo: Obtendo Todos os Métodos
import java.lang.reflect.*;
public class Program {
public static void main(String[] args) {
Class<?> cl = Operation.class;
Method[] methods = cl.getDeclaredMethods();
for (Method m : methods) {
System.out.println(m);
}
}
}
class Operation {
static int sum(int val1, int val2) {
return val1 + val2;
}
static double sum(double val1, double val2) {
return val1 + val2;
}
static int subtract(int val1, int val2) {
return val1 - val2;
}
}
Saída:
static int Operation.sum(int,int) static double Operation.sum(double,double) static int Operation.subtract(int,int)
Inspecionando um Método
O exemplo abaixo mostra como obter informações detalhadas sobre o método sum
que recebe dois parâmetros int
:
import java.lang.reflect.*;
public class Program {
public static void main(String[] args) {
Class<?> cl = Operation.class;
try {
// Obtém o método sum com dois parâmetros int
Method m = cl.getDeclaredMethod("sum", int.class, int.class);
String methodName = m.getName();
String modifiers = Modifier.toString(m.getModifiers());
int paramsCount = m.getParameterCount();
Class<?> retType = m.getReturnType();
Class<?>[] paramTypes = m.getParameterTypes();
System.out.print(modifiers + " " + retType.getName() + " " + methodName + "(");
for (int j = 0; j < paramsCount; j++) {
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
} catch (Exception ex) {
System.out.println(ex);
}
}
}
class Operation {
static int sum(int val1, int val2) {
return val1 + val2;
}
static double sum(double val1, double val2) {
return val1 + val2;
}
static int subtract(int val1, int val2) {
return val1 - val2;
}
}
Saída:
static int sum(int, int);
Chamando Métodos com invoke
O método invoke(Object obj, Object... args)
chama dinamicamente o método representado.
O primeiro parâmetro obj
indica o objeto no qual o método será chamado. Para métodos estáticos, esse parâmetro é ignorado e pode ser null
.
O segundo parâmetro args
é um array com os argumentos a serem passados para o método.
O valor de retorno de invoke
é o resultado do método chamado.
Chamando um Método Estático
import java.lang.reflect.*;
public class Program {
public static void main(String[] args) {
Class<?> cl = Operation.class;
try {
Method m = cl.getDeclaredMethod("sum", int.class, int.class);
int val1 = 23;
int val2 = 4;
int result = (int) m.invoke(null, val1, val2);
System.out.printf("sum(%d, %d) = %d%n", val1, val2, result);
} catch (Exception ex) {
System.out.println(ex);
}
}
}
class Operation {
static int sum(int val1, int val2) {
return val1 + val2;
}
static int subtract(int val1, int val2) {
return val1 - val2;
}
}
Saída:
sum(23, 4) = 27
Chamando um Método de Instância
import java.lang.reflect.*;
public class Program {
public static void main(String[] args) {
Person tom = new Person("Tom");
Class<?> cl = tom.getClass();
try {
Method m = cl.getDeclaredMethod("setName", String.class);
String name = "Programício";
m.invoke(tom, name);
tom.print(); // Person Programício
} catch (Exception ex) {
System.out.println(ex);
}
}
}
class Person {
private String name;
void setName(String name) { this.name = name; }
Person(String name) { this.name = name; }
void print() {
System.out.println("Person " + name);
}
}
Saída:
Person Programício
Acessando Métodos Privados
Por padrão, não é possível acessar métodos privados por reflexão.
Para habilitar o acesso, o método precisa ser tornado acessível com setAccessible(true)
.
import java.lang.reflect.*;
public class Program {
public static void main(String[] args) {
Person tom = new Person("Tom");
Class<?> cl = tom.getClass();
try {
Method m = cl.getDeclaredMethod("setName", String.class);
m.setAccessible(true); // habilita o acesso
String name = "Programício";
m.invoke(tom, name);
tom.print(); // Person Programício
} catch (Exception ex) {
System.out.println(ex);
}
}
}
class Person {
private String name;
private void setName(String name) { this.name = name; }
Person(String name) { this.name = name; }
void print() {
System.out.println("Person " + name);
}
}
Saída:
Resumo
- A classe
Method
fornece acesso às informações e à execução de métodos de uma classe. - Os métodos
getMethods()
egetDeclaredMethods()
listam os métodos públicos ou todos os métodos definidos. - Os métodos
getMethod()
egetDeclaredMethod()
recuperam métodos específicos conforme nome e parâmetros. - Métodos como
getName()
,getReturnType()
,getParameterTypes()
egetModifiers()
permitem inspecionar as características de um método. - O método
invoke()
chama métodos estáticos ou de instância dinamicamente. - Métodos privados podem ser acessados após habilitar o acesso com
setAccessible(true)
.