【Java】--반사(Java)
27821 단어 자바
, , 。 , 。 C, , 。
Brian Cantwell Smith 1982 , meta-circular 3-Lisp 。
무엇
: (run time) 、 。( )
왜 반 사 를 사용 합 니까?
Java 。 , 。 , , 。
4.567917.확장 가능 한 특징 응용 프로그램 은 전체 한 정 된 이름 으로 확장 가능 한 대상 을 만 드 는 인 스 턴 스 를 통 해 외부 사용자 가 정의 하 는 클래스 를 사용 할 수 있 습 니 다
4.567917.클래스 브 라 우 저 와 시각 화 개발 환경 브 라 우 저 는 매 거 진 클래스 의 구성원 이 필요 합 니 다.시각 화 개발 환경 은 반 영 된 유형 정 보 를 이용 하여 개발 자 들 이 정확 한 코드 를 작성 하 는 데 도움 을 줄 수 있다
4.567917.디 버 거 와 테스트 도구 디 버 깅 자 는 수업 시간 에 개인 구성원 을 검사 할 수 있어 야 한다.테스트 빔 은 클래스 에 정 의 된 발견 가능 한 집합 API 를 반사 시스템 으로 호출 하여 테스트 세트 의 높 은 수준의 코드 를 덮어 쓸 수 있 도록 합 니 다
적용 장면 이 뭐 예요?
1).자바 의 반사 체 제 는 기본 구 조 를 만 들 때 매우 유용 하 다.한 마디 로 반사 체 제 는 많은 자바 구조의 초석 이다.일반적인 응용 차원 에 서 는 거의 사용 되 지 않 지만 이런 물건 은 현재 많은 오픈 소스 프레임 워 크 가 기본적으로 당신 에 게 포장 되 어 있 고 자신 은 거의 쓸 필요 가 없습니다.전형 적 인 것 은 hibenate 외 에 도 spring 도 많은 반사 체 제 를 사용한다.전형 적 인 것 은 xml 파일 이나 properties 에 설정 을 작성 한 다음 에 자바 류 에서 xml 또는 properties 안의 내용 을 분석 하고 문자열 을 얻 은 다음 에 반사 체 제 를 사용 하여 이 문자열 에 따라 특정한 클래스 의 Class 인 스 턴 스 를 얻 으 면 동적 으로 무언 가 를 배치 할 수 있 습 니 다.매번 코드 에서 new 나 다른 일 을 하지 않 아 도 됩 니 다.나중에 고 치 려 면 설정 파일 을 직접 고 쳐 야 합 니 다.코드 를 유지 하 는 것 이 편리 합 니 다.또한 가끔 은 특정한 수요 에 적응 해 야 합 니 다.자바 류 에서 반드시 다른 방법 을 직접 호출 할 수 있 는 것 이 아니 라 반사 체 제 를 통 해 이 루어 질 수 있 습 니 다.전체적으로 말 하면 자신 이 쓴 것 이 매우 적다.구체 적 으로 언제 그것 을 사용 해 야 하 는 지 는 수 요 를 봐 야 한다.반사 체 제 는 하나의 String 에 따라 당신 이 원 하 는 실체 대상 을 얻 은 다음 에 원래 의 것 을 호출 하 는 것 이다.하지만 스스로 틀 을 쓰 려 면 많이 쓴다.
2)소프트웨어 를 만 들 면 플러그 인의 기능 을 설치 할 수 있 습 니 다.플러그 인의 유형 이름 도 모 르 는데 이 대상 을 어떻게 예화 합 니까?프로그램 은 플러그 인(제3자)을 지원 하기 때문에 개발 할 때 몰 랐 습 니 다.그래서 코드 에서 New 를 나 올 수 없 지만 반사 할 수 있 습 니 다.반사,동적 로드 프로그램 집합 을 통 해 클래스 를 읽 고 표 시 를 검사 한 후에 대상 을 예화 하면 정확 한 인 스 턴 스 를 얻 을 수 있 습 니 다.
3)인 코딩 단계 에서 그 클래스 이름 을 모 릅 니 다.설정 파일 에서 클래스 이름 을 읽 으 려 면 new ClassName()을 하 드 인 코딩 할 방법 이 없습니다.반 사 를 사용 해 야 이 대상 을 만 들 수 있 습 니 다.반 사 는 알 수 없 는 응용 프로그램 을 확장 하기 위 한 것 입 니 다.예 를 들 어 프로그램 을 썼 습 니 다.이 프로그램 은 인 터 페 이 스 를 정 의 했 습 니 다.이 인터페이스의 dll 을 실현 하면 플러그 인 으로 이 프로그램 에 삽입 할 수 있 습 니 다.그럼 어떻게 이 루어 질 까요?반 사 를 통 해 이 루어 질 수 있다.dll 을 메모리 에 불 러 오고 반사 적 으로 dll 을 호출 하 는 방법 입 니 다.많은 공장 모델 이 바로 사용 하 는 반사 이다.
실례
반사 가 어떻게 일 하 는 지 알 고 싶 으 면 이 간단 한 예 를 고려 하 세 요.
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
호출:
java DumpMethods java.util.Stack
출력:
public java.lang.Object java.util.Stack.push(
java.lang.Object)
public synchronized
java.lang.Object java.util.Stack.pop()
public synchronized
java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized
int java.util.Stack.search(java.lang.Object)
즉,자바 util.stack 과 같은 방법 이름과 그들의 모든 한정 매개 변수 와 반환 유형 을 보 여 줍 니 다.
이 프로그램 은 class.forName 을 사용 하여 지정 한 클래스 를 불 러 오고 getDeclared Methods 를 사용 하여 클래스 에서 정의 하 는 방법 목록 을 검색 합 니 다.java.lang.reflect.Method 는 단일 한 방법 을 나타 내 는 클래스 입 니 다.
사용 반사 설정
반사 류,예 를 들 어 Method,java.lang.reflect 에서 찾 을 수 있 습 니 다.이런 종 류 를 사용 하려 면 반드시 세 가지 절 차 를 따라 야 한다.첫 번 째 단 계 는 작 동 할 클래스 를 위해 자바.lang.class 대상 을 가 져 오 는 것 입 니 다.java.lang.class 는 실행 중인 자바 프로그램의 클래스 와 인 터 페 이 스 를 표시 하 는 데 사 용 됩 니 다.
Class 대상 을 가 져 오 는 방법 은:
Class c = Class.forName("java.lang.String");
String 의 Class 대상 을 가 져 옵 니 다.다른 방법 은 다음 과 같다.
Class c = int.class;
or
Class c = Integer.TYPE;
기본 형식의 클래스 정 보 를 가 져 옵 니 다.다음 방법 은 기본 유형의 포장 기의 미리 정 의 된 TYPE 필드(예 를 들 어 정수)에 접근 합 니 다.두 번 째 단 계 는 getDeclared Methods 등 방법 으로 이 성명 의 모든 방법 을 가 져 오 는 목록 입 니 다.
이 정 보 를 손 에 쥐 면 세 번 째 단 계 는 반사 API 를 사용 해 정 보 를 조작 하 는 것 이다.예 를 들 어 시퀀스:
Class c = Class.forName("java.lang.String");
Method m[] = c.getDeclaredMethods(); System.out.println(m[0].toString());
String 에서 설명 하 는 첫 번 째 방법의 텍스트 를 표시 합 니 다.다음 의 예 에서 세 가지 절 차 를 결합 시 켜 반 사 를 어떻게 사용 하여 구체 적 인 응용 을 해결 하 는 지 보 여 준다.
아 날로 그 연산 자의 인 스 턴 스
클 라 스 정보 가 손 에 있 으 면 보통 다음 단 계 는 클 라 스 대상 에 대한 기본 적 인 질문 이다.예 를 들 어 Class.isInstance 방법 은 instanceof 연산 자 를 모 의 하 는 데 사용 할 수 있 습 니 다.
class A {}
public class instance1 {
public static void main(String args[])
{
try {
Class cls = Class.forName("A");
boolean b1
= cls.isInstance(new Integer(37));
System.out.println(b1);
boolean b2 = cls.isInstance(new A());
System.out.println(b2);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
이 예제 에서 A 에 사용 할 Class 대상 을 만 든 다음 클래스 인 스 턴 스 대상 을 검사 하여 A 의 인 스 턴 스 인지 확인 합 니 다.integer(37)는 아니 지만 new A()는.
한 가지 방법 을 찾아내다
반성 의 가장 가치 있 고 기본 적 인 사용 중 하 나 는 수업 시간 에 정 의 된 방법 을 찾 는 것 이다.이 를 위해 다음 코드 를 사용 할 수 있 습 니 다.
import java.lang.reflect.*;
public class method1 {
private int f1(
Object p, int x) throws NullPointerException
{
if (p == null)
throw new NullPointerException();
return x;
}
public static void main(String args[])
{
try {
Class cls = Class.forName("method1");
Method methlist[]
= cls.getDeclaredMethods();
for (int i = 0; i < methlist.length;
i++) {
Method m = methlist[i];
System.out.println("name
= " + m.getName());
System.out.println("decl class = " +
m.getDeclaringClass());
Class pvec[] = m.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("
param #" + j + " " + pvec[j]);
Class evec[] = m.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exc #" + j
+ " " + evec[j]);
System.out.println("return type = " +
m.getReturnType());
System.out.println("-----");
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
프로그램 은 먼저 method 1 의 클래스 설명 을 가 져 온 다음 getDeclared Methods 를 호출 하여 Method 대상 목록 을 검색 합 니 다.클래스 에서 정의 하 는 모든 방법 입 니 다.Public,proctected,package,private 방법 을 포함 합 니 다.프로그램 에서 getDeclared Methods 가 아 닌 getMethods 를 사용 하면 계승 방법 에 대한 정 보 를 얻 을 수 있 습 니 다.Method 대상 의 목록 을 얻 으 면 매개 변수 유형,이상 유형,각 방법의 반환 유형 에 대한 정 보 를 표시 합 니 다.이러한 유형의 모든 종 류 는 기본 클래스 든 클래스 유형 이 든 모두 Class 설명자 에 의 해 표 시 됩 니 다.프로그램의 출력 은:
name = f1
decl class = class method1
param #0 class java.lang.Object
param #1 int
exc #0 class java.lang.NullPointerException
return type = int
-----
name = main
decl class = class method1
param #0 class [Ljava.lang.String;
return type = void
-----
구조 함수 에 대한 정 보 를 얻 는 유사 한 방법 은 클래스 의 구조 함 수 를 이해 하 는 데 사용 된다.예 를 들 면:
import java.lang.reflect.*;
public class constructor1 {
public constructor1()
{
}
protected constructor1(int i, double d)
{
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor1");
Constructor ctorlist[]
= cls.getDeclaredConstructors();
for (int i = 0; i < ctorlist.length; i++) {
Constructor ct = ctorlist[i];
System.out.println("name
= " + ct.getName());
System.out.println("decl class = " +
ct.getDeclaringClass());
Class pvec[] = ct.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #"
+ j + " " + pvec[j]);
Class evec[] = ct.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println(
"exc #" + j + " " + evec[j]);
System.out.println("-----");
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
이 예제 에서 반환 형식의 정 보 를 검색 하지 못 했 습 니 다.구조 함수 가 실제 반환 형식 이 없 기 때 문 입 니 다.이 프로그램 을 실행 할 때 출력 은:
name = constructor1
decl class = class constructor1
-----
name = constructor1
decl class = class constructor1
param #0 int
param #1 double
-----
클래스 필드 찾기
클래스 에서 정 의 된 데이터 필드 도 찾 을 수 있다.이 를 위해 다음 코드 를 사용 할 수 있 습 니 다.
import java.lang.reflect.*;
public class field1 {
private double d;
public static final int i = 37;
String s = "testing";
public static void main(String args[])
{
try {
Class cls = Class.forName("field1");
Field fieldlist[]
= cls.getDeclaredFields();
for (int i
= 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("name
= " + fld.getName());
System.out.println("decl class = " +
fld.getDeclaringClass());
System.out.println("type
= " + fld.getType());
int mod = fld.getModifiers();
System.out.println("modifiers = " +
Modifier.toString(mod));
System.out.println("-----");
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
이 예 는 이전의 예 와 비슷 하 다.새로운 기능 은 Modifier 를 사용 하 는 것 입 니 다.이것 은 필드 구성원 에서 찾 은 수정자,예 를 들 어'private int'를 나타 내 는 반영 류 입 니 다.수정자 자 자 체 는 정수 로 표시 되 며,Modifier.toString 은'공식'성명 순서 로 문자열 표시 형식(예 를 들 어'final'이전의'static')을 되 돌려 줍 니 다.프로그램의 출력 은:
name = d
decl class = class field1
type = double
modifiers = private
-----
name = i
decl class = class field1
type = int
modifiers = public static final
-----
name = s
decl class = class field1
type = class java.lang.String
modifiers =
-----
방법 과 마찬가지 로 클래스(getDeclared Fields)에서 설명 한 필드 에 대한 정 보 를 얻 을 수 있 고,클래스(getFields)에서 정 의 된 필드 에 대한 정 보 를 얻 을 수 있 습 니 다.
이름 호출 방법
지금까지 제 공 된 예 는 모두 수업 정 보 를 얻 는 것 과 관련 이 있다.그러나 지 정 된 이름 을 호출 하 는 방법 과 같은 다른 방식 으로 반 사 를 사용 할 수도 있다.
어떻게 일 하 는 지 알 고 싶 으 면 다음 과 같은 예 를 고려 하 세 요.
import java.lang.reflect.*;
public class method2 {
public int add(int a, int b)
{
return a + b;
}
public static void main(String args[])
{
try {
Class cls = Class.forName("method2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod(
"add", partypes);
method2 methobj = new method2();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj
= meth.invoke(methobj, arglist);
Integer retval = (Integer)retobj;
System.out.println(retval.intValue());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
프로그램 이 add 방법 을 호출 하려 고 한다 고 가정 하지만 실행 할 때 까지 알 수 있 습 니 다.즉,방법의 명칭 은 실행 기간 에 지정 된다(예 를 들 어 자바 빈 스 개발 환경 에서 완성 할 수 있다).위의 프로그램 은 이렇게 하 는 방법 을 보 여 주 었 다.getMethod 는 클래스 에서 두 개의 정수 매개 변수 유형 을 가지 고 적당 한 이름 을 가 진 방법 을 찾 는 데 사 용 됩 니 다.이 방법 이 발견 되 고 하나의 방법 대상 에 포착 되면 적당 한 유형의 대상 인 스 턴 스 를 호출 합 니 다.하나의 방법 을 호출 하려 면 매개 변수 목록 을 구성 해 야 합 니 다.그 중에서 전체 수치 37 과 47 은 정수 대상 에 포함 되 어 있 습 니 다.반환 값(84)도 정수 대상 에 싸 여 있다.
새 개체 만 들 기
구조 함 수 를 호출 하 는 것 은 새로운 대상 을 만 드 는 것 과 같 기 때문에 구조 함수 와 같은 방법 으로 호출 되 지 않 습 니 다.그래서 가장 가 까 운 예 는 다음 과 같다.
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
지정 한 매개 변수 형식 을 처리 하고 호출 하여 대상 의 새로운 인 스 턴 스 를 만 들 수 있 는 구조 함 수 를 찾 았 습 니 다.이 방법의 가 치 는 컴 파일 할 때 구조 함수 로 찾 고 호출 하 는 것 이 아니 라 순 전 히 동적 인 것 이다.필드 의 값 반 사 를 바 꾸 는 또 다른 용 도 는 대상 의 데이터 필드 의 값 을 바 꾸 는 것 이다.이 값 은 반 사 된 동적 특성 에서 다시 나 옵 니 다.그 중에서 실행 프로그램의 이름 을 통 해 필드 를 찾 은 다음 값 을 바 꿀 수 있 습 니 다.이것 은 다음 과 같은 예 시 를 통 해 설명 한다.
import java.lang.reflect.*;
public class field2 {
public double d;
public static void main(String args[])
{
try {
Class cls = Class.forName("field2");
Field fld = cls.getField("d");
field2 f2obj = new field2();
System.out.println("d = " + f2obj.d);
fld.setDouble(f2obj, 12.34);
System.out.println("d = " + f2obj.d);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
이 예제 에서 d 필드 의 값 은 12.34 로 설정 되 어 있 습 니 다.
배열 사용
반성 의 마지막 용 도 는 배열 을 만 들 고 조작 하 는 것 이다.자바 언어의 배열 은 전문 적 인 클래스 로 배열 인용 은 Object 에 할당 할 수 있 습 니 다.
배열 이 어떻게 작 동 하 는 지 알 고 싶 으 면 다음 과 같은 예 를 고려 하 십시오.
import java.lang.reflect.*;
public class array1 {
public static void main(String args[])
{
try {
Class cls = Class.forName(
"java.lang.String");
Object arr = Array.newInstance(cls, 10);
Array.set(arr, 5, "this is a test");
String s = (String)Array.get(arr, 5);
System.out.println(s);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
이 예제 에 서 는 10 개의 긴 문자열 배열 을 만 든 다음 배열 의 위치 5 를 문자열 값 으로 설정 합 니 다.이 값 을 검색 하고 표시 합 니 다.더 복잡 한 배열 작업 은 다음 코드 와 같 습 니 다.
import java.lang.reflect.*;
public class array2 {
public static void main(String args[])
{
int dims[] = new int[]{5, 10, 15};
Object arr
= Array.newInstance(Integer.TYPE, dims);
Object arrobj = Array.get(arr, 3);
Class cls =
arrobj.getClass().getComponentType();
System.out.println(cls);
arrobj = Array.get(arrobj, 5);
Array.setInt(arrobj, 10, 37);
int arrcast[][][] = (int[][][])arr;
System.out.println(arrcast[3][5][10]);
}
}
이 예제 에 서 는 5 x 10 x 15 의 int 배열 을 만 든 다음 에 배열 의 위 치 를[3][5][10][10]값 37 로 설정 합 니 다.다 차원 배열 은 실제 배열 이기 때문에 예 를 들 어 첫 번 째 Array.get 이후 arrobj 의 결 과 는 10 x 15 의 배열 입 니 다.15 개의 긴 배열 을 얻 기 위해 서 이 배열 의 10 번 째 슬롯 은 Array.setInt 로 설정 되 어 있 습 니 다.생 성 된 배열 의 유형 은 동적 입 니 다.컴 파일 할 때 꼭 알 아야 할 것 은 아 닙 니 다.
총결산
자바 반 사 는 클래스 와 데이터 구조 에 대한 정 보 를 이름 동적 으로 검색 하고 실행 중인 자바 프로그램 에서 조작 할 수 있 도록 지원 하기 때문에 유용 합 니 다.이 기능 은 매우 강해 서 다른 일반적인 언어(예 를 들 어 C,C+,Fortran 또는 Pascal)에서 비슷 한 점 이 없다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.