자바 리 플 렉 션 관련 및 예시

자바 리 플 렉 션 관련 및 예시
선언:
 
        코드 가 길 어서 github 주 소 를 붙 입 니 다:https://github.com/andyChenHuaYing/scattered-items/tree/master/items-java-reflection
        테스트 대상 클래스: TargetClass, 사용자 정의 보조 클래스 가 많 습 니 다. 여기에 붙 이지 않 습 니 다.편폭 이 제한 되 어 있 고 테스트 도 간단 하기 때문에 테스트 류 에 대해 서도 언급 하지 않 았 다.
 
프로필
 
         자바 리 플 렉 션 은 클 라 스, 즉 우리 가 흔히 말 하 는 클래스 에 대한 것 이다. 자바 의 클 라 스 를 조작 하 는 데 사용 되 고 자바 에서 모든 것 이 대상 이다 (주의해 야 할 것 은 원시 유형 과 정태 류, 정태 적 인 방법 은 대상 을 대상 으로 하 는 것 이 아니 라 클래스 에 속 하 는 것 이다). 그러면 '클래스' 도 자바 의 대상 이 고 'Class 류' 유형의 대상 이다.
 
반사 관련
 
        자바 리 플 렉 션 과 관련 된 것 은 네 개의 final 유형의 클래스 클래스 클래스, Method, Field, Constructor 이다.자바 의 모든 종류의 부모 클래스 Object 입 니 다.그 중에서 Class 의 구조 방법 은 개인 적 인 것 이 고 외부 에서 Class 류 구조 방법 을 사용 하여 Class 인 스 턴 스 를 구성 하 는 것 을 허락 하지 않 는 다 는 것 을 의미 합 니 다. Class 류 는 자바 의 유형 에 대한 조작 을 제공 합 니 다. 예 를 들 어 클래스 유형 에 따라 획득 하고 조작 속성, 방법 을 제공 합 니 다.(사유 방법, 사유 유형, 이런 행위 에 대해 서 는 잠시 논 의 를 하지 않 아야 하 는 것 은 아니 지만, 현재 존재 하 는 만큼 자 연 스 럽 게 존재 하 는 이치), Element Type. TYPE, Element TYPE. METHOD, Element TYPE. FIELD 급 의 Annotation 정보 등 이다.
        자바 클래스 의 속성 도 대상 입 니 다. Field, 마찬가지 로 일반적인 방법 도 Method 입 니 다. 구조 방법 - Constructor, Field, Method, Constructor 지정 클래스 유형 에서 속성 대상, 일반 방법 대상 과 구조 방법 대상 의 표현 유형, 지정 클래스 유형 에서 의 속성 과 방법 을 조작 하 는 데 사 용 됩 니 다.
 
3. 유형의 생명 주기
 
        클래스 컴 파일 이 완료 되면 다음 단 계 는 클래스 를 사용 해 야 합 니 다. 클래스 를 사용 하려 면 JVM 과 떨 어 질 수 없습니다. 프로그램 실행 중 JVM 은 불 러 오기, 링크 를 통 해 이 세 단 계 를 초기 화 합 니 다.
마 운 트: 클래스 마 운 트 는 클래스 마 운 트 를 통 해 이 루어 집 니 다. 마 운 트 는. class 파일 의 바 이 너 리 파일 을 JVM 방법 영역 에 불 러 오고, 이 클래스 를 설명 하 는 java. lang. class 대상 을 만 듭 니 다. 데 이 터 를 봉인 하 는 데 사 용 됩 니 다. 단, 같은 클래스 는 클래스 마 운 트 에 한 번 만 불 러 옵 니 다.
        링크: 링크 는 바 이 너 리 데 이 터 를 실행 가능 한 상태 로 조립 하 는 것 입 니 다. 링크 는 검사, 준비, 분석 세 단계 로 나 뉘 어 있 습 니 다. 이 바 이 너 리 파일 이 현재 JVM (버 전) 에 적합 한 지 확인 하 는 데 사 용 됩 니 다.준 비 는 정적 구성원 에 게 메모리 공간 을 할당 하고 기본 값 을 설정 하 는 것 입 니 다. 상수 탱크 의 코드 를 직접 참조 하 는 과정 으로 변환 하 는 것 을 말 합 니 다. 모든 기호 참조 가 실 행 될 때 까지 프로그램 에서 사용 할 수 있 습 니 다 (완전한 대응 관 계 를 만 듭 니 다).
        초기 화: 완료 되면 유형 도 초기 화 됩 니 다. 초기 화 된 대상 은 한 대상 이 더 이상 사용 하지 않 을 때 까지 정상적으로 사용 할 수 있 습 니 다. 쓰레기 를 회수 합 니 다. 공간 을 방출 합 니 다.
        클래스 대상 을 가리 키 는 인용 이 없 을 때 마 운 트 해제 되 고 클래스 의 수명 주 기 를 끝 냅 니 다.
 
4: 클래스 의 세 가지 표현 방법
 
        만약 에 우리 가 현재 foo 류 가 있다 고 가정 하면 그의 유형 은 다음 과 같은 세 가지 방식 으로 얻 을 수 있다.
        1、 Classclazz1 = Foo.class;
        2、 Classclazz2 = foo.getClass();
        3、 Classclazz3 = Class.forName(“packageName.Foo”);

        앞에서 알 고 있 듯 이 모든 종 류 는 한 번 만 불 러 옵 니 다. 즉, 모든 종 류 는 어떤 방식 으로 든 얻 을 수 있 는 유형 이 똑 같 습 니 다.
        clazz1 == clazz2 == clazz3;

5: 정적 로드 와 동적 로드
 
        이 두 명 사 를 우 리 는 모두 낯 설 지 않 지만 반 사 를 통 해 우 리 는 그들의 차 이 를 더욱 잘 알 수 있다. 아니면 두 가지 개념 을 다시 한 번 반복 할 것 인가?
        1. 정적 로드: 컴 파일 시 (javac) 로드 클래스 를 표시 합 니 다.
        2. 동적 로드: 실행 시 (자바) 로드 클래스 를 표시 합 니 다.
        이에 대응 하 는, 우 리 는 Runtime Exception 과 비 Runtime Exception 을 결합 하여 이해 할 수 있 습 니 다. 비 Runtime Exception 은 컴 파일 할 때 반드시 처리 해 야 하 는 이상 입 니 다. 예 를 들 어 흔히 볼 수 있 는 것: ClassNotFoundException, ClassCastException, IOException 등 은 코드 를 두 드 릴 때 던 질 지, try, catch 를 사용 하여 잡 을 지 밝 혀 야 합 니 다. 그렇지 않 으 면 컴 파일 하 는 것 입 니 다.실패 하고 Runtime Exception 은 우리 가 컴 파일 할 때 처리 할 필요 가 없 으 며 실행 할 때 조건 을 만족 시 키 지 않 으 면 이상 을 던 집 니 다. 예 를 들 어 흔히 볼 수 있 는: NullPoint Exception, Index Outof Bound Exception 등 입 니 다.
        자바 에서 new 키워드 구 조 를 사용 하 는 모든 인 스 턴 스 는 컴 파일 기간 에 불 러 옵 니 다. 즉, 우리 가 쓴 자바 류 를 컴 파일 할 때 이와 관련 된 모든 것 을 컴 파일 하고 new 키 워드 를 사용 하여 예화 된 것 이 존재 해 야 한 다 는 것 을 의미 합 니 다. 클 라 스 파일 로 컴 파일 합 니 다.
        동적 로 딩 은 프로그램 이 실 행 될 때, 사용 할 때 실제 유형 에 따라 클래스 를 불 러 오 는 인 스 턴 스 입 니 다.
 
6: 세 가지 클래스 획득 방식 의 차이
 
        1. List. class 는 컴 파일 할 때 Foo 류 를 가 져 올 수 있 는 형식 입 니 다.
        2. list. getClass () 는 실행 할 때 Foo 의 구체 적 인 인 인 스 턴 스 대상 에 따라 Class 형식 을 가 져 옵 니 다. 예 를 들 어 Array List 형식 일 수도 있 고 LinkedList 일 수도 있 으 며 TreeList 형식 일 수도 있 습 니 다. 이것 은 실행 할 때 만 구체 적 으로 어떤 유형 인지 확인 할 수 있 습 니 다.
        3. Class. forName ("packageName. ClassName") 은 클래스 의 유형 을 표시 할 뿐만 아니 라 동적 로드 클래스 도 대표 합 니 다.
7: 실례 전의 설명
 
        반 사 된 작업 은 컴 파일 된 후에 이 루어 집 니 다. 즉, 실행 할 때 실 행 됩 니 다. 구체 적 인 자바 류 유형 에 따라 이러한 인 스 턴 스 를 만 들 수 있 습 니 다. 전 제 는 이러한 인 스 턴 스 가 반드시 참여 구조 방법 이 있어 야 한 다 는 것 입 니 다!
8: 자바 리 플 렉 션 을 통 해 범 형 을 돌아 갑 니 다.
     
        제 네 릭 (범 형) 에 대해 서 는 낯 설 지 않 습 니 다. 특히 집합 을 사용 할 때 범 형 을 지정 하면 우리 가 잘못된 유형 을 추가 하 는 것 을 피 할 수 있 고 예상 치 못 한 결 과 를 초래 할 수 있 습 니 다. 제 네 릭 은 컴 파일 할 때 같은 유형의 데이터 만 추가 할 수 있 도록 규정 하고 있 습 니 다. 그러나 반 사 를 통 해 우 리 는 범 형의 검사 와 컴 파일 을 통과 할 수 있 습 니 다.
        코드:
package org.alien.reflection.generic;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * Demonstrate java reflect could bypass the Collection Generic.
 * Happy day, happy life.
 *
 * @author andy
 * @version 1.0-SNAPSHOT
 *          Created date: 2014-12-22 20:46
 */
@SuppressWarnings("unchecked")
public class CollectionGenericEssence {

    /**
     * Use java reflect to bypass the Collection Generic.
     * @param arrayList
     *        ArrayList of String.
     * @param value
     *        An object which will be added in ArrayList of String.
     */
    public ArrayList<String> addElementsByMethodReflect(ArrayList<String> arrayList, Object value) {
        /*
         * Illegal value type:
         * arrayList.add(value);
         */

        Class arrayListClass = arrayList.getClass();
        try {
            Method method = arrayListClass.getMethod("add", Object.class);
            method.invoke(arrayList, value);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return arrayList;
    }

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<String> arrayList = new ArrayList<String>();
        Class clazz = arrayList.getClass();
        Method method = clazz.getMethod("add", Object.class);
        method.invoke(arrayList, 20);
        System.out.println(arrayList.size());
    }

    @Override
    public String toString() {
        return "CollectionGenericEssence{}";
    }
}

        결론: 자바 의 범 형 은 입력 오류 유형 을 방지 하 는 조치 입 니 다. 위 코드 를 통 해 컴 파일 후 집합 하 는 범 형 은 이미 소 용이 없다 는 것 을 설명 할 수 있 습 니 다. 즉, 범 형 화 된 것 은 컴 파일 시기 에 만 유용 합 니 다. 물론 우 리 는 foreach 를 사용 하여 이러한 특수 집합 을 교체 할 수 없습니다.
 
9: 자바 리 플 렉 션 을 통 해 클래스 를 재 구성 합 니 다.
 
        먼저 설명: 이렇게 하 는 의 미 는 그 를 통 해 자바 리 플 렉 션 과 관련 된 클래스 의 사용 을 알 게 되 는 것 입 니 다. 이것 은 기본 이 며, 동시에 전부 가 아 닙 니 다. 중점 이 다 릅 니 다. 아래 의 필터 가 있 으 면 나중에 사용 하 는 것 외 에 도 찾 는 결과 가 다 르 고 과정 이 같 습 니 다. Field, Method 에 대한 실행 은 뒤에 있 습 니 다. 또한 아래 에 재현 되 는 클래스 도 포함 되 지 않 습 니 다.방법 체, 잠시 이러한 종류의 속성, 방법 만 포함 되 어 있 습 니 다. 아래 몇 가지 로 나 누 어 설명 하 겠 습 니 다. 그리고 이것들 은 모두 코드 에 주석 이 있 으 며, 모든 방법 은 단독으로 테스트 할 수 있 습 니 다. 테스트 류 의 코드 는 붙 이지 않 습 니 다. 그 다음 에 TargetClass 내용 이 있 을 것 입 니 다. 그 안에 사 용 된 자체 정의 Annotation 도 붙 이지 않 고 github 에 놓 으 며 앞 뒤로 주 소 를 붙 입 니 다. 구체 적 인 과정:
        1. 완성 한 가방 이름 가 져 오기,
        2. import, 클래스 에서 사용 하 는 클래스 가 모두 전체 이름 일 때 import 가 필요 하지 않 습 니 다 (물론 방법 체 에 서 는 제외)
        3. 클래스 설명 가 져 오기,
        4. 부류 의 부류 가 져 오기,
        5. 클래스 의 모든 인터페이스 가 져 오기,
        6. 클래스 장식 부적 가 져 오기,
        7. 클래스 이름 가 져 오기,
        8. 클래스 의 모든 속성 을 획득,
        9. 속성 을 가 져 오 는 모든 Annotation,
        10. 모든 구조 방법 을 얻 고,
        11. 모든 구조 방법의 Annotation 가 져 오기,
        12. 모든 방법 을 얻 고,
        13. 각각 획득 방법의 Annotation,
        14. 모든 방법의 장식 부 호 를 각각 획득 하고,
        15. 모든 방법의 반환 값 을 각각 획득 하고,
        16. 모든 방법의 모든 매개 변수 와 유형 을 가 져 옵 니 다.
        17. 모든 방법 으로 성명 한 이상 정 보 를 각각 얻는다.
        18. 종합 하여 최종 결 과 를 만든다.
        구체 적 인 코드:
     
package org.alien.reflection.api;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;

/**
 * Happy day, happy life.
 *
 * @author andy
 * @version 1.0-SNAPSHOT
 *          Created date: 2014-12-22 21:48
 */

public class ShowClassDetailInfo {

    private static final String LINE_BREAK = "\r
"; private static final String SPACE = " "; private static final String SEMICOLON = ";"; public static String showClassFullInfo(Class clazz) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("package ").append(showClassPackage(clazz)).append(LINE_BREAK); String classModifier = Modifier.toString(clazz.getModifiers()); stringBuilder.append(classModifier).append(SPACE).append(clazz.getSimpleName()); if (hasSuperClass(clazz)) { stringBuilder.append(SPACE).append("extend ").append(clazz.getSimpleName()); } if (hasInterface(clazz)) { stringBuilder.append(SPACE).append("implement ").append(showClassImplInterfaces(clazz)); } stringBuilder.append(" {").append(LINE_BREAK); stringBuilder.append(showDeclaredField(clazz)) .append(LINE_BREAK) .append(showConstructs(clazz)) .append(LINE_BREAK) .append(showDeclaredMethod(clazz)) .append(LINE_BREAK) .append("}"); return stringBuilder.toString(); } /** * Show target class's package name. * @return * Target class package name. */ public static String showClassPackage(Class clazz) { return clazz.getPackage().getName(); } /** * Validate target class has super class or not. * @param clazz * Target class. * @return * If target class has super class, return true, otherwise false. */ public static boolean hasSuperClass(Class clazz) { Class superclass = clazz.getSuperclass(); return superclass != null; } /** * Show target class's super class. * @param clazz * Target class. * @return * The name of super class. */ public static String showSuperClass(Class clazz) { if (hasSuperClass(clazz)) { return clazz.getSuperclass().getSimpleName(); } return "Object"; } /** * Validate target class has interface or not. * @param clazz * Target class. * @return * If target class has one or more interface, return true, otherwise false. */ public static boolean hasInterface(Class clazz) { return clazz.getInterfaces().length > 0; } /** * Show target class's interfaces. * @param clazz * Target class * @return * Interfaces info. */ public static String showClassImplInterfaces(Class clazz) { StringBuffer stringBuffer = new StringBuffer(); Class[] classes = clazz.getInterfaces(); if (hasInterface(clazz)) { for (Class face : classes) { stringBuffer.append(face.getSimpleName()).append(", "); } stringBuffer = fixStringBuffer(stringBuffer); } return stringBuffer.toString(); } /** * Show target class's constructors * @param clazz * Target class * @return * Constructors info. */ public static String showConstructs(Class clazz) { StringBuffer stringBuffer = new StringBuffer(); Constructor[] constructors = clazz.getConstructors(); for (Constructor constructor : constructors) { Annotation[] annotations = constructor.getDeclaredAnnotations(); stringBuffer = constructorAnnotation(stringBuffer, annotations); String modifierType = Modifier.toString(constructor.getModifiers()); stringBuffer.append(modifierType).append(SPACE).append(clazz.getSimpleName()).append("("); Class[] types = constructor.getParameterTypes(); if (types.length > 0) { for (Class type : types) { String parameterTypeName = type.getName(); String parameterTypeReferenceName = type.getClass().getSimpleName().toLowerCase(); stringBuffer = injectMethodParametersContent(stringBuffer, parameterTypeName, parameterTypeReferenceName); } stringBuffer = fixStringBuffer(stringBuffer); } stringBuffer.append(")").append("{...}").append(LINE_BREAK).append(LINE_BREAK); } return stringBuffer.toString(); } /** * Show all fields value declared by target class instance. * @param object * Target class instance. * @return * The object array of fields value. * @throws IllegalAccessException * Execution failed. */ public static Object[] showAllDirectInstanceFieldsValue(Object object) throws IllegalAccessException { Field[] fields = object.getClass().getDeclaredFields(); Object[] objects = new Object[fields.length]; for (int i = 0; i < fields.length; i++) { Field field = fields[i]; /* change the access privilege so that we could obtain or change the private Field , Constructor(except Class) or private method action. */ field.setAccessible(true); Object obj = fields[i].get(object); objects[i] = obj; System.out.println(fields[i].get(object)); System.out.println(Modifier.toString(fields[i].getModifiers())); } return objects; } /** * Show class's declared field. * @param clazz * Target class. * @return * Declared field info. */ public static String showDeclaredField(Class clazz) { StringBuffer stringBuffer = new StringBuffer(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { Annotation[] annotations = field.getDeclaredAnnotations(); stringBuffer = constructorAnnotation(stringBuffer, annotations); String fieldModifier = Modifier.toString(field.getModifiers()); String fieldType = field.getType().getSimpleName(); stringBuffer.append(fieldModifier).append(SPACE).append(fieldType).append(SPACE); stringBuffer.append(field.getName()).append(SEMICOLON).append(LINE_BREAK).append(LINE_BREAK); } return stringBuffer.toString(); } /** * Show class's declared method. * @param clazz * Target Class type. */ public static String showDeclaredMethod(Class clazz) { Method[] methods = clazz.getDeclaredMethods(); return showMethodsDetail(methods); } /** * Show methods' detail information * @param methods * Target class's method. * @return * All methods print info . */ private static String showMethodsDetail(Method[] methods) { StringBuffer stringBuffer = new StringBuffer(); for (Method method : methods) { //Construct Annotation Annotation[] annotations = method.getDeclaredAnnotations(); stringBuffer = constructorAnnotation(stringBuffer, annotations); //Construct method modifier type String modifierType = Modifier.toString(method.getModifiers()); stringBuffer.append(modifierType).append(SPACE); // String methodInfo = method.toString(); // if (methodInfo.startsWith("public")) { // stringBuffer.append("public "); // } // if (methodInfo.startsWith("protected")) { // stringBuffer.append("protected "); // } // if (methodInfo.startsWith("private")) { // stringBuffer.append("private "); // } //Construct method name Class<?> returnType = method.getReturnType(); String methodName = method.getName(); stringBuffer.append(returnType).append(SPACE).append(methodName).append("("); //Construction method parameters Class[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length > 0) { for (Class parameterTypeClass : parameterTypes) { String parameterTypeName = parameterTypeClass.getName(); String parameterTypeReferenceName = parameterTypeClass.getSimpleName().toLowerCase(); stringBuffer = injectMethodParametersContent(stringBuffer, parameterTypeName, parameterTypeReferenceName); } stringBuffer = fixStringBuffer(stringBuffer); } stringBuffer.append(")"); //Construct throws Exceptions Class<?>[] exceptionTypes = method.getExceptionTypes(); if (exceptionTypes.length > 0) { stringBuffer.append("throws "); for (Class exceptionType : exceptionTypes) { String exceptionName = exceptionType.getSimpleName(); stringBuffer.append(exceptionName).append(", "); } stringBuffer = fixStringBuffer(stringBuffer); } //Construct method body, of course is invisible. stringBuffer.append("{...}").append(LINE_BREAK).append(LINE_BREAK); } return stringBuffer.toString(); } /** * Construct target's annotation expression. * @param stringBuffer * Result container. * @param annotations * Target's all annotations. * @return * Final expression. */ private static StringBuffer constructorAnnotation(StringBuffer stringBuffer, Annotation[] annotations) { if (annotations.length > 0) { for (Annotation annotation : annotations) { String annotationName = annotation.annotationType().getSimpleName(); stringBuffer.append("@").append(annotationName).append("\r
"); } } return stringBuffer; } /** * Cut the last "," in stringBuffer. * @param stringBuffer * raw str. * @return * Fixed str. */ private static StringBuffer fixStringBuffer(StringBuffer stringBuffer) { return stringBuffer.delete(stringBuffer.lastIndexOf(","), stringBuffer.length()); } /** * Construct method parameters list. * @param stringBuffer * Parameters list container. * @param parameterTypeName * Parameter type class name. * @param parameterTypeReferenceName * Parameter dummy reference name. * @return * Method parameters list info. */ private static StringBuffer injectMethodParametersContent(StringBuffer stringBuffer, String parameterTypeName, String parameterTypeReferenceName) { return stringBuffer.append(parameterTypeName).append(SPACE).append(parameterTypeReferenceName).append(", "); } }

10: 방법, 속성의 집행
     
        1. 방법의 집행 은 다음 과 같은 방법 밖 에 없 으 니 직접 해 볼 수 있다.
                Method.invok(TargetClassInstance, Object …parameters);

        2. 속성의 실행 방법 이 유사 하고 구체 적 으로 Field 의 API 를 볼 수 있 습 니 다.
                Object = field.getValue(TargetClassInstancetarget);

        개인 적 인 방법, 속성의 집행 대 가 를 중점적으로 설명 하 다.
        자바 에 서 는 클래스, 방법, 속성 에 대해 수정자 Public, proctected, 기본, private 를 사용 하여 클래스, 속성, 방법 에 대한 접근 권한 을 제한 합 니 다. 자바 리 플 렉 션 에 서 는 클래스 유형 및 그의 구성 부분 에 대한 조작 방식 뿐만 아니 라 클래스 유형의 속성, 방법 을 수정 할 수 있 는 접근 권한 도 제공 합 니 다. AccessibleObject, 그 는 Field, Method, Con 입 니 다.structor, ReflectPermission 의 부모 클래스, 그 중 하 나 는 setAccessible (), boolean 형식의 매개 변 수 를 받 아들 여 현재 Field, Method, Constructor 의 개인 접근 을 개방 할 권 리 를 지정 할 수 있 습 니 다. 주의 하 십시오.(앞에서 언급 한 Class 의 구조 방법 은 사유 적 인 것 입 니 다. 이런 방식 으로 Class 류 의 사유 구조 방법의 권 리 를 얻 을 수 있 습 니까? 정 답 은 부정 적 입 니 다. Class 는 AccessibleObject 의 하위 클래스 가 아니 기 때 문 입 니 다!)
        코드 세 션:
 
    public static Object[] showAllDirectInstanceFieldsValue(Object object) throws IllegalAccessException {
        Field[] fields = object.getClass().getDeclaredFields();
        Object[] objects = new Object[fields.length];

        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            /*
            change the access privilege so that we could obtain or change the private Field ,
            Constructor(except Class) or private method action.
            */
            field.setAccessible(true);
            Object obj = fields[i].get(object);
            objects[i] = obj;
            System.out.println(fields[i].get(object));
            System.out.println(Modifier.toString(fields[i].getModifiers()));
        }
        return objects;
    }

보충:
        클래스 로 더 의 정보, 클래스 로 더 가 많은 JVM 내용 과 관련 되 어 있 지 않 습 니 다. 마지막 으로 클래스 구성 도와 이 항목 이 github 에 있 는 주 소 를 올 립 니 다.
https://github.com/andyChenHuaYing/scattered-items/tree/master/items-java-reflection
        클래스 구성 도:
     
     
     
 
 
 

좋은 웹페이지 즐겨찾기