Java 반사 메커니즘 이해

1. 반사란 무엇인가


반사(Reflection)는 자바 프로그램 개발 언어의 특징 중 하나로 실행 중인 자바 프로그램이 자신의 정보를 얻을 수 있고 클래스나 대상의 내부 속성을 조작할 수 있다.공식적인 설명은 다음과 같다.
Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

간단하게 말하자면 반사를 통해 우리는 실행할 때 인터페이스, 변수, 방법 등 임의의 종류의 바이트 코드를 얻을 수 있다.
자바 반사 메커니즘은 동적 으로 대상을 만들고 속성을 호출할 수 있으며, 이러한 대상의 유형은 컴파일 기간에 알 수 없습니다.그래서 우리는 반사 메커니즘을 통해 대상을 직접 만들 수 있다. 설령 이 대상의 유형이 컴파일링 기간에 알 수 없다 하더라도.
반사의 핵심은 JVM이 실행할 때 클래스나 호출 방법/접근 속성을 동적으로 불러오는 것이다. 실행 대상이 누구인지 미리 알 필요가 없다.

2. 반사 프레임이 제공하는 주요 기능


1. 운행 시 임의의 대상이 속한 클래스를 판단한다.
2. 운행할 때 임의의 종류의 대상을 구성한다.
3. 운행 시 임의의 클래스가 가지고 있는 구성원 변수와 방법을 판단한다
4. 운행 시 접근 대상의 속성, 방법, 구조 방법 등.

3. 반사 메커니즘의 주요 용도


1. 특정 클래스의 변수를 가져오고 특정 클래스의 개인 (private) 방법을 사용합니다.
2. 코드의 유연성을 증가시킨다.많은 주류 프레임워크가 반사 기술을 사용했고 우리가 익숙한spring 등 우수한 소스 오픈 프레임워크는 두 가지 기술인 xml을 이용하여 프로필+반사 실현을 했다.


4. 반사의 기본적 활용


class 대상 가져오기 1. Class 클래스의 forName 정적 방법 사용 String className = ... ;//실행 중 가져오는 클래스 이름 문자열 Class class = Class.forName(className); 2. 어떤 대상의class를 직접 가져오기 Class> classInt = Integer.TYPE; 3. 어떤 대상의 getClass () 방법을 호출한다 StringBuilder str = new StringBuilder("123"); Class> klass = str.getClass(); 세 가지 방식으로 우리가 자주 사용하는 것은 첫 번째, 두 번째는 가져오는 종류의 가방을 필요로 하는데 의존도가 너무 강하기 때문에 가방을 가져오지 않으면 컴파일 오류를 버리고 세 번째 대상은 모두 반사되어 무엇을 해야 하는가.일반적으로 첫 번째이며, 하나의 문자열은 전송할 수도 있고 설정 파일에 쓸 수도 있는 등 여러 가지 방법이 있다.

어떤 종류의 실례인지 아닌지를 판단하다 일반적으로, 우리는 instanceof 키워드로 어떤 종류의 실례인지 아닌지를 판단한다.또한 Class 객체가 반사되는 isInstance() 방법을 사용하여 클래스의 인스턴스인지 여부를 판단할 수 있습니다. 이것은 Native 방법입니다. public native boolean isInstance(Object obj);

인스턴스 생성하기 (1) Class 대상의 newInstance () 방법을 사용하여 Class 대상에 대응하는 클래스의 실례를 만듭니다. Class> c = String.class; Object str = c.newInstance(); (2) Class 대상을 통해 지정한 Constructor 대상을 가져오고 Constructor 대상의 newInstance () 방법을 호출하여 실례를 만듭니다.이런 방법은 지정된 구조기 구조류의 실례를 사용할 수 있다. // String에 해당하는 Class 객체 가져오기 Class> c = String.class; // String 클래스에 String 매개 변수가 있는 구조자 가져오기 Constructor constructor = c.getConstructor(String.class); // 구조자에 따라 실례 만들기 Object obj = constructor.newInstance("23333"); System.out.println(obj);

Method 가져오기 Class 객체를 가져오는 방법에는 주로 다음과 같은 몇 가지 방법이 있습니다. 1. getDeclaredMethods () 방법은 클래스나 인터페이스에서 설명하는 모든 방법을 되돌려줍니다. 공공, 보호, 기본 (패키지) 접근과 개인 방법을 포함하지만 계승하는 방법은 포함되지 않습니다. public Method[] getDeclaredMethods() throws SecurityException 2. getMethods () 방법은 특정한 클래스의 모든 공용 (public) 방법을 되돌려줍니다. 계승 클래스의 공용 방법을 포함합니다. public Method[] getMethods() throws SecurityException 3. getMethod 방법은 특정한 방법을 되돌려줍니다. 그 중에서 첫 번째 파라미터는 방법 이름이고 뒤에 있는 파라미터는 방법의 파라미터가Class의 대상에 대응합니다. public Method getMethod(String name, Class>... parameterTypes)

획득 구조기 클래스 구조기를 가져오는 방법은 상기 가져오는 방법과 유사합니다.주로 Class 클래스의 get Constructor 방법을 통해 Constructor 클래스의 실례를 얻을 수 있고, Constructor 클래스는 new Instance 방법으로 대상 실례를 만들 수 있습니다.이 메서드는 들어오는 매개 변수에 따라 해당 Constructor를 호출하여 객체 인스턴스를 만들 수 있습니다. public T newInstance(Object ... initargs) 메서드 묘사 public Constructor getConstructor(Class… parameterTypes) 지정한 구조 방법을 얻습니다.public 권한만 얻을 수 있는 구조 방법을 주의하십시오. 다른 접근 권한은 얻을 수 없습니다. public Constructor getDeclaredConstructor(Class… parameterTypes) 지정한 구조 방법을 얻었습니다. 접근 권한을 얻을 수 있는 구조 방법을 주의하십시오. public Constructor[] getConstructors() throws SecurityException 모든public 접근 권한을 얻는 구조 방법 public Constructor[] getDeclaredConstructors() throws SecurityException (public,private,protected,기본 권한을 포함하여 모든 구조 방법을 얻습니다)



클래스의 구성원 변수(필드) 정보 가져오기 주로 다음과 같은 몇 가지 방법이 있습니다. getFiled: 공유 구성원 변수에 접근 getDeclaredField: 선언된 모든 구성원 변수입니다.그러나 부류의 구성원 변수를 얻을 수 없다 getFileds와 getDeclaredFields 사용법은 동일합니다(Method 참조). 호출 방법 클래스에서 방법을 얻으면 invoke () 방법으로 이 방법을 호출할 수 있습니다.invoke 방법의 원형은 다음과 같다. public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException 다음은 인스턴스입니다. public class test1 { public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class> klass = methodClass.class; // methodClass를 만드는 실례 Object obj = klass.newInstance(); // methodClass 클래스를 가져오는dd 방법 Method method = klass.getMethod("add",int.class,int.class); //method에 대응하는 방법을 호출합니다 =>add(1,4) Object result = method.invoke(obj,1,4); System.out.println(result); } } class methodClass { public final int fuck = 3; public int add(int a,int b) { return a+b; } public int sub(int a,int b) { return a+b; } }

반사 작업 배열 사용하기 배열은 Java에서 Object Reference에 값을 부여할 수 있는 비교적 특수한 유형입니다.다음은 반사를 이용하여 그룹을 만드는 예를 살펴보자. /** *반사를 이용한 배열 조작 * 1 배열의 요소를 반사로 수정 * 2 배열의 각 요소를 반사로 가져오기 */ public static void testArrayClass() { String[]strarray = new String[]{"5", "7", "여름철", "미녀", "여자", "여신"}; Array.set(strArray, 0, "멋쟁이"); Class clazz = strArray.getClass(); if (clazz.isArray()) { int length = Array.getLength(strArray); for (int i = 0; i < length; i++) { Object object = Array.get(strArray, i); String className=object.getClass().getName(); System.out.println("----> object=" + object+",className="+className); } } } 결과에서 알 수 있듯이 우리는 성공적으로 Array를 통과했다.set(strArray, 0, "멋쟁이") 배열의 값을 변경합니다.

반사 획득 일반 유형 public static void getGenericHelper(HashMap map) { } 지금 우리가 이런 방법이 있다고 가정한다면, 우리는 어떻게 HashMap 안의 String, Person의 유형을 얻을 수 있을까? public static void getGenericType() { try { Method method =TestHelper.class.getDeclaredMethod("getGenericHelper",HashMap.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); // 비어 있는지 확인 if (null == genericParameterTypes || genericParameterTypes.length < 1) { return ; } // getGenericHelper 메서드의 첫 번째 매개변수 가져오기 ParameterizedType parameterizedType=(ParameterizedType)genericParameterTypes[0]; Type rawType = parameterizedType.getRawType(); System.out.println("----> rawType=" + rawType); Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); if (actualTypeArguments==genericParameterTypes || actualTypeArguments.length<1) { return ; } // 각 유형 인쇄 for (int i = 0; i < actualTypeArguments.length; i++) { Type type = actualTypeArguments[i]; System.out.println("----> type=" + type); } } catch (Exception e) { } } 위 코드를 실행하여 결과를 출력합니다. —-> rawType=class java.util.HashMap —-> type=class java.lang.String —-> type=class com.example.reflectdemo.Person

총결산 1. 반사의 장점 동적 창설 대상과 컴파일링으로 유연성이 강합니다.개원 프레임워크의 개발에 특히 적합하다. 클래스의 각종 내용을 쉽게 얻을 수 있고 동적 호출 클래스의 각 방법, 클래스의 각 속성을 사용하며 설정은 개인적인 방법이다. 2. 반사의 단점 반사는 일정한 시스템 자원을 추가로 소모하기 때문에 동적으로 대상을 만들 필요가 없다면 반사할 필요가 없다. 반사 호출 방법은 권한 검사를 무시할 수 있기 때문에 봉인성을 파괴하여 안전 문제를 초래할 수 있습니다. 참조: Java 반사 심층 분석(1)

좋은 웹페이지 즐겨찾기