자바 리 플 렉 션 관련 및 예시
선언:
코드 가 길 어서 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
클래스 구성 도:
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.