java 기본 반사 (reflect)

4054 단어
지난주에 자바 기초의 주석(Annotation)을 기록했는데 이번 주에 그의 친한 친구가 약속대로 반사했다(분명히 늦게 왔다~).

반사의 기본 개념


반사 메커니즘은 운행 상태에서 임의의 클래스에 대해 이 클래스의 모든 속성과 방법을 알 수 있다.임의의 대상에 대해 임의의 방법과 속성을 호출할 수 있다.이런 동적으로 얻은 정보와 동적 호출 대상의 방법의 기능을 자바 언어의 반사 메커니즘이라고 한다.
반사된 초석:class 클래스
Class 클래스의 각 실례 대상은 각각 메모리에 있는 클래스의 바이트 코드에 대응한다. 예를 들어TestModel 클래스의 바이트 코드,ArrayList 클래스의 바이트 코드 등이다.
하나의 클래스는 클래스 마운트에 의해 메모리에 불러와 하나의 저장 공간을 차지한다. 이 공간 안의 내용은 클래스의 바이트 코드이고 서로 다른 클래스의 바이트 코드는 다르기 때문에 그들이 메모리에 있는 내용은 다르다. 이 공간은 각각 하나의 대상으로 나타낼 수 있다. 이런 대상은 분명히 같은 유형을 가진다. 이 유형이 바로Class 유형이다.
여기서 한 대상의 Class 유형과 대상의 내용을 반드시 구분해야 한다.두 개의 서로 다른 대상은 같은 Class 유형을 가질 수 있다.예를 들어 다음 두 문자열은 분명히 같은 대상이 아니지만 그들의Class 유형은 같다:java.lang.String
String str1 = "abc";// 1
String str2 = "abcd";// 2

반사 상용 방법


Class 클래스 객체 인스턴스화

Class clazz = Class.forName("java.lang.String");
Class clazz = new String().getClass();
Class clazz = String.class;

Class의 Constructor 클래스, 객체 인스턴스화

/** String */
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();

/** String String */
String str = String.class.newInstance();

/** String ( , Class )*/
Constructor constructor = String.class.getConstructor(StringBuffer.class);
String str = (String) constructor.newInstance(new StringBuffer("abc"));

Class의 Field 클래스

/** clazz Class */
Field[] fields = clazz.getDeclaredFields();

// clazz “X” 
//getField public ,getDeclaredField 
Field field = clazz.getDeclaredField("x");

// private Accessible true
field.setAccessible(true);

// field 
 field.set(testModel, (String)name.value());
 field.get(obj);

// 
 field.getGenericType()

// TestAnnotationName 
field.isAnnotationPresent(TestAnnotationName.class)
// 
 field.getAnnotation(annotationClass)

Class의 Method 클래스


Method를 가져오는 방법과 필드를 가져오는 방법은 거의 일치합니다
// 
Method[] methods = clazz.getDeclaredMethods();

// 
Method methodCharAt = clazz.getMethod("charAt", int.class);

// 
methodCharAt.invoke(object,18);

대상의 부류와 실현된 인터페이스 가져오기

 //  
 Class> parentClass = clazz.getSuperclass();
 //  
 Class> intes[] = clazz.getInterfaces();

반사를 사용하여 메모 해석


드디어 주해를 했습니다.

주석 선언

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotationAge{
    int value() default 18;
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotationName{
    String value() default "aclululu";
}

메모 설정

public class TestModel {

    @TestAnnotationName
    private String name;

    @TestAnnotationAge
    private int age;

    /** getter setter **/
}

해석

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
    TestModel testModel = new TestModel();
    System.out.println(testModel.toString());
    System.out.println(" Model...");
    Class clazz = TestModel.class;
    Field[] fields = clazz.getDeclaredFields();
    for(Field field :fields){
        if(field.isAnnotationPresent(TestAnnotationName.class)){
            TestAnnotationName name = (TestAnnotationName) field.getAnnotation(TestAnnotationName.class);
            field.setAccessible(true);
            field.set(testModel, (String)name.value());
        }
        else if(field.isAnnotationPresent(TestAnnotationAge.class)){
             TestAnnotationAge age= (TestAnnotationAge) field.getAnnotation(TestAnnotationAge.class);
             field.setAccessible(true);
             field.set(testModel, (int)age.value());
        }
    }
    
    System.out.println(testModel.toString());
}

결과 내보내기

TestModel [age=0, name=null]
 Model...
TestModel [age=18, name=aclululu]

좋은 웹페이지 즐겨찾기