편집 기간 동안 수업 받기에 대한 다양한 정보를 제공하는 것 외에도 Java는 반사 기간 동안 클래스에 대한 다양한 정보를 얻을 수 있습니다. 반사를 통해 수업 정보를 검색하고 클래스 정보를 얻은 후 다음 관련 내용을 얻을 수 있습니다.
이 기사는 또한 위의 측면에서 Java 반사를 소개합니다. 이 기사와 관련된 모든 코드는 반영됩니다
먼저, Java 클래스는 반사의 연구 대상으로 출시됩니다. 수업의 내용은 다음과 같습니다.
공개 초록 클래스 ausherobject emplements runnable {public void dosomething () {System.out.println ( "do things ..."); }} public class exampleObject 확장 ashoybject {public int age = 30; 공개 문자열 이름 = "byhieg"; 개인 정수 점수 = 60; public void printname () {System.out.println (이름); } public int getage () {반환 연령; } public void 설정 (int Age) {this.age = age; } public String getName () {return name; } public void setName (문자열 이름) {this.name = 이름; } public Integer getScore () {반환 점수; } public void setScore (정수 점수) {this.score = score; } public exampleObject () {} public exampleObject (문자열 이름) {} public exampleObject (int age, integer score) {} @override public void dosomething () {super.dosomething (); } @override public void run () {System.out.println ( "run ..."); }}클래스 객체
우리의 응용 프로그램은 반사의 지식 지점을 사용합니다. 런타임에 클래스 정보를 얻고 클래스 정보를 기반으로 특정 작업을 수행해야합니다. 그런 다음 첫 번째는 클래스의 정보를 얻는 것이며, 클래스의 정보를 저장하기 위해 JDK에 클래스 객체가 제공됩니다. 따라서 반사의 첫 번째 단계는 클래스 객체를 얻는 것입니다. JDK에서 클래스 객체를 얻는 두 가지 방법이 있습니다.
첫 번째는 코드를 작성할 때 클래스 이름을 알고 있다면 다음과 같은 방식으로 클래스 객체를 직접 얻을 수 있다는 것입니다.
Class exampleObjectClass = ExampleObject.class;
두 번째 유형은 코드를 작성할 때 클래스 이름을 모르지만 런타임에 클래스 이름을 얻을 수 있으며 다음과 같은 방식으로 클래스 객체를 얻을 수 있다는 것입니다.
Class exampleObjectClass = Class.forName("cn.byhieg.reflectiontutorial.ExampleObject");
이 방법에는 두 가지 조건이 필요합니다. 첫째, Forname의 문자열은 완전히 자격을 갖춘 이름이어야하며, 둘째, 클래스 클래스는 클래스 경로의 경로 아래에 있어야합니다. 메소드는 ClassNotFoundException을 제외하고 이루어지기 때문입니다.
이 클래스 객체를 얻은 후에는 클래스에 대한 다양한 정보를 얻을 수 있습니다. 처음에는 일부 정보가 언급되었습니다. 아래에서 언급되지 않은 수업에 대한 정보에 대해 이야기 해 봅시다.
수업의 이름을 얻으십시오
클래스의 이름을 얻는 두 가지 방법이 있습니다. 하나는 getName ()이고 다른 하나는 getSimplename ()입니다. 첫 번째 이름은 완전히 자격을 갖춘 이름을 얻고 두 번째 이름은 패키지 이름이없는이 클래스의 이름을 얻습니다. 다음 예를보십시오. 위의 코드를 통해 얻은 클래스 객체.
String fullClassName = exampleObjectClass.getName (); String SimpleClassName = exampleObjectClass.getSimplename (); System.out.println (fullclassName); System.out.println (SimpleClassName); System.out.println (SimpleClassName);
결과는 다음과 같습니다.
Cn.ByHieg.ReflectionTutorial.exampleBjectExampleBject
클래스의 패키지 이름, 부모 클래스 및 구현 인터페이스 받기
클래스의 패키지 이름과 부모 클래스는 다음 코드를 통해 얻을 수 있습니다.
// 패키지 정보 패키지 가져 오기 apackage = exampleObjectClass.getPackage (); System.out.println (Apackage); // 상위 클래스를 받기 수퍼 클래스 = exampleObjectClass.getSuperClass (); System.out.println (superClass.getSimplename ());
결과는 다음과 같습니다.
패키지 CN.ByHieg.reflectionTutorialFatherObject
분명히 부모 클래스의 반환 값을 얻는 것도 클래스 객체입니다. 그런 다음이 개체를 사용하여 상위 클래스가 추상 클래스인지 판단하는 등 부모 클래스에 대한 정보를 얻을 수 있습니다.
System.out.println("父类是不是抽象类" + Modifier.isAbstract(superClass.getModifiers()));
get -modifiers는 클래스 수정자를 얻을 수 있으므로 클래스 수정자를 얻을 수 있습니다. 물론,이 get -modifiers는 클래스 객체라고 불릴 수있을뿐만 아니라 메소드 객체를 호출 할 수 있습니다.
java.lang.reflect.modifier 클래스의 메소드를 사용하여 수정 자의 유형을 확인할 수 있습니다.
modifier.isabstract (int modifiers); modifier.isfinal (int modifiers); modifier.isinterface (int modifiers); modifier.isnative (int modifiers); modifier.isprivate (int modifiers); modifier.isprotected (int modifer); modifier (int); modifiers); modifier.isstrict (int modifiers); modifier.issynchronized (int modifiers); modifier.istransient (int modifiers); modifier.isvolatile (int modifiers);
또한 부모 클래스에서 구현 한 인터페이스를 얻을 수도 있습니다.
// 인터페이스 클래스를 가져옵니다 [] classe = superClass.getInterfaces (); System.out.println ( "상위 클래스의 인터페이스" + 클래스 [0]);
Java 클래스는 많은 인터페이스를 구현할 수 있으므로 배열을 사용하지만 실제로 사용하면 먼저 배열의 길이를 결정해야합니다.
아래에서 위의 나열된 내용을 설명하는 데 중점을 둘 것입니다.
건설자
Java 반사를 사용하면 클래스 생성자를 얻고 생성자를 기반으로 런타임에 객체를 동적으로 생성 할 수 있습니다. 먼저 Java는 다음과 같이 생성자의 인스턴스를 얻습니다.
// ConstructOrconstructor [] constructors = exampleObjectClass.getConstructors (); for (생성자 생성기 : 생성자) {System.out.println (생성기 .toString ()); }결과는 다음과 같습니다.
public cn.byhieg.reflectionTutorial.exampleBject (int, java.lang.integer) public cn.byhieg.reflectionTutorial.exampleObject (java.lang.string) public cn.byhieg.beyhieg.
생성자의 매개 변수 유형을 미리 액세스 할 수있는 경우 다음 방법을 사용하여 다음과 같이 지정된 생성자를 얻을 수 있습니다.
생성자 생성자 = exampleObjectClass.getConstructor (String.class); System.out.println (생성기 .toString ());
결과는 분명히 다음과 같습니다.
public cn.byhieg.reflectiontutorial.ExampleObject(java.lang.String)
다른 생성자도 다음 방법으로 얻을 수 있습니다.
생성자 생성기 = exampleObjectClass.getConstructor (int.class, integer.class); System.out.println (생성기 .toString ());
또한 생성자 매개 변수를 모르고 모든 생성자 객체 만 얻을 수있는 경우 각 생성자가 다음과 같이 사용하는 매개 변수를 얻을 수 있습니다.
생성자 [] 생성자 = exampleObjectClass.getConstructors (); for (생성자 생성자 : 생성자) {class [] parametertypes = constructor.getParameterTypes (); System.out.println ( "생성자 매개 변수는 다음과 같습니다 다음 ======================================================================= ================================================================================= for (clz : parametertypes) {system.out.println ( "parametertype" + clz.toString ());결과는 다음과 같습니다.
생성자 매개 변수는 다음과 같습니다.
여기서는 매개 변수가없는 구조 방법이 결과를 인쇄하지 않음을 알 수 있습니다. 기본 유형의 클래스 객체와 참조 유형의 클래스 객체는 다릅니다.
이제 생성자의 다양한 정보를 기반으로 객체를 동적으로 만들 수 있습니다.
Object 객체 = Constructor.newinstance (1,100); System.out.println (Object.toString ());
객체를 만드는 두 가지 조건이 있습니다. 첫 번째는 매개 변수 생성자를 통해 생성됩니다. 두 번째는 생성자 객체를 매개 변수 정보를 전달하는 getConstructor를 통해 얻어야한다는 것입니다.
첫 번째 조건은 매개 변수 구성 방법없이 만들 수있는 객체의 경우 생성자 객체를 얻을 필요가 없다는 것입니다. 클래스 객체는 NewInstance () 메소드를 호출하고 객체를 직접 생성합니다.
두 번째 조건은 생성자 객체가 exampleObjectClass.getConstructor (String.class)를 통해 얻어야한다는 것입니다. GetConstructors를 통해 생성자 배열을 가져온 다음 지정된 생성자 객체를 호출하여 JDK1.8에서 객체를 작성하는 것은 잘못입니다. 그러나 JDK1.6은 정상입니다.
변하기 쉬운
Java Reflection을 사용하면 런타임에 클래스의 가변 정보를 얻을 수 있으며 위의 방법에 따라 객체를 생성하고 변수 값을 설정할 수 있습니다. 먼저, 모든 공개 변수는 다음 방법에 따라 얻습니다.
필드 [] fields = exampleObjectClass.getFields (); for (필드 필드 : 필드) {System.out.println ( "변수는" + field.toString ()); }결과는 다음과 같습니다.
변수는 : public int cn.byhieg.reflectiontutorial.examplebject.age 변수는 : public java.lang.string cn.byhieg.reflectiontutorial.examplebject.name입니다.
분명히, 획득 된 모든 공개 변수는 공개적이며 위의 개인 변수 점수는 얻지 못합니다.
생성자와 동일한 방식으로 매개 변수 이름을 지정한 다음 지정된 변수를 얻을 수 있습니다.
필드 필드 = exampleObjectClass.getField ( "Age"); System.out.println ( "변수 :" + field.toString ());
위 변수의 Tostring 방법에 의해 얻은 이름은 너무 길다. Java는 GetName 메소드를 필드 클래스에 제공하며 클래스에 작성된 변수의 이름을 반환합니다. 위의 코드는 Field.getName ()로 변경 될 수 있습니다.
반사는 변수를 얻는 방법을 제공 할뿐만 아니라 변수 값을 설정하는 방법을 제공합니다. 다음 방법을 따르면 동적으로 생성 된 클래스의 변수 값을 변경할 수 있습니다.
exampleObject Object = ((exampleObject) constructor1.newinstance ( "byHieg")); System.out.println ( "원래 연령은" + object.age); field.set (Object, 10); System.out.println ( "변경 후 나이는" + object.age);
결과는 다음과 같습니다.
원래 연령은 30 세이고 변화 후 나이는 10입니다.
위의 코드에 따르면 Age라는 필드 객체를 얻은 다음 객체의 설정 방법을 호출하고 변경할 값을 전달한 다음 객체의 값을 변경할 수 있습니다. 이 방법은 멤버 변수뿐만 아니라 정적 변수에도 유용합니다. 물론 정적 변수라면 물체를 전달하지 않고 널을 통과해도됩니다.
방법
Java Reflection은 클래스의 가변 정보를 제공하는 것 외에도 방법 정보를 제공합니다. 반사를 통해 메소드 이름, 메소드 매개 변수, 메소드 리턴 유형 및 호출 메소드를 얻을 수 있습니다.
먼저 다음 코드를 통해 메소드를 가져옵니다.
// 출력 클래스 메소드의 공개 메소드 [] method = exampleObjectClass.getMethods (); for (method method : method) {system.out.println ( "method ="+ method.getname ()); }변수를 얻는 것과 같이 익숙해 보이는 코드. getName은 클래스에 작성된 메소드 이름을 얻기 위해 바로 여기에 호출됩니다. 이것을 작성한 후, 자바는 파라미터를 기반으로 특정 방법을 제공한다고 자연스럽게 생각해야합니다.
메소드 메소드 = exampleObjectClass.getMethod ( "설정지", int.class); System.out.println (Method.getName ());
여기서 차이점은 getMethod 메소드가 매개 변수 유형 정보를 전달해야한다는 것입니다. 반사는 메소드 매개 변수 및 리턴 유형을 얻는 메소드를 제공합니다. 방법 매개 변수를 얻는 예는 다음과 같습니다.
메소드 메소드 = exampleObjectClass.getMethod ( "설정지", int.class); System.out.println (Method.getName ()); for (clz : method.getParameterTypes ()) {system.out.println ( "메소드의 매개 변수" + clz.getName ()); }결과는 다음과 같습니다.
설정지 방법의 매개 변수 int
메소드 리턴 유형을 얻는 예는 다음과 같습니다.
System.out.println(method.getReturnType().getName());
결과는 다음과 같습니다.
void
또한 Java Reflection은 호출 호출을 통해 얻은 방법을 지원합니다. 예는 다음과 같습니다.
method.invoke(exampleObjectClass.newInstance(),1);
첫 번째 매개 변수 호출은이 객체이고, 두 번째 매개 변수는 가변 길이 배열이고, 메소드의 매개 변수가 전달됩니다. 필드 객체와 마찬가지로 정적 메소드의 경우 null을 전달하고 정적 메소드를 호출 할 수 있습니다.
개인 변수 및 개인 방법
위의 방법은 공개 방법과 변수 만 얻을 수 있지만 비공개 수정 방법 및 변수를 얻을 수는 없습니다. Java는 비공개 변수 및 방법을 얻는 추가 방법을 제공합니다. 즉, 개인 변수와 방법은 getDeclaredfields 및 getDeclaredMethods 방법을 통해 얻습니다. 또한 지정된 변수 이름 및 메소드 이름을 얻기 위해 getDeclaredfield (변수 이름) 및 getDeclaredMethod (메소드 이름)의 사용을 지원합니다. 그러나 이러한 방식으로 얻은 필드 객체 및 메소드 객체는 직접 사용할 수 없습니다. 이러한 객체는 정상적인 사용을 위해 setAccessible (true)이라고해야합니다. 다음 방법은 위에서 언급 한 것과 동일 할 수 있습니다.
주석
먼저 주석이 포함 된 클래스를 작성하십시오.
@MyAnnotation (name = "byHieg", value = "Hello World") public class annotationObject { @myAnnotation (name = "field", value = "variable") 공개 문자열 필드; @MyAnnotation (name = "method", value = "method") public void dosomething () {system.out.println ( "do something"); } public void dootherthing (@myAnnotation (name = "param", value = "param") {}}@rendent (retentionpolicy.runtime) public @interface myAnnotation {public String name (); 공개 문자열 값 ();}Java는 런타임에 클래스 주석을 얻는 것에 대한 정보를 제공하며 클래스 주석, 메소드 주석, 매개 변수 주석 및 가변 주석을 얻을 수 있습니다.
위의 획득 방법과 마찬가지로 Java는 두 가지 획득 방법을 제공합니다. 하나는 모든 주석을 얻고 배열을 반환하는 것이고, 두 번째는 지정된 주석을 지정하는 것입니다.
다음 두 가지 방법을 설명하기 위해 수업 주석을 예로 들어 봅시다.
클래스 clz = AnnotationObject.class; 주석 [] 주석 = clz.getAnnotations (); 주석 주석 = clz.getAnnotation (AnnotationObject.class);
그런 다음, 얻은 주석에 따라 후속 처리를 수행 할 수 있습니다. 다음은 처리의 예입니다.
for (주석 주석 : 주석) {if (myAnnotation의 주석 인스턴스) {myAnnotation myAnnotation = (myAnnotation) 주석; System.out.println ( "이름 :" + myAnnotation.name ()); System.out.println ( "value :" + myAnnotation.value ()); }}위의 클래스 주석은 클래스 객체를 사용하여 getannotations를 호출하여 얻습니다. 메소드 주석 및 가변 주석은 동일합니다. 메소드 객체와 필드 객체를 각각 사용하여 주석을 얻는 GetDeclaredAnnotations를 호출합니다. 할 말이 많지 않습니다. 예를 들어 반사 코드를 참조하십시오
매개 변수 주석은 비교적 번거로운 항목입니다. 획득 방법을 비교합니다. 첫 번째 단계는 먼저 메소드 객체를 얻고 getParameterAnnotations를 호출하는 것입니다. 그러나이 리턴 값은 메소드 객체에 많은 매개 변수가 있고 각 매개 변수에는 많은 주석이있을 수 있기 때문에 2 차원 배열입니다. 예는 다음과 같습니다.
메소드 메소드 1 = clz.getMethod ( "dootherthing", String.class); 주석 [] [] annotationInparam = method1.getParameterAnnotations (); class [] params = method1.getParameterTypes (); int i = 0; for (주석 [] 주석 : AnnotationInparam) {class para = params [i ++]; for (주석 주석 : 주석) {if (myAnnotation의 주석 인스턴스) {myAnnotation myAnnotation = (myAnnotation) 주석; System.out.println ( "param :" + para.getName ()); System.out.println ( "이름 :" + myAnnotation.name ()); System.out.println ( "value :" + myAnnotation.value ()); }}}제네릭
Java 제네릭은 지우기를 통해 구현되기 때문에 특정 매개 변수 유형의 제네릭에 대한 정보를 직접 얻는 것은 어렵지만 반사를 사용하여 간접 형식을 통해 제네릭 정보를 얻을 수 있습니다. 예를 들어, 다음 수업 :
공개 클래스 genericobject {public list <string> 목록; 공개 목록 <string> getLists () {return lists; } public void setlists (list <string> lists) {this.lists = lists; }}메소드가 일반 클래스를 반환하는 경우 메소드 객체를 통해 getGenericreTurnType를 호출 하여이 일반 클래스의 특정 매개 변수화 유형을 얻을 수 있습니다. 다음 코드를보십시오.
클래스 clz = genericobject.class; 메소드 메소드 = clz.getMethod ( "getLists"); type genericType = method.getGenericReturnType (); if (parameterizedtype의 generictepe 인스턴스) {parameterizedtype parameterizedtype = ((ParameterizedType) generictype); type [] type = parameterizedtype.getActualTyPearguments (); for (type type : type) {class allyclz = ((클래스) 유형); System.out.println ( "매개 변수화 유형은 :" + realclz); }}결과는 다음과 같습니다.
参数化类型为: class java.lang.String
단계는 약간 번거 롭기 때문에 다음과 같은 설명은 다음과 같습니다.
결과를 살펴보면 제네릭에 대한 구체적인 정보를 얻었습니다.
메소드가 일반 유형을 반환하지 않으면 위의 클래스의 setLists 메소드와 같은 메소드 매개 변수에 의해 일반 유형의 매개 변수화 된 유형의 일반 유형을 얻을 수 있습니다. 예는 다음과 같습니다.
메소드 setMethod = clz.getMethod ( "setLists", list.class); type [] genericparametertypes = setMethod.getGenericParameterTypes (); for (genericparametertype : genericparametertypes) {system.out.println ( "genericparametertypes는 다음과 같습니다." + genericparametertype.gettypename ()); if (parameterizedtype의 genericparameterType 인스턴스) {parameterizedType parameterizedType = ((ParameterizedType) genericparameterType); System.out.println ( "ParameterizedType는 다음과 같습니다. 유형 유형 [] = ParameterizedType.getActualTyPearguments (); for (type type : type) {System.out.println ( "매개 변수화 유형은" + ((클래스) 유형) .getName ()); }}}실행 결과는 다음과 같습니다.
GenericParameterTypes IS : java.util.list <java.lang.string> ParameterizedType IS : java.util.list <java.lang.string> 매개 변수 유형은 : java.lang.string입니다
이 방법의 매개 변수는 둘 이상의 일반 유형을 가질 수 있으므로 배열을 얻기 위해 GetGenericParameterTypes를 얻습니다. 각 요소에 매개 변수화 된 유형이 있는지 확인해야합니다. 후속 단계는 위의 단계와 비슷하므로 많이 말하지 않을 것입니다.
메소드 매개 변수조차 일반 클래스를 포함하지 않으면 변수 유형을 통해 마지막 경우 만 필드 클래스가 사용됩니다. 예는 다음과 같습니다.
필드 필드 = clz.getfield ( "목록"); 유형 유형 = field.getGenericType (); if (parameterizedtype의 유형 인스턴스) {parameterizedtype parameterizedtype = ((ParameterizedType) 유형); type [] type = parameterizedtype.getActualTyPearguments (); for (type type1 : type) {system.out.println ( "매개 변수화 유형 :" + ((클래스) type1) .getTypename ()); }}원리는 유형 객체가 field.getgenerictype ()를 통한 것을 제외하고는 위와 동일하므로 나머지 작업에 대해별로 말하지 않을 것입니다.
이것은 반사를 통해 매개 변수화 된 유형의 제네릭을 얻는 데 소개됩니다.
정렬
Java 반사는 배열 생성, 배열에서 값 액세스, 배열의 클래스 객체를 얻는 등 배열에서 작동 할 수 있습니다.
배열에서 배열에서 값에 액세스하고, 배열 클래스를 반사하는 것은 반사 패키지 아래의 값에 대해 간단히 이야기 해 봅시다.
// 길이가 3 int [] intarray = (int []) array.newinstance (int.class, 3)의 int 유형 배열을 만듭니다. // (int i = 0; i <intarray.length; i ++) {array.set (intarray, i, i+2); } // 반사 형태의 배열은 배열에서 값을 가져옵니다 (int i = 0; i <intarray.length; i ++) {system.out.println (array.get (intarray, i)); }위는 배열을 생성하고 반사를 사용하여 배열의 값에 액세스하는 것입니다.
배열을 얻는 클래스 객체의 경우 int []. class를 사용하거나 클래스를 사용할 수 있습니다.
클래스 clz = class.forname ( "[i"); System.out.println (clz.gettypename ());
결과는 다음과 같습니다.
int[]
이 forname의 문자열, [ 배열을 나타내고, int , float is f , double is d 등을 나타냅니다. 일반적인 객체를 얻으려면 다음 양식을 사용하십시오.
Class stringClz = Class.forName("[Ljava.lang.String;");
[ 배열이라고 말하고 L 의 오른쪽은 클래스 이름이고, 오른쪽은 유형의 오른쪽은 a입니다 . ;
이 방법으로 배열의 클래스 객체를 얻는 것은 너무 번거 롭습니다.
배열의 클래스 객체를 얻은 후 GetComponentType를 호출하여 배열 멤버의 유형 정보를 얻는 것과 같은 고유 한 방법 중 일부를 호출 할 수 있습니다. 예를 들어, int 배열은 int입니다.
System.out.println(clz.getComponentType().getTypeName());
결과는 int 입니다
요약
이번에는 반사의 다양한 응용이 이로 끝나고 앞으로 심층적 인 지식 설명이있을 수 있습니다. 특정 코드의 경우 반사 코드를 볼 수 있습니다.
SRC 패키지에는 다양한 클래스가 있으며 테스트 클래스에는 이러한 클래스에 액세스 할 수 있습니다.
위는이 기사의 모든 내용입니다. 이 기사의 내용이 모든 사람의 연구 나 업무에 도움이되기를 바랍니다. 또한 wulin.com을 더 지원하기를 바랍니다!