Java 반사 Java.lang.reflect.Method
35747 단어 Java 반사 시리즈
java.lang.reflect.Field
의 상용 사용 방식과 주의사항을 다루었다.Class의 방법java.lang.reflect.Method
에 대해 살펴보겠습니다.소개하다.
방법은 실행 가능한 코드입니다. 계승된 코드일 수도 있고, 다시 불러오거나, 컴파일러에 의해 강제로 숨겨질 수도 있습니다.그러나 반대로 반사 코드는 방법의 선택을 특정한 클래스에 제한하고 부류를 고려하지 않는다. 비록 우리가 부류를 찾을 수 있지만 이것은 방법의 반사로 할 수 있는 것이 아니기 때문에 여기서 문제를 일으키기 쉽다.
Method 선언 가져오기
방법의 성명은 방법 이름, 설명자, 매개 변수, 되돌아오는 유형, 이상표를 포함한다.클래스
java.lang.reflect.Method
는 이러한 정보를 얻을 수 있는 방법을 제공합니다.1. 획득 방법의 명칭String getName()
2.가져오는 방법의 설명자 int getModifiers()
반환값은 이전 글의 소개를 참고하십시오.3. 반환 방법의 반환값 유형Class> getReturnType()
Type getGenericReturnType
4.반환 방법의 매개 변수(목록)Class>[] getParameterTypes()
Type[] getGenericParameterTypes()
5.되돌아오는 방법의 이상 정보Class>[] getExceptionTypes()
Type[] getGenericExceptionTypes()
는 왜 방법의 매개 변수, 되돌아오는 값 유형과 이상표에 두 가지 방법이 있습니까?Generic가 있는 것은 성명을 되돌려주는 유형이기 때문에 이 성명의 유형이 범형이라도 범형 표지부를 되돌려주고 진정한 유형을 되돌려주지 않기 때문에 지난 글에서 말한 범형 지우개에 대한 설명이 있습니다.말로는 증거가 없으니 예를 들자.public class MethodSpy {
private static final String fmt = "%24s: %s%n";
// for the morbidly curious
void genericThrow() throws E {}
public static void main(String... args) {
try {
Class> c = Class.forName(args[0]);
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
if (!m.getName().equals(args[1])) {
continue;
}
out.format("%s%n", m.toGenericString());
out.format(fmt, "ReturnType", m.getReturnType());
out.format(fmt, "GenericReturnType", m.getGenericReturnType());
Class>[] pType = m.getParameterTypes();
Type[] gpType = m.getGenericParameterTypes();
for (int i = 0; i < pType.length; i++) {
out.format(fmt,"ParameterType", pType[i]);
out.format(fmt,"GenericParameterType", gpType[i]);
}
Class>[] xType = m.getExceptionTypes();
Type[] gxType = m.getGenericExceptionTypes();
for (int i = 0; i < xType.length; i++) {
out.format(fmt,"ExceptionType", xType[i]);
out.format(fmt,"GenericExceptionType", gxType[i]);
}
}
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
}
이 예의 대체적인 의미는 하나의 종류를 입력하고 방법 정보를 얻으려는 방법명을 입력하는 것이다.입력 결과: 1.java.lang.Class의 getConstructor 방법
$ java MethodSpy java.lang.Class getConstructor
public java.lang.reflect.Constructor java.lang.Class.getConstructor
(java.lang.Class>[]) throws java.lang.NoSuchMethodException,
java.lang.SecurityException
ReturnType: class java.lang.reflect.Constructor
GenericReturnType: java.lang.reflect.Constructor
ParameterType: class [Ljava.lang.Class;
GenericParameterType: java.lang.Class>[]
ExceptionType: class java.lang.NoSuchMethodException
GenericExceptionType: class java.lang.NoSuchMethodException
ExceptionType: class java.lang.SecurityException
GenericExceptionType: class java.lang.SecurityException
$ java MethodSpy java.lang.Class cast
public T java.lang.Class.cast(java.lang.Object)
ReturnType: class java.lang.Object
GenericReturnType: T
ParameterType: class java.lang.Object
GenericParameterType: class java.lang.Object
cast 방법의 반환값은 범형이고 표지부호는 'T' 이기 때문에 getGenericReturnType () 방법은 T를 되돌려주고 getReturnType () 은java를 되돌려줍니다.lang.object, 즉 일반 지우기 후의 유형입니다.3. java.io.PrintStream format 방법
$ java MethodSpy java.io.PrintStream format
public java.io.PrintStream java.io.PrintStream.format
(java.util.Locale,java.lang.String,java.lang.Object[])
ReturnType: class java.io.PrintStream
GenericReturnType: class java.io.PrintStream
ParameterType: class java.util.Locale
GenericParameterType: class java.util.Locale
ParameterType: class java.lang.String
GenericParameterType: class java.lang.String
ParameterType: class [Ljava.lang.Object;
GenericParameterType: class [Ljava.lang.Object;
public java.io.PrintStream java.io.PrintStream.format
(java.lang.String,java.lang.Object[])
ReturnType: class java.io.PrintStream
GenericReturnType: class java.io.PrintStream
ParameterType: class java.lang.String
GenericParameterType: class java.lang.String
ParameterType: class [Ljava.lang.Object;
GenericParameterType: class [Ljava.lang.Object;
매개변수 정보 가져오기
우리는 매개 변수의 정보를 얻는 것은 매개 변수가 비교적 특수하기 때문에 안전과 메모리를 고려하기 위해class의 바이트 코드 파일에 매개 변수의 이름을 저장하지 않는다. 예를 들어 일부 매개 변수의 이름, 예를 들어secret이나password 등은 안전 민감 방법과 관련된 정보를 공개할 수 있다. 예를 들어 긴 매개 변수, 그 매개 변수의 이름을 저장하면 메모리가 폭증할 수 있다.물론 우리가 실행할 때 -parameters 파라미터를 추가하면 그 파라미터의 이름을 강제로 저장할 수 있으며 기본적으로 저장하지 않습니다.공식적으로 인쇄 매개 변수의 데모 코드가 있습니다.
public class MethodParameterSpy {
private static final String fmt = "%24s: %s%n";
// for the morbidly curious
void genericThrow() throws E {}
public static void printClassConstructors(Class c) {
Constructor[] allConstructors = c.getConstructors();
out.format(fmt, "Number of constructors", allConstructors.length);
for (Constructor currentConstructor : allConstructors) {
printConstructor(currentConstructor);
}
Constructor[] allDeclConst = c.getDeclaredConstructors();
out.format(fmt, "Number of declared constructors",
allDeclConst.length);
for (Constructor currentDeclConst : allDeclConst) {
printConstructor(currentDeclConst);
}
}
public static void printClassMethods(Class c) {
Method[] allMethods = c.getDeclaredMethods();
out.format(fmt, "Number of methods", allMethods.length);
for (Method m : allMethods) {
printMethod(m);
}
}
public static void printConstructor(Constructor c) {
out.format("%s%n", c.toGenericString());
Parameter[] params = c.getParameters();
out.format(fmt, "Number of parameters", params.length);
for (int i = 0; i < params.length; i++) {
printParameter(params[i]);
}
}
public static void printMethod(Method m) {
out.format("%s%n", m.toGenericString());
out.format(fmt, "Return type", m.getReturnType());
out.format(fmt, "Generic return type", m.getGenericReturnType());
Parameter[] params = m.getParameters();
for (int i = 0; i < params.length; i++) {
printParameter(params[i]);
}
}
public static void printParameter(Parameter p) {
out.format(fmt, "Parameter class", p.getType());
out.format(fmt, "Parameter name", p.getName());
out.format(fmt, "Modifiers", p.getModifiers());
out.format(fmt, "Is implicit?", p.isImplicit());
out.format(fmt, "Is name present?", p.isNamePresent());
out.format(fmt, "Is synthetic?", p.isSynthetic());
}
public static void main(String... args) {
try {
printClassConstructors(Class.forName(args[0]));
printClassMethods(Class.forName(args[0]));
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
}
가져오는 매개 변수는 Parameter입니다. Field와 마찬가지로 getType (): 매개 변수 형식 getName (): 매개 변수 이름. 컴파일러가 매개 변수 -parameters를 추가하면 진정한 매개 변수 이름을 되돌려줍니다. 추가하지 않으면 매개 변수는argN 형식이고 N은 몇 번째 매개 변수입니다.getModifiers (): 매개 변수 식별자, 상세하게 설명하지 않습니다.isImplicit(): 암시적 선언이면 true로 돌아갑니다.예를 들어 내부 클래스는parent 구성원 변수와 구조기를 은밀하게 설명합니다.우리의 코드:
public class MethodParameterExamples {
public class InnerClass { }
}
컴파일러가 실제로 생성한 코드:
public class MethodParameterExamples {
public class InnerClass {
final MethodParameterExamples parent;
InnerClass(final MethodParameterExamples this$0) {
parent = this$0;
}
}
}
isNamePresent (): 이름이 -parameters와 동일할 수 있는지 여부입니다.isSynthetic (): 컴파일러가 생성한 것인지 여부입니다.예를 들어 위의 코드로 다음 유형의 메서드 정보를 얻는 경우
public class ExampleMethods<T> {
public boolean simpleMethod(String stringParam, int intParam) {
System.out.println("String: " + stringParam + ", integer: " + intParam);
return true;
}
public int varArgsMethod(String... manyStrings) {
return manyStrings.length;
}
public boolean methodWithList(List listParam) {
return listParam.isEmpty();
}
public void genericMethod(T[] a, Collection c) {
System.out.println("Length of array: " + a.length);
System.out.println("Size of collection: " + c.size());
}
}
컴파일러 가-parameters의 실행 결과는 다음과 같습니다.
Number of constructors: 1
Constructor #1
public ExampleMethods()
Number of declared constructors: 1
Declared constructor #1
public ExampleMethods()
Number of methods: 4
Method #1
public boolean ExampleMethods.simpleMethod(java.lang.String,int)
Return type: boolean
Generic return type: boolean
Parameter class: class java.lang.String
Parameter name: stringParam
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Parameter class: int
Parameter name: intParam
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Method #2
public int ExampleMethods.varArgsMethod(java.lang.String...)
Return type: int
Generic return type: int
Parameter class: class [Ljava.lang.String;
Parameter name: manyStrings
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Method #3
public boolean ExampleMethods.methodWithList(java.util.List)
Return type: boolean
Generic return type: boolean
Parameter class: interface java.util.List
Parameter name: listParam
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Method #4
public <T> void ExampleMethods.genericMethod(T[],java.util.Collection)
Return type: void
Generic return type: void
Parameter class: class [Ljava.lang.Object;
Parameter name: a
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Parameter class: interface java.util.Collection
Parameter name: c
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
매개변수가 없는 실행 결과:
Number of constructors: 1
public reflect.ExampleMethods()
Number of parameters: 0
Number of declared constructors: 1
public reflect.ExampleMethods()
Number of parameters: 0
Number of methods: 4
public boolean reflect.ExampleMethods.simpleMethod(java.lang.String,int)
Return type: boolean
Generic return type: boolean
Parameter class: class java.lang.String
Parameter name: arg0
Modifiers: 0
Is implicit?: false
Is name present?: false
Is synthetic?: false
Parameter class: int
Parameter name: arg1
Modifiers: 0
Is implicit?: false
Is name present?: false
Is synthetic?: false
public int reflect.ExampleMethods.varArgsMethod(java.lang.String...)
Return type: int
Generic return type: int
Parameter class: class [Ljava.lang.String;
Parameter name: arg0
Modifiers: 0
Is implicit?: false
Is name present?: false
Is synthetic?: false
public boolean reflect.ExampleMethods.methodWithList(java.util.List)
Return type: boolean
Generic return type: boolean
Parameter class: interface java.util.List
Parameter name: arg0
Modifiers: 0
Is implicit?: false
Is name present?: false
Is synthetic?: false
public void reflect.ExampleMethods.genericMethod(T[],java.util.Collection)
Return type: void
Generic return type: void
Parameter class: class [Ljava.lang.Object;
Parameter name: arg0
Modifiers: 0
Is implicit?: false
Is name present?: false
Is synthetic?: false
Parameter class: interface java.util.Collection
Parameter name: arg1
Modifiers: 0
Is implicit?: false
Is name present?: false
Is synthetic?: false
획득 방법의 식별자
int getModifiers
표지부를 얻으려면 여기에 예를 들면 됩니다. 상세한 소개는 하지 않겠습니다.public class MethodModifierSpy {
private static int count;
private static synchronized void inc() { count++; }
private static synchronized int cnt() { return count; }
public static void main(String... args) {
try {
Class> c = Class.forName(args[0]);
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
if (!m.getName().equals(args[1])) {
continue;
}
out.format("%s%n", m.toGenericString());
out.format(" Modifiers: %s%n",
Modifier.toString(m.getModifiers()));
out.format(" [ synthetic=%-5b var_args=%-5b bridge=%-5b ]%n",
m.isSynthetic(), m.isVarArgs(), m.isBridge());
inc();
}
out.format("%d matching overload%s found%n", cnt(),
(cnt() == 1 ? "" : "s"));
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
}
결과 출력:
$ java MethodModifierSpy java.lang.Object wait
public final void java.lang.Object.wait() throws java.lang.InterruptedException
Modifiers: public final
[ synthetic=false var_args=false bridge=false ]
public final void java.lang.Object.wait(long,int)
throws java.lang.InterruptedException
Modifiers: public final
[ synthetic=false var_args=false bridge=false ]
public final native void java.lang.Object.wait(long)
throws java.lang.InterruptedException
Modifiers: public final native
[ synthetic=false var_args=false bridge=false ]
3 matching overloads found
$ java MethodModifierSpy java.lang.StrictMath toRadians
public static double java.lang.StrictMath.toRadians(double)
Modifiers: public static strictfp
[ synthetic=false var_args=false bridge=false ]
1 matching overload found
$ java MethodModifierSpy MethodModifierSpy inc
private synchronized void MethodModifierSpy.inc()
Modifiers: private synchronized
[ synthetic=false var_args=false bridge=false ]
1 matching overload found
$ java MethodModifierSpy java.lang.Class getConstructor
public java.lang.reflect.Constructor java.lang.Class.getConstructor
(java.lang.Class[]) throws java.lang.NoSuchMethodException,
java.lang.SecurityException
Modifiers: public transient
[ synthetic=false var_args=true bridge=false ]
1 matching overload found
$ java MethodModifierSpy java.lang.String compareTo
public int java.lang.String.compareTo(java.lang.String)
Modifiers: public
[ synthetic=false var_args=false bridge=false ]
public int java.lang.String.compareTo(java.lang.Object)
Modifiers: public volatile
[ synthetic=true var_args=false bridge=true ]
2 matching overloads found
실행 방법
반사 실행 방법(Invoking Methods)을 사용하는 것은 매우 간단한 일이다.
public Object invoke(Object obj,
Object... args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
을 호출하면 된다. obj는 방법을 가진Class의 실례이고args는 방법의 매개 변수이다.주의 방법은 Illegal Access Exception, Illegal Argument Exception, Invocation Target Exception 이상을 던질 수 있습니다.반사된 Method 고려 사항