자바 개발 반사 메커니즘 의 실전 경험 총화

머리말
저 는 실제 프로젝트 에서 반사 체 제 를 자주 사용 하기 때문에 배 운 반사 용법 을 종합 필 기 를 해서 나중에 다시 사용 하 는 것 으로 생각 합 니 다.
이러한 종류 가 존재 합 니 다:

package com.example.demo;
import com.alibaba.fastjson.annotation.JSONField;
public class User {
    private String name;
    @Value( value ="age_a")
    private String age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
     public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

1.Class 를 만 드 는 세 가지 방식
1 - Class clazz = Class.forName("com.example.demo.User");

여기 있 는 forName("xxx")의 클래스 이름 은 전체 이름 이 필요 하고 인터페이스 나 클래스 가 필요 합 니 다.그렇지 않 으 면 불 러 올 수 없습니다.
2 - User user = new User();
Class clazz2 = user.getClass();

3 - Class clazz3 = User.class;
상기 세 가지 방식 은 모두 사용자 의 클 라 스 대상 을 얻 을 수 있 고 클 라 스 를 통 해 반 사 를 시작 할 수 있 습 니 다.
2.반사 획득 류 의 모든 속성 과 속성 유형

Class clazz = User.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
    System.out.println("   :"+field.getName());
    System.out.println("     :"+field.getGenericType().getTypeName());
}
출력 User 의 속성 과 속성 유형 을 인쇄 합 니 다.
속성 이름:name
속성의 종류:java.lang.String
속성 명:age
속성의 종류:java.lang.String
반 사 를 이용 하여 클래스 의 필드 속성 을 얻 은 후 반 사 를 이용 하여 대상 을 만 들 수 있 습 니까?답 은 긍정 적 이다.
예 를 들 어 아래 코드 와 유사 하 게 반 사 된 필드 속성 을 통 해 대상 을 만 들 수 있다.

Map<String,Object> fileds = new HashMap<>();
fileds.put("name","  ");
fileds.put("age","10");
Object o = User.class.newInstance();
 Field[] fields = o.getClass().getDeclaredFields();
 for (Field field : fields) {
     //               
     field.setAccessible(true);
     //         
     field.set(o,fileds.get(field.getName()));
 }
 User user1 = (User) o;
 System.out.println(user1.toString());
어떤 장면 에서 이렇게 해 야 할 까요?일부 내부 데이터 와 외부 데이터 필드 의 맵 처럼 유사 한 필드 반사 방식 으로 소스 데 이 터 를 목표 데이터 에 투사 하여 데이터 베 이 스 를 삽입 할 수 있 는 목표 대상 을 얻 을 수 있다.
3.반사 동적 수정 클래스 속성의 주해 값
주의 하 세 요.사용자 클래스 를 설정 할 때 그 필드 에 주 해 를 달 았 습 니 다:@Value(value="agea")。이것 은 설정 값 의 주해 입 니 다.설정 값 인 이상 코드 가 실행 되 는 과정 에서 상황 에 따라 동적 으로 수정 할 수 있 습 니까?
필드 의 주 해 는 사실 하나의 member Values 속성 에 저장 되 어 있 습 니 다.이것 은 map 입 니 다.이렇게 얻 을 수 있 습 니 다.

Field[] fields = User.class.getDeclaredFields();
for (Field field : fields) {
    //               
    if ("age".equals(field.getName() )){
        field.setAccessible(true);
       //   annotation            InvocationHandler
       InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(Value.class));
       //    InvocationHandler   memberValues   
        Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
        memberValues.setAccessible(true);
        Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler);
        System.out.println(values);
    }
}
debug 중단 점,볼 수 있 습 니 다.

이 맵는 이@주해 의 모든 속성 값 을 저장 합 니 다.여기,@Value 는 하나의 value 속성 만 있 습 니 다.

public @interface Value {
    String value();
}
@JSONfield(name="age"와 유사 하 게 바 꾸 면a"),위의 코드 를 약간 수정 합 니 다.예 를 들 어:

Field[] fields = User.class.getDeclaredFields();
for (Field field : fields) {
    if ("age".equals(field.getName() )){
        field.setAccessible(true);
          InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(JSONField.class));
  ......
    }
}
@JSONfield 주해 의 내부 속성 은 다음 과 같은 방식 이 있 습 니 다.

방금 코드 를 실행 하면 맵에서 저 장 된 모든 속성 과 대응 하 는 속성 값 을 얻 을 수 있 습 니 다.

이 단계 에 이 르 러 이전의 문제 로 돌아 가 이 주해 의 값 을 동적 으로 바 꾸 려 면 어떻게 처리 해 야 합 니까?
사실 아주 간단 합 니 다.직접 값 설정 만 하면 됩 니 다.예 를 들 어-

InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(Value.class));
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
memberValues.setAccessible(true);
Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler);
values.put("value","new_age");
memberValues.setAccessible(false);
다만,주의해 야 할 것 은 여기 키 가 대응 하 는 주석 에 속성 값 이 있어 야 한 다 는 것 입 니 다.
4.반사 획득 류 의 방법 및 호출 방식

 Object o=User.class.newInstance();
//       User setAge  ,   String.class    setAge       ,    ,      
//  ,      , List,Long,  List.class,Long.class
 Method m =  (Method) o.getClass().getMethod("setAge",String.class);
 m.invoke(o,"name");
 User user = (User) o;
 System.out.println(user);
인쇄 를 통 해 알 수 있 듯 이 age 는 name 이 고 setAge 호출 이 성공 했다 는 것 을 설명 합 니 다.

이런 사용 장면 은 대리 에서 비교적 많이 나타난다.
마지막 으로 반 사 를 통 해 맵 을 대상 으로 하 는 패 키 징 도 구 를 실현 한다.

   public Object MapToObject(Object object,Map<String, Object> map) throws IllegalAccessException {
        Class cla =  object.getClass();
        Field[] fields = cla.getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            if("serialVersionUID".equals(field.getName()))continue;
            if(map.get(field.getName())!=null) {
                Object value=map.get(field.getName());
                value=convertValType(value,field.getType());
                field.set(object, value);
            }
        }
        return object;
    }


    private static Object convertValType(Object value, Class<?> fieldTypeClass) {
        Object o = null;
        if (Long.class.getName().equals(fieldTypeClass.getName())
                || long.class.getName().equals(fieldTypeClass.getName())) {
            o = Long.parseLong(value.toString());
        } else if (Integer.class.getName().equals(fieldTypeClass.getName())
                || int.class.getName().equals(fieldTypeClass.getName())) {
            o = Integer.parseInt(value.toString());
        } else if (Float.class.getName().equals(fieldTypeClass.getName())
                || float.class.getName().equals(fieldTypeClass.getName())) {
            o = Float.parseFloat(value.toString());
        } else if (Double.class.getName().equals(fieldTypeClass.getName())
                || double.class.getName().equals(fieldTypeClass.getName())) {
            o = Double.parseDouble(value.toString());
        } else {
            retVal = o;
        }
        return retVal;
    }
총결산
자바 반사 체제 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 개발 반사 체제 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기