자바 의 반사 기초 지식
1.1 자바 의 반사
자바 반 사 는 우리 가 실행 할 때 클래스 의 함수, 속성, 부모 클래스, 인터페이스 등 Class 내부 정 보 를 얻 을 수 있 는 메커니즘 입 니 다.반 사 를 통 해 우 리 는 운행 기 실례 화 대상, 호출 방법, get / set 방법 을 호출 하여 변수의 값 을 얻 을 수 있다. 방법 이나 속성 이 사유 적 이 더 라 도 반사 적 인 형식 으로 호출 할 수 있다. 이런 '클 라 스 를 꿰 뚫 어 보 는' 능력 을 내성 이 라 고 하 는데 이런 능력 은 프레임 워 크 개발 에서 특히 중요 하 다.어떤 경우 에 우리 가 사용 하고 자 하 는 종 류 는 실행 할 때 만 확정 된다. 이때 우 리 는 컴 파일 기간 에 그것 을 사용 할 수 없 기 때문에 실행 할 때 만 존재 하 는 종 류 를 반사 적 으로 사용 할 수 있다. (이런 종 류 는 특정한 규범 에 부합 한다. 예 를 들 어 JDBC) 이것 은 반사 적 으로 많이 사용 하 는 장면 이다.또 하나의 흔히 볼 수 있 는 장면 은 컴 파일 할 때 우 리 는 클래스 의 내부 정 보 를 알 수 없고 실행 되 어야 클래스 의 구체 적 인 정 보 를 얻 을 수 있다 는 것 이다.예 를 들 어 ORM 프레임 워 크 는 실행 할 때 클래스 의 각 속성 을 가 져 온 다음 에 반사 적 인 형식 으로 속성 이름과 값 을 가 져 와 데이터 베 이 스 를 저장 할 수 있 습 니 다.이것 도 비교적 전형 적 인 응용 장면 중 하나 이다.
1.2 Class 클래스
그렇다면 반 사 는 클 라 스 정 보 를 조작 하 는 것 이 고 클 라 스 는 무엇 일 까?자바 프로젝트 를 작성 한 후에 모든 자바 파일 은. class 파일 로 컴 파일 됩 니 다. 이 class 대상 들 은 이 유형의 부모 클래스, 인터페이스, 구조 함수, 방법, 속성 등 원시 정 보 를 불 러 옵 니 다. 이 class 파일 들 은 프로그램 이 실 행 될 때 ClassLoader 에 의 해 가상 컴퓨터 에 불 러 옵 니 다.클래스 가 불 러 오 면 자바 가상 컴퓨터 는 메모리 에 클 라 스 대상 을 자동 으로 생 성 합 니 다.우 리 는 new 형식 으로 대상 을 만 드 는 것 은 사실상 이러한 Class 를 통 해 만 드 는 것 입 니 다. 다만 이 과정 은 우리 에 게 불투명 할 뿐 입 니 다.다음 장 에서 저 희 는 반 사 된 자주 사용 되 는 api 를 보 여 드 리 고 코드 의 측면 에서 반 사 를 이해 할 것 입 니 다.
2. 반사 Class 및 구조 대상
2.1 Class 대상 가 져 오기
클래스 의 정 보 를 검사 하기 전에 클래스 의 클래스 대상 을 가 져 와 야 합 니 다.자바 의 모든 유형 은 기본 유형 을 포함 하고 배열 도 이와 관련 된 Class 류 의 대상 이 있 습 니 다.컴 파일 기간 에 클래스 이름 을 알 고 있다 면 다음 과 같은 방식 으로 클래스 대상 을 가 져 올 수 있 습 니 다.
Class<?> myObjectClass = MyObject.class;
만약 당신 이 이미 어떤 대상 을 얻 었 지만, 이 대상 의 클 라 스 대상 을 얻 고 싶다 면, 아래 의 방법 을 통 해 얻 을 수 있다.
Student me = new Student("mr.simple");
Class<?> clazz = me.getClass();
컴 파일 기간 에 대상 형식 을 가 져 올 수 없 지만 전체 클래스 경 로 를 알 고 있다 면 다음 과 같은 형식 으로 Class 대상 을 가 져 올 수 있 습 니 다.
Class<?> myObjectClass = Class.forName("com.simple.User");
Class. forName () 방법 을 사용 할 때 클래스 가 있 는 가방 의 이름 을 포함 하 는 클래스 의 전체 이름 을 제공 해 야 합 니 다.예 를 들 어 User 클래스 가 com. simple 패키지 에 있 으 면 그의 전체 클래스 경 로 는 com. simple. User 입 니 다.Class. forName () 방법 을 호출 할 때 컴 파일 경로 (classpath) 에서 해당 하 는 클래스 를 찾 지 못 하면 Class NotFoundException 을 던 집 니 다.
인터페이스 설명
// Class , 1 , "com.simple.Student". ( )
public static Class<?> forName (String className)
// Class , 1 , "com.simple.Student";
// 2 Class , 3 ClassLoader.
public static Class<?> forName (String className, boolean shouldInitialize, ClassLoader classLoader)
2.2 Class 대상 을 통 해 목표 유형 을 구성 하 는 대상
일단 당신 이 클 라 스 상 대 를 받 은 후에 당신 은 하고 싶 은 대로 할 수 있 습 니 다!당신 이 그것 을 잘 사용 할 때 그것 은 신병 의 이기 입 니 다. 당신 이 꿍꿍이 를 품 었 을 때 그것 은 악마 가 됩 니 다.그러나 클 라 스 대상 을 얻 는 것 은 첫 번 째 단계 입 니 다. 우 리 는 강력 한 행 위 를 수행 하기 전에 클 라 스 대상 을 통 해 이 유형의 대상 을 구성 한 후에 야 이 대상 을 통 해 에 너 지 를 방출 할 수 있 습 니 다.우 리 는 자바 에서 대상 을 구성 하려 면 반드시 이런 구조 함 수 를 통과 해 야 한 다 는 것 을 알 고 있다. 그러면 사실 반사 도 마찬가지 이다.그러나 이들 은 확실히 차이 가 있다. 반사 구조 대상 을 통 해 우 리 는 먼저 클래스 의 Constructor (구조 기) 대상 을 얻 은 다음 에 Constructor 를 통 해 목표 클래스 의 대상 을 만들어 야 한다.그냥 코드 올 리 는 거 야?
private static void classForName() {
try {
// Class
Class<?> clz = Class.forName("org.java.advance.reflect.Student");
// Class Constructor,Student
// ( Student )
Constructor<?> constructor = clz.getConstructor(String.class);
// Constructor Student
Object obj = constructor.newInstance("mr.simple");
System.out.println(" obj : " + obj.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
상기 코드 를 통 해 우 리 는 실행 할 때 완전한 클래스 이름 을 통 해 대상 을 구축 할 수 있다.
구조 함수 인터페이스 가 져 오기
// , , , getConstructor
public Constructor<T> getConstructor (Class...<?> parameterTypes)
//
public Constructor[]<?> getConstructors ()
반사 로 Constructor, Method, Field 를 얻 은 후 반사 호출 전에 이 대상 의 access 표 지 를 true 로 설정 하여 반사 속 도 를 높 입 니 다.값 이 true 이면 반사 대상 이 사용 할 때 자바 언어 접근 검 사 를 취소 해 야 합 니 다.값 이 false 이면 반사 대상 에 게 자바 언어 접근 검 사 를 실시 해 야 합 니 다.예 를 들 면:
Constructor<?> constructor = clz.getConstructor(String.class);
// Constructor Accessible
constructor.setAccessible(true);
// Methohd Accessible
Method learnMethod = Student.class.getMethod("learn", String.class);
learnMethod.setAccessible(true);
뒤에 Student 와 관련 된 클래스 도 사용 되 기 때문에 코드 를 먼저 드 리 겠 습 니 다.Person.java
public class Person {
String mName;
public Person(String aName) {
mName = aName;
}
private void sayHello(String friendName) {
System.out.println(mName + " say hello to " + friendName);
}
protected void showMyName() {
System.out.println("My name is " + mName);
}
public void breathe() {
System.out.println(" take breathe ");
}
}
Student.java
public class Student extends Person implements Examination {
//
int mGrade;
public Student(String aName) {
super(aName);
}
public Student(int grade, String aName) {
super(aName);
mGrade = grade;
}
private void learn(String course) {
System.out.println(mName + " learn " + course);
}
public void takeAnExamination() {
System.out.println(" takeAnExamination ");
}
public String toString() {
return " Student : " + mName;
}
Breathe.java
//
public interface Breathe {
public void breathe();
}
Examination.java
//
public interface Examination {
public void takeAnExamination();
}
3 반사 획득 클래스 중 함수
3.1 현재 클래스 에서 정 의 된 방법 가 져 오기
현재 클래스 에서 정 의 된 모든 방법 을 가 져 오 려 면 Class 의 getDeclared Methods 함 수 를 통 해 현재 클래스 의 Public, default, proctected, private 의 모든 방법 을 가 져 올 수 있 습 니 다.getDeclared Method (String name, Class... parameterTypes) 는 지정 한 방법 을 가 져 옵 니 다.코드 예 시 는 다음 과 같다.
private static void showDeclaredMethods() {
Student student = new Student("mr.simple");
Method[] methods = student.getClass().getDeclaredMethods();
for (Method method : methods) {
System.out.println("declared method name : " + method.getName());
}
try {
Method learnMethod = student.getClass().getDeclaredMethod("learn", String.class);
//
Class<?>[] paramClasses = learnMethod.getParameterTypes() ;
for (Class<?> class1 : paramClasses) {
System.out.println("learn : " + class1.getName());
}
// private , private
System.out.println(learnMethod.getName() + " is private "
+ Modifier.isPrivate(learnMethod.getModifiers()));
learnMethod.invoke(student, "java ---> ");
} catch (Exception e) {
e.printStackTrace();
}
}
3.2 현재 클래스, 부모 클래스 에서 정 의 된 공유 방법 가 져 오기
현재 클래스 와 부모 클래스 의 모든 Public 방법 을 가 져 오 려 면 Class 의 getMethods 함 수 를 통 해 가 져 올 수 있 으 며, getMethod 는 지정 한 방법 을 가 져 올 수 있 습 니 다.코드 예 시 는 다음 과 같다.
private static void showMethods() {
Student student = new Student("mr.simple");
//
Method[] methods = student.getClass().getMethods();
for (Method method : methods) {
System.out.println("method name : " + method.getName());
}
try {
// getMethod , ,
Method learnMethod = student.getClass().getMethod("learn", String.class);
// private , private
System.out.println(learnMethod.getName() + " is private " + Modifier.isPrivate(learnMethod.getModifiers()));
// learn
learnMethod.invoke(student, "java");
} catch (Exception e) {
e.printStackTrace();
}
}
인터페이스 설명
// Class , , 2
public Method getDeclaredMethod (String name, Class...<?> parameterTypes)
// Class ( )
public Method[] getDeclaredMethods ()
// Class ** ** , , 2
public Method getMethod (String name, Class...<?> parameterTypes)
// Class ** ** ( )
public Method[] getMethods ()
여기 서 주의해 야 할 것 은 getDeclared Method 와 getDeclared Methods 는 private, proctected, default, Public 의 함 수 를 포함 하고 이 두 함 수 를 통 해 얻 은 것 은 자신 이 정의 하 는 함수 일 뿐 부모 클래스 에서 통 합 된 함 수 는 얻 을 수 없습니다.한편, getMethod 와 getMethods 는 Public 함수 만 포함 하고 부모 클래스 의 공유 함수 도 얻 을 수 있 습 니 다.
4 반사 획득 클래스 의 속성
속성 을 가 져 오 는 것 은 장 3 에서 가 져 오 는 방법 과 매우 비슷 합 니 다. getMethod 함수 에서 getField 로 바 뀌 었 을 뿐 입 니 다. getDeclared Method 에서 getDeclared Field 로 바 뀌 었 을 뿐 입 니 다.
4.1 현재 클래스 에서 정 의 된 속성 가 져 오기
현재 클래스 에서 정의 하 는 모든 속성 을 가 져 오 려 면 Class 의 getDeclared Fields 함 수 를 통 해 현재 클래스 의 Public, default, proctected, private 의 모든 속성 을 가 져 올 수 있 습 니 다.getDeclared Field 는 지정 한 속성 을 가 져 옵 니 다.코드 예 시 는 다음 과 같다.
private static void showDeclaredFields() {
Student student = new Student("mr.simple");
//
Field[] publicFields = student.getClass().getDeclaredFields();
for (Field field : publicFields) {
System.out.println("declared field name : " + field.getName());
}
try {
//
Field gradeField = student.getClass().getDeclaredField("mGrade");
//
System.out.println(" my grade is : " + gradeField.getInt(student));
//
gradeField.set(student, 10);
System.out.println(" my grade is : " + gradeField.getInt(student));
} catch (Exception e) {
e.printStackTrace();
}
}
4.2 현재 클래스, 부모 클래스 에서 정의 하 는 공유 속성 가 져 오기
현재 클래스 와 부모 클래스 의 모든 Public 속성 을 가 져 오 려 면 Class 의 getFields 함 수 를 통 해 가 져 올 수 있 으 며, getField 는 지정 한 속성 을 가 져 옵 니 다.코드 예 시 는 다음 과 같다.
private static void showFields() {
Student student = new Student("mr.simple");
//
Field[] publicFields = student.getClass().getFields();
for (Field field : publicFields) {
System.out.println("field name : " + field.getName());
}
try {
//
Field ageField = student.getClass().getField("mAge");
System.out.println(" age is : " + ageField.getInt(student));
} catch (Exception e) {
e.printStackTrace();
}
}
인터페이스 설명
// Class ,
public Method getDeclaredField (String name)
// Class ( )
public Method[] getDeclaredFields ()
// Class ** ** ,
public Method getField (String name)
// Class ** ** ( )
public Method[] getFields ()
여기 서 주의해 야 할 것 은 getDeclared Field 와 getDeclared Fields 는 private, proctected, default, Public 의 속성 을 포함 하고 이 두 함 수 를 통 해 얻 은 것 은 자신 에 게 정 의 된 속성 일 뿐 부모 클래스 에서 통 합 된 속성 을 얻 을 수 없습니다.한편, getField 와 getFields 는 Public 속성 만 포함 하고 부모 클래스 의 공유 속성 도 얻 을 수 있 습 니 다.
5. 부모 클래스 와 인터페이스 반사 획득
5.1 부모 클래스 가 져 오기
Class 대상 의 부모 클래스 를 가 져 옵 니 다.
Student student = new Student("mr.simple");
Class<?> superClass = student.getClass().getSuperclass();
while (superClass != null) {
System.out.println("Student's super class is : " + superClass.getName());
// , Object ,Object null
superClass = superClass.getSuperclass();
}
5.2 획득 인터페이스
Class 대상 에서 실 현 된 인 터 페 이 스 를 가 져 옵 니 다.
private static void showInterfaces() {
Student student = new Student("mr.simple");
Class<?>[] interfaceses = student.getClass().getInterfaces();
for (Class<?> class1 : interfaceses) {
System.out.println("Student's interface is : " + class1.getName());
}
}
6 주석 정보 가 져 오기
프레임 워 크 개발 에서 주해 가 반사 되 는 조합 사용 이 가장 흔 한 형식 이다.주해 에 관 한 지식 은 공공 기술 점 의 자바 주해 Annotation 을 참고 하 십시오. 주 해 를 정의 할 때 저 희 는 @ Target 을 통 해 이 주해 가 작용 할 수 있 는 유형 을 지정 합 니 다. 다음 과 같은 예 를 보십시오.
@Target({
ElementType.METHOD, ElementType.FIELD, ElementType.TYPE
})
@Retention(RetentionPolicy.RUNTIME)
static @interface Test {
}
상기 주해 의 @ target 은 이 주 해 는 함수 에 만 사용 할 수 있 고 Type, Field, PARAMETER 등 유형 도 있 으 므 로 상기 참고 자 료 를 참고 할 수 있 습 니 다.반사 api 를 통 해 저 희 는 Class 대상 을 통 해 유형, 속성, 함수 등 관련 대상 을 얻 을 수 있 습 니 다. 이 대상 의 getAnnotation 인 터 페 이 스 를 통 해 해당 하 는 주석 정 보 를 얻 을 수 있 습 니 다.우선 우 리 는 목표 대상 에 주 해 를 추가 해 야 한다. 예 를 들 어:
@Test(tag = "Student class Test Annoatation")
public class Student extends Person implements Examination {
//
@Test(tag = "mGrade Test Annotation ")
int mGrade;
// ......
}
그리고 관련 주해 함 수 를 통 해 주해 정 보 를 얻 으 면 다음 과 같다.
private static void getAnnotationInfos() {
Student student = new Student("mr.simple");
Test classTest = student.getClass().getAnnotation(Test.class);
System.out.println("class Annotatation tag = " + classTest.tag());
Field field = null;
try {
field = student.getClass().getDeclaredField("mGrade");
Test testAnnotation = field.getAnnotation(Test.class);
System.out.println(" Test tag : " + testAnnotation.tag());
} catch (Exception e) {
e.printStackTrace();
}
}
출력 결 과 는: >
class Annotatation tag = Student class Test Annoatation
Test tag : mGrade Test Annotation
인터페이스 설명
//
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) ;
// Class
public Annotation[] getAnnotations() ;
잡담
반 사 는 자바 언어의 중요 한 특성 으로서 개발 에서 매우 중요 한 역할 을 한다.많은 개발 프레임 워 크 는 반 사 를 바탕 으로 목표 대상 에 대한 조작 을 실현 하 는 것 이 고 반사 와 주 해 는 디자인 개발 프레임 워 크 의 주류 선택 이다. 예 를 들 어 ActiveAndroid 는 반사 작용 과 사용 이 향후 개발 과 학습 에 큰 도움 이 될 것 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.