자바 반사 메커니즘 과 동적 에이전트 (1)
자바 반사 메커니즘 은 주로 다음 과 같은 기능 을 제공한다.
실행 할 때 임의의 대상 이 속 한 종 류 를 판단 합 니 다.운행 할 때 임의의 종류의 대상 을 구성한다.실행 할 때 임의의 클래스 가 가지 고 있 는 구성원 변수 와 방법 을 판단 합 니 다.실행 할 때 임의의 대상 을 호출 하 는 방법.
Reflection 은 자바 가 동적 (또는 준 동적) 언어 로 여 겨 지 는 관건 적 인 성질 이다.이 메커니즘 은 프로그램 이 실 행 될 때 Reflection API 를 통 해 알려 진 클 라 스 의 내부 정 보 를 얻 을 수 있 도록 합 니 다. 이 는 modifiers (예 를 들 어 Public, static 등), 슈퍼 클 라 스 (예 를 들 어 Object), 실 현 된 인터페이스 (예 를 들 어 Serializable) 를 포함 하고 fields 와 methods 의 모든 정 보 를 포함 하 며 실 행 될 때 fields 내용 을 바 꾸 거나 methods 를 호출 할 수 있 습 니 다.
일반적으로 개발 자 커 뮤 니 티 는 동적 언어 에 대해 대체적으로 인정 하 는 정 의 는 '프로그램 이 실 행 될 때 프로그램 구조 나 변수 유형 을 바 꿀 수 있 고 이런 언어 를 동적 언어 라 고 부른다' 는 것 이다.
JDK 에서 주로 다음 과 같은 종류 로 자바 반사 체 제 를 실현 합 니 다. 이런 종 류 는 모두 자바. lang. reflect 패키지 에 있 습 니 다. Class 류: 하나의 종 류 를 대표 합 니 다.Field 클래스: 대표 클래스 의 구성원 변수 (구성원 변수 도 클래스 의 속성 이 라 고 함);Method 류: 대표 적 인 방법;Constructor 류: 대표 적 인 구조 방법;Array 클래스: 동적 으로 배열 을 만 들 고 배열 에 접근 하 는 요 소 를 정적 으로 만 드 는 방법 을 제공 합 니 다.
예제 DateMethods Test 클래스 는 Reflection API 의 기본 적 인 역할 을 보 여 줍 니 다. 명령 행 매개 변수 가 지정 한 클래스 이름 을 읽 은 다음 에 이 클래스 가 가지 고 있 는 방법 정 보 를 인쇄 합 니 다. 코드 는 다음 과 같 습 니 다.
public class DateMethodsTest
{
public static void main(String args[]) throws Exception
{
//
Class> classType = Class.forName("java.util.Date");
//
Method methods[] = classType.getDeclaredMethods();
for (int i = 0; i < methods.length; i++)
{
System.out.println(methods[i].toString());
}
}
}
루틴 ReflectTester 클래스 는 Reflection API 의 기본 적 인 사용 방법 을 한층 더 보 여 주 었 다.ReflectTester 클래스 는 copy (Object object) 방법 이 있 습 니 다. 이 방법 은 매개 변수 object 와 같은 유형의 대상 을 만 든 다음 object 대상 의 모든 속성 을 새 대상 에 복사 하고 이 예 를 되 돌려 줍 니 다. 간단 한 자바 빈 만 복사 할 수 있 습 니 다. 자바 빈 의 모든 속성 이 Public 형식의 getXXX () 와 setXXX () 방법 이 있다 고 가정 하면 코드 는 다음 과 같 습 니 다.
public class ReflectTester {
public Object copy(Object object) throws Exception {
//
Class> classType = object.getClass();
System.out.println("Class:" + classType.getName());
//
Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});
//
Field fields[] = classType.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
String fieldName = field.getName();
String firstLetter = fieldName.substring(0, 1).toUpperCase();
// getXXX()
String getMethodName = "get" + firstLetter + fieldName.substring(1);
// setXXX()
String setMethodName = "set" + firstLetter + fieldName.substring(1);
// getXXX()
Method getMethod = classType.getMethod(getMethodName, new Class[] {});
// setXXX()
Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });
// getXXX()
Object value = getMethod.invoke(object, new Object[] {});
System.out.println(fieldName + ":" + value);
// setXXX()
setMethod.invoke(objectCopy, new Object[] { value });
}
return objectCopy;
}
public static void main(String[] args) throws Exception {
Customer customer = new Customer("Tom", 21);
customer.setId(new Long(1));
Customer customerCopy = (Customer) new ReflectTester().copy(customer);
System.out.println("Copy information:" + customerCopy.getId() + " "
+ customerCopy.getName() + " " + customerCopy.getAge());
}
}
class Customer {
private Long id;
private String name;
private int age;
public Customer() {
}
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
ReflectTester 클래스 의 copy (Object object) 방법 은 다음 절 차 를 순서대로 수행 합 니 다.
(1) 대상 을 얻 는 유형: Class classType = object. getClass ();System.out.println("Class:"+classType.getName());
자바. lang. Object 클래스 에서 getClass () 방법 을 정 의 했 기 때문에 임의의 자바 대상 에 대해 서 는 이 방법 을 통 해 대상 의 유형 을 얻 을 수 있 습 니 다.Class 클래스 는 Reflection API 의 핵심 클래스 입 니 다. 다음 과 같은 방법 이 있 습 니 다. getName (): 클래스 의 전체 이름 을 얻 습 니 다.getFields (): 클래스 의 Public 형식의 속성 획득;getDeclared Fields (): 클래스 의 모든 속성 획득;getMethods (): 클래스 의 Public 형식 을 얻 는 방법;getDeclared Methods (): 클래스 를 얻 는 모든 방법;
getMethod (String name, Class [] parameterTypes): 클래스 의 특정한 방법, name 매개 변수 지정 방법의 이름, parameterTypes 매개 변수 지정 방법의 매개 변수 유형 을 얻 을 수 있 습 니 다.
getConstructors (): 클래스 의 Public 유형의 구조 방법 을 얻 습 니 다.getConstructor (Class [] parameterTypes): 클래스 의 특정 구조 방법 을 얻 고 parameterTypes 매개 변 수 는 구조 방법의 매개 변수 유형 을 지정 합 니 다.new Instance (): 클래스 의 매개 변수 가 없 는 구조 방법 으로 이러한 대상 을 만 듭 니 다.
(2) 기본 구조 방법 으로 새 대상 을 만 듭 니 다: Object objectCopy = classType. getConstructor (new Class [] {}). newInstance (new Object [] {});상기 코드 는 먼저 Class 류 의 getConstructor () 방법 을 호출 하여 Constructor 대상 을 얻 습 니 다. 이것 은 기본 적 인 구조 방법 을 대표 하고 Constructor 대상 의 new Instance () 방법 으로 인 스 턴 스 를 구성 합 니 다.
(3) 대상 의 모든 속성 획득: Field fields [] = classType. getDeclared Fields ();Class 류 의 getDeclared Fields () 방법 은 Public, proctected, 기본 값, private 접근 등급 의 속성 을 포함 하여 클래스 의 모든 속성 을 되 돌려 줍 니 다.
(4) 각 속성 에 해당 하 는 getXXX () 와 setXXX () 방법 을 얻 은 다음 에 이 방법 을 실행 하여 원래 대상 의 속성 을 새로운 대상 에 복사 합 니 다.
이상 은 반사 (reflection) 의 비교적 상세 한 해설 이다. 물론 진정한 공사 에 서 는 이렇게 번 거 롭 지 않 을 것 이다. 여 기 는 밑바닥 의 설명 이다.
다음 과 같은 종 류 는 반사 체 제 를 이용 하여 add () 와 echo () 방법 을 호출 하고 코드 는 다음 과 같다.
import java.lang.reflect.Method;
public class InvokeTester {
public int add(int param1, int param2) {
return param1 + param2;
}
public String echo(String msg) {
return "echo: " + msg;
}
public static void main(String[] args) throws Exception {
Class> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
// InvokeTester add()
Method addMethod = classType.getMethod("add", new Class[] { int.class,
int.class });
Object result = addMethod.invoke(invokeTester, new Object[] {
new Integer(100), new Integer(200) });
System.out.println((Integer) result);
// InvokeTester echo()
Method echoMethod = classType.getMethod("echo",
new Class[] { String.class });
result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });
System.out.println((String) result);
}
}
add () 방법의 두 매개 변 수 는 int 형식 입 니 다. add () 방법 을 나타 내 는 Method 대상 의 코드 는 다음 과 같 습 니 다. Method addMethod = classType. getMethod ("add", new Class [] {int. class, int. class});Method 류 의 invoke (Object obj, Object args []) 방법 으로 받 은 매개 변 수 는 대상 이 어야 하 며, 매개 변수 가 기본 형식 데이터 라면 해당 포장 유형의 대상 으로 변환 해 야 합 니 다.invoke () 방법의 반환 값 은 항상 대상 입 니 다. 실제 호출 된 방법의 반환 유형 이 기본 형식 데이터 라면 invoke () 방법 은 해당 하 는 포장 유형의 대상 으로 변환 하여 되 돌려 줍 니 다.
이 예 에서 InvokeTester 류 의 add () 방법의 두 가지 매개 변수 와 반환 값 은 모두 int 형식 임 에 도 불구 하고 add Method 대상 의 invoke () 방법 을 호출 할 때 Integer 형식의 매개 변수 만 전달 할 수 있 고 invoke () 방법의 반환 유형 도 Integer 유형 이 며 Integer 류 는 int 기본 유형의 포장 류 입 니 다.
Object result=addMethod.invoke(invokeTester,new Object[]{new Integer(100),new Integer(200)});System.out.println((Integer)result); //result 는 Integer 형식 입 니 다.
java. lang. Array 류 는 동적 으로 배열 요 소 를 만 들 고 방문 하 는 여러 가지 정적 방법 을 제공 합 니 다.다음 예 Array Tester 1. java 의 main () 방법 은 길이 가 10 인 문자열 배열 을 만 들 었 습 니 다. 이 어 색인 위치 가 5 인 요 소 를 "hello" 로 설정 한 다음 색인 위치 가 5 인 요소 의 값 을 읽 습 니 다. 코드 는 다음 과 같 습 니 다.
import java.lang.reflect.Array;
public class ArrayTester1
{
public static void main(String args[]) throws Exception
{
Class> classType = Class.forName("java.lang.String");
// 10
Object array = Array.newInstance(classType, 10);
// 5 "hello"
Array.set(array, 5, "hello");
// 5
String s = (String) Array.get(array, 5);
System.out.println(s);
}
}
자바 API 는 좋 은 도움말 자료 이 니 찾 아 보 세 요.예 를 들 어 상기 예: classType 은 String 형식의 대상 입 니 다.Array 클래스 의 new Instance (형식, 길이) 를 통 해 길이 가 10 인 String 인 Array 배열 을 만 들 었 습 니 다.Array 의 get 과 set 방법 을 통 해 5 (실제로는 Array 의 여섯 번 째 요소) 로 표 시 된 '배열 사각형' 에 문자열 'hello' 를 삽입 할 수 있 습 니 다.
다음 예 는 복잡 한 다 차원 배열 의 예 이지 만 1 차원 배열 만 알 면 다 차원 배열 을 이해 하기 어렵 지 않 을 것 이다.다 차원 배열 이란 하급 배열 이 하나의 '요소' 로 서 상급 배열 에 존재 할 뿐이다.
예 를 들 어 Array Tester 2 류 의 main () 방법 은 5 x 10 x 15 의 전체 배열 을 만 들 고 색인 위 치 를 [3] [5] [10] [10] 요소 의 값 을 37 로 설정 합 니 다. 코드 는 다음 과 같 습 니 다.
import java.lang.reflect.Array;
public class ArrayTester2
{
public static void main(String args[])
{
int[] dims = new int[] { 5, 10, 15 };
Object array = Array.newInstance(Integer.TYPE, dims);
Object arrayObj = Array.get(array, 3);
Class> cls = arrayObj.getClass().getComponentType();
System.out.println(cls);
arrayObj = Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int arrayCast[][][] = (int[][][]) array;
System.out.println(arrayCast[3][5][10]);
}
}
Class 는 Reflection 의 기원 입 니 다.탐색 하고 싶 은 class 에 대해 서 는 먼저 Class object 를 만들어 야 후자 가 수 십 여 개의 Reflection API 를 불 러 올 수 있 습 니 다.
자바 에 서 는 클래스 에 대응 하 는 클래스 object 를 여러 경로 로 생 성 할 수 있 습 니 다.
(1) getClass () 방법 활용:
String str = "abc";
Class class = str.getClass();
(2) Class. getSuperclass () 방법 활용:
Button b = new Button();
Class c1 = b.getSuperclass();
Class c2 = c1.getSuperclass();
(3) 정적 방법 Class. forName () 을 사용 합 니 다.
Class c1 = Class.forName("java.lang.String");
Class c2 = Class.forName("java.util.Date");
(4). class 문법 활용:
Class c1 = String.class;
Class c2 = java.awt.Button.class;
Class c3 = int.class;
Class C4 = int[].class;
(5) 원시 포장 류 의 TYPE 방법 활용:
Class c1 = Integer.TYPE;
Class c2 = Character.TYPE;
Class c3 = Boolean.TYPE;
Class c4 = Void.TYPE;
이 다섯 가지 방법 을 통 해 우리 가 원 하 는 대상 을 만 들 수 있다.
[전환:http://phoenix-ghk.iteye.com/blog/392743]
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
어떻게 ASP에서NET Core에서 ViewComponent 사용이전의 개발 과정에서 우리는 응용이나 작은 구성 요소에 대해 분포 페이지(partial view)를 사용하고 앞으로 웹 Form에서 응용WEB Control을 할 것이다. 이런 표시를 통해 우리는 우리web form...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.