Java 반사에 대한 자세한 설명
이 기사는 여전히 작은 예를 사용하여 설명하기 위해 작은 예를 사용합니다. 왜냐하면 나는 항상 사례 중심이 최고라고 생각하기 때문에, 그렇지 않으면 이론을 읽는다면 읽은 후에는 이해할 수 없습니다. 그러나 기사를 읽은 후 이론을 되돌아보고 더 잘 이해하는 것이 좋습니다.
본문은 아래에서 시작됩니다.
[사례 1] 개체를 통해 전체 패키지 및 클래스 이름을 얻습니다.
패키지 반영; /*** 개체를 통해 전체 패키지 이름과 클래스 이름을 가져옵니다*/클래스 데모 {// 기타 코드 ...} 클래스 hello {public static void main (String [] args) {demo demo = new demo (); System.out.println (demo.getClass (). getName ()); }}【실행 결과】 : 반사
문장 추가 : 클래스의 모든 객체는 실제로 클래스의 인스턴스입니다.
case 2】 클래스 객체를 인스턴스화합니다
패키지 반사; 클래스 데모 {// 기타 코드 ...} 클래스 hello {public static void main (String [] args) {class <?> demo1 = null; 클래스 <?> demo2 = null; 클래스 <?> demo3 = null; try {// 일반적 으로이 양식 demo1 = class.forname ( "reflect.demo")을 사용해보십시오. } catch (예외 e) {e.printstacktrace (); } demo2 = new demo (). getClass (); demo3 = demo.class; System.out.println ( "클래스 이름"+demo1.getName ()); System.out.println ( "클래스 이름"+demo2.getName ()); System.out.println ( "클래스 이름"+demo3.getName ()); }}【작동 결과】 :
클래스 namereflect.demo
클래스 namereflect.demo
클래스 namereflect.demo
[사례 3] 클래스를 통해 다른 클래스의 개체를 인스턴스화합니다
비모수를 구성하여 인스턴스화 된 물체
패키지 반영; 클래스 개인 {public String getName () {return name; } public void setName (문자열 이름) {this.name = 이름; } public int getage () {반환 연령; } public void 설정 (int Age) {this.age = age; } @override public String toString () {return "["+this.name+""+this.age+"]; } 개인 문자열 이름; 사적인 int 연령; } class hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } person per = null; try {per = (person) demo.newinstance (); } catch (InstantiationException e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); } catch (불법 행위 exception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); } per.setName ( "rollen"); per.setage (20); System.out.println (per); }}【작동 결과】 :
[Rollen 20]
그러나 예를 들어, 기본 매개 변수가없는 생성자를 직접 취소하면 매개 변수로 하나의 생성자 만 정의하면 오류가 발생합니다.
예를 들어 생성자를 정의했습니다.
공개 사람 (문자열 이름, int age) {this.age = age; this.name = 이름; }그런 다음 위의 프로그램을 계속 실행하면 다음과 같이 나타납니다.
java.lang.instantiationException : 반사
at java.lang.class.newinstance0 (class.java:340)
at java.lang.class.newinstance (class.java:308)
at at at at at at allo.main (hello.java:39)
스레드의 예외 "main"java.lang.nullpointerexception
at at at at at at allo.main (hello.java:47)
따라서 클래스를 사용하여 다른 클래스를 인스턴스화하는 객체를 작성할 때 매개 변수없이 자신의 생성자를 정의해야합니다.
[CASE] 클래스를 통해 다른 클래스의 생성자 호출 (이 방법으로 클래스를 통해 다른 클래스의 객체를 만들 수도 있음).
패키지 반영; java.lang.reflect.constructor import; 클래스 사람 {public person () {} public person (문자열 이름) {this.name = name; } 공공 사람 (int Age) {this.age = age; } 공개 사람 (문자열 이름, int age) {this.age = age; this.name = 이름; } public String getName () {return name; } public int getage () {반환 연령; } @override public String toString () {return "["+this.name+""+this.age+"]; } 개인 문자열 이름; 개인 int age;} class hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } person per1 = null; PER2 = NULL; Per3 = null; Per4 = null; // 모든 생성자 생성자 생성자 <?> cons [] = demo.getConstructors (); try {per1 = (person) cons [0] .newinstance (); per2 = (사람) cons [1] .newinstance ( "rollen"); per3 = (사람) cons [2] .newinstance (20); per4 = (사람) cons [3] .newinstance ( "rollen", 20); } catch (예외 e) {e.printstacktrace (); } system.out.println (Per1); System.out.println (Per2); System.out.println (Per3); System.out.println (Per4); }}【작동 결과】 :
[NULL 0]
[롤렌 0]
[NULL 20]
[Rollen 20]
【사례】
클래스에서 구현 한 인터페이스를 반환합니다.
패키지 반영; 인터페이스 중국 {public static final String name = "rollen"; 공공 정적 int 연령 = 20; 공공 void saychina (); 공개 무효 SAYSHELLO (문자열 이름, int Age);} 클래스 사람은 중국 {public person () {} 공개 사람 (String Sex) {this.sex = sex; } public String getSex () {return sex; } public void setsex (String sex) {this.sex = sex; } @override public void saychina () {System.out.println ( "Hello, China"); } @override public void sayhello (문자열 이름, int age) {system.out.println (name+""+age); } private String sex;} class Hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } // 모든 인터페이스를 저장 클래스 <?> intes [] = demo.getInterfaces (); for (int i = 0; i <intes.length; i ++) {system.out.println ( "구현 인터페이스"+int [i] .getName ()); }}}【작동 결과】 :
구현 된 인터페이스 반사 .china
(다음 예제는이 예제의 개인 클래스를 사용하므로 공간을 절약하기 위해 더 이상 개인 코드 부분을 여기에 붙여 넣지 않고 메인 클래스의 코드 만 헬자를 붙여 넣지 않습니다).
【사례 get : 다른 클래스에서 부모 수업을받습니다
클래스 hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } // 상위 클래스 클래스를 가져옵니다 <?> temp = demo.getSuperClass (); System.out.println ( "상속 된 상위 클래스는"+temp.getName ()); }}【실행 결과】
상속 된 부모 클래스는 java.lang.object입니다
【사례 obtain : 다른 클래스의 모든 생성자를 얻습니다
이 예제는 import java.lang.reflect를 추가해야합니다.* 프로그램 시작시;
그런 다음 메인 클래스를 다음과 같이 씁니다.
클래스 hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } 생성자 <?> cons [] = demo.getConstructors (); for (int i = 0; i <cons.length; i ++) {system.out.println ( "생성자 :"+cons [i]); }}}【작동 결과】 :
구성 방법 : Public Recelf.Person ()
생성자 : 공개 반사.
그러나 신중한 독자는 위의 생성자에게 공공 또는 개인과 같은 수정자가 없다는 것을 알게 될 것입니다.
다음 예에서 수정자를 얻으겠습니다
클래스 hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } 생성자 <?> cons [] = demo.getConstructors (); for (int i = 0; i <cons.length; i ++) {class <?> p [] = cons [i] .getParameterTypes (); System.out.print ( "생성자 :"); int mo = cons [i] .getModifiers (); System.out.print (modifier.toString (MO)+""); system.out.print (cons [i] .getName ()); system.out.print ( "("); for (int j = 0; }}【작동 결과】 :
생성자 : public refling.person () {}
생성자 : Public Relect.Person (java.lang.string arg1) {}
때로는 방법에 예외가있을 수 있습니다. 봅시다 :
클래스 hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } 메소드 메소드 [] = demo.getMethods (); for (int i = 0; i <method.length; ++ i) {class <?> returnType = 메소드 [i] .getReturnType (); class <?> para [] = 메소드 [i] .getParameterTypes (); int temp = method [i] .getModifiers (); System.out.print (modifier.tostring (temp)+""); System.out.print (returnType.getName ()+""); System.out.print (메소드 [i] .getName ()+""); system.out.print ( "("); for (int j = 0; if (exce.length> 0) {System.out.print ( ") Throws"); for (int k = 0; k <exce.length; ++ k) {system.out.print (exce [k] .getName ()+""); if (k <exce.length-1) {system.out.print ( ","); }}} else {system.out.print ( ")"); } system.out.println (); }}}【작동 결과】 :
public java.lang.string getsex ()
public void setsex (java.lang.string arg0)
공개 void saychina ()
공개 void sayhello (java.lang.string arg0, int arg1)
공개 최종 네이티브 void wain (Long Arg0)은 java.lang.interruptedException을 던졌습니다
공개 최종 무효 대기 ()는 java.lang.interruptedException을 던졌습니다
공개 최종 무효 대기 (Long Arg0, int arg1)는 java.lang.interruptedException을 던졌습니다
Public Boolean Equals (java.lang.object arg0)
public java.lang.string tostring ()
공개 기본 int hashcode ()
공개 최종 기본 java.lang.class getClass ()
공개 최종 기본 void notify ()
공개 최종 기본 void notifyall ()
[CASE] 다음으로 다른 클래스의 모든 속성을 얻으십시오. 마지막으로, 나는 그것들을 함께 분류 할 것입니다. 즉, 수업을 통해 수업의 전체 프레임 워크를 얻으려면
클래스 hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } System.out.println ( "====================================================================================================== ============================================================================================================================================== ============================================================================================================================================== ============================================================================================================================================== 허가 int mo = getModifiers (); System.out.println ( "=================================================================================================================================== ======================================================================================================================= ===================================================================================================================================== ======================================================================================================================= filed1 = demo.getfields (); for (int j = 0; j <filed1.length; j ++) {// 허가 수정 자 int mo = filed1 [j] .getModifiers (); 문자열 priv = modifier.tostring (Mo); // 속성 유형 class <?> type = filed1 [j] .getType (); system.out.println (priv + "" + type.getName () + "" + filed1 [j] .getName () + ";"); }}}【작동 결과】 :
===================================================
개인 java.lang.string 섹스;
===========================================================
공개 정적 최종 Java.Lang.String 이름;
공개 정적 최종 연령;
[사례] 실제로 다른 클래스의 방법은 반사를 통해 호출 할 수 있습니다.
클래스 hello {public static void main (String [] args) {class <?> demo = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } try {// 개인 클래스 메소드에서 Saychina 메소드를 호출하십시오 메소드 메소드 = demo.getMethod ( "Saychina"); method.invoke (demo.newinstance ()); // 사람의 SayHello를 호출하십시오 메소드 = demo.getMethod ( "sayhello", String.class, int.class); method.invoke (demo.newinstance (), "rollen", 20); } catch (예외 e) {e.printstacktrace (); }}}【작동 결과】 :
안녕하세요, 중국
롤렌 20
case CASE set 호출 세트 및 기타 클래스의 방법을 얻습니다
클래스 hello {public static void main (String [] args) {class <?> demo = null; Object obj = null; try {demo = class.forname ( "reflic.person"); } catch (예외 e) {e.printstacktrace (); } try {obj = demo.newinstance (); } catch (예외 e) {e.printstacktrace (); } setter (obj, "sex", "male", string.class); getter (obj, "섹스"); } / ** * @param obj * 작동 대상 * @param att * 작업의 속성 * * / public static void getter (Object obj, String att) {try {method method = obj.getClass (). getMethod ( "get" + att); System.out.println (method.invoke (obj)); } catch (예외 e) {e.printstacktrace (); }} / ** * @param obj * 작업의 객체 * @param att * 작업의 속성 * @param value * @param type * @param type * @param void setter (object obj, String att, 객체 값, class <?> type) {try {method method = obj.getClass ( " + att, getclass); method.invoke (obj, value); } catch (예외 e) {e.printstacktrace (); }}} // 종료 클래스【작동 결과】 :
남성
case 사례 by 반사에 의한 작동
클래스 hello {public static void main (string [] args)은 예외 {class <?> demo = null을 던집니다. Object obj = null; Demo = class.forname ( "Reflect.person"); obj = demo.newinstance (); 필드 필드 = demo.getDeclaredfield ( "섹스"); field.setAccessible (true); field.set (obj, "male"); System.out.println (field.get (obj)); }} // 종료 클래스[CASE] 반사를 통해 배열의 정보를 얻고 수정하십시오.
import java.lang.reflect.*; class hello {public static void main (String [] args) {int [] temp = {1,2,3,4,5}; 클래스 <?> demo = temp.getClass (). getComponentType (); System.out.println ( "배열 유형 :"+demo.getName ()); System.out.println ( "배열 길이"+array.getlength (temp)); System.out.println ( "배열의 첫 번째 요소 :"+array.get (temp, 0)); Array.set (Temp, 0, 100); System.out.println ( "배열의 첫 번째 요소를 수정 한 후"+array.get (temp, 0)); }}【작동 결과】 :
배열 유형 : int
배열 길이 5
배열의 첫 번째 요소 : 1
수정 후 배열의 첫 번째 요소는 다음과 같습니다.
case Case ify 반사를 통해 배열 크기를 수정하십시오
클래스 hello {public static void main (String [] args) {int [] temp = {1,2,3,4,5,6,7,8,9}; int [] newtemp = (int []) arrayinc (temp, 15); 인쇄 (newtemp); System.out.println ( "====================================================================================== ================================================================================================================= String []) 배열 (Atr, 8); arraycopy (obj, 0, 0, co)}** / public static void print (class <?> array.getLength (obj);【작동 결과】 :
배열 길이는 다음과 같습니다
1 2 3 4 5 6 7 8 9 0 0 0 0 0 =========================================
배열 길이는 8입니다
ABC NULL NULL NULL NULL NULL NULL
동적 에이전트
[CASE] 먼저, 클래스 로더를 얻는 방법을 살펴 보겠습니다.
클래스 테스트 {} class hello {public static void main (String [] args) {test t = new test (); System.out.println ( "ClassLoader"+T.getClass (). getClassLoader (). getClass (). getName ()); }}【프로그램 출력 put :
클래스 로더 Sun.misc.launcher $ appclassloader
실제로 Java에는 세 가지 종류의 클래스 로더가 있습니다.
1) 부트 스트랩 클래스 로더이 로더는 C ++로 작성되었으며 일반적인 개발에서는 거의 볼 수 없습니다.
2) Extension Classloader는 일반적으로 JRE/LIB/EXT 디렉토리의 클래스에 해당하는 확장 클래스를로드하는 데 사용됩니다.
3) AppClassLoader는 ClassPath에서 지정된 클래스를로드하며 가장 일반적으로 사용되는 로더입니다. 또한 Java의 기본 로더이기도합니다.
동적 프록시를 완료하려면 먼저 invocationhandler 인터페이스의 서브 클래스를 정의해야하며 프록시의 특정 작동이 완료되었습니다.
패키지 반사; import java.lang.reflect.*; // 프로젝트 인터페이스 인터페이스 주제 정의 {public String sayment (문자열 이름, int age);} // 실제 프로젝트 클래스 정의 realsubject empless {@override public string says (문자열 이름, int age) {return name + "" + age; }} class myInVocationHandler는 invocationHandler {private 객체 obj = null; public object bind (object obj) {this.obj = obj; return proxy.newproxyInstance (obj.getClass (). getClassLoader (), obj .getClass (). getInterfaces (), this); } @override public Object Invoke (오브젝트 프록시, 메소드 메소드, 개체 [] args) 던지기 가능 {object temp = method.invoke (this.obj, args); 반환 온도; }} class hello {public static void main (String [] args) {myinVocationHandler demo = new MyInvocationHandler (); 제목 sub = (주제) demo.bind (new RealSubject ()); 문자열 정보 = sub.say ( "rollen", 20); System.out.println (정보); }}【작동 결과】 :
롤렌 20
클래스의 수명주기
수업이 컴파일 된 후 다음 단계는 클래스 사용을 시작하는 것입니다. 클래스를 사용하려면 JVM과 분리 할 수 없습니다. 프로그램 실행 중에 JVM은이 세 단계, 즉로드, 링크 및 초기화를 통해 완료됩니다.
클래스 로딩은 클래스 로더를 통해 수행됩니다. 로더는 .class 파일의 이진 파일을 JVM 메소드 영역에로드하고 힙 영역 에서이 클래스를 설명하는 java.lang.class 객체를 만듭니다. 데이터를 캡슐화하는 데 사용됩니다. 그러나 동일한 클래스는 이전에 클래스 로더에서만로드됩니다.
링크는 이진 데이터를 실행할 수있는 상태로 조립하는 것입니다.
링크는 검증, 준비 및 구문 분석의 세 단계로 나뉩니다.
검증은 일반적 으로이 바이너리 파일이 현재 JVM (버전)에 적합한 지 확인하는 데 사용됩니다.
준비는 정적 멤버를위한 메모리 공간을 할당하는 것입니다. 기본값을 설정합니다
구문 분석은 실행 프로그램에서 모든 상징적 참조를 사용할 수있을 때까지 상수 풀의 코드를 직접 참조로 변환하는 과정을 나타냅니다 (완전한 서신 설정).
완료 후 유형이 초기화됩니다. 초기화 후 클래스의 객체를 정상적으로 사용할 수 있습니다. 물체가 더 이상 사용되지 않으면 쓰레기가 수집됩니다. 무료 공간.
클래스 객체에 대한 기준이 없으면 제거되지 않으면 클래스 수명주기가 끝납니다.
공장 모드에 반사를 사용하십시오
반사가 필요하지 않으면 공장 모드를 살펴 보겠습니다.
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html
/ *** @Author Rollen-Holt Factory Design 패턴 모드*/ 인터페이스 과일 {public acpract void eat ();} 클래스 애플 과일 {public void eat () {system.out.println ( "Apple"); }} 클래스 오렌지색 과일 {public void eat () {System.out.println ( "Orange"); }} // 공장 클래스를 구성 // 즉, 미래의 클래스 공장에서 다른 인스턴스를 추가 할 때만 공장 클래스를 수정 해야하는 경우 {public static fruit getinstance (String Fruitname) {fruit f = null; if ( "apple".equals (fruitname)) {f = new Apple (); } if ( "Orange".Equals (fruitName)) {f = new Orange (); } 반환 f; }} class hello {public static void main (String [] a) {fruit f = factory.getInstance ( "Orange"); 위업(); }}이런 식으로 서브 클래스를 추가하면 공장 클래스를 수정해야합니다. 너무 많은 서브 클래스를 추가하면 많은 것을 변경합니다.
이제 반사 메커니즘을 활용하는 것을 살펴 보겠습니다.
패키지 반영; 인터페이스 과일 {public Abstract void eat ();} 클래스 애플은 과일 {public void eat () {system.out.println ( "Apple"); }} 클래스 오렌지색 과일 {public void eat () {System.out.println ( "Orange"); }} 클래스 팩토리 {public static fruit getInstance (String ClassName) {fruit f = null; try {f = (fruit) class.forname (classname) .newinstance (); } catch (예외 e) {e.printstacktrace (); } 반환 f; }} class hello {public static void main (String [] a) {fruit f = factory.getInstance ( "Reffer.Apple"); if (f! = null) {f.eat (); }}}이제 많은 서브 클래스를 추가하더라도 공장 클래스를 수정할 필요가 없습니다.
위의 사랑은 반사를 통해 인터페이스 인스턴스를 얻을 수 있지만 전체 패키지와 클래스 이름으로 전달해야합니다. 또한 사용자는 인터페이스에서 얼마나 많은 서브 클래스를 사용할 수 있는지 알 수 없으므로 속성 파일 형태로 필요한 서브 클래스를 구성합니다.
다음을 살펴 보자 : 속성 파일을 결합한 공장 모드
먼저 과일을 만듭니다 .properties 리소스 파일.
내용은 다음과 같습니다.
Apple = Reflect.Apple
오렌지 = 반사
그런 다음 메인 클래스 코드를 작성하십시오.
패키지 반영; import java.io.*; import java.util.*; 인터페이스 과일 {public Abstract void eat ();} 클래스 애플은 과일 {public void eat () {system.out.println ( "Apple"); }} 클래스 오렌지색 과일 {public void eat () {System.out.println ( "Orange"); }} // 작동 속성 파일 클래스 init {public static properties getPro ()는 filenotfoundException, ioException {properties pro = new Properties (); 파일 f = 새 파일 ( "fruit.properties"); if (f.exists ()) {pro.load (new FileInputStream (f)); } else {pro.setProperty ( "Apple", "Reflect.Apple"); Pro.SetProperty ( "Orange", "Reflect.orange"); Pro.Store (새 파일 아웃 PutStream (F), "Fruit Class"); } 리턴 프로; }} 클래스 팩토리 {public static fruit getInstance (String ClassName) {fruit f = null; try {f = (fruit) class.forname (classname) .newinstance (); } catch (예외 e) {e.printstacktrace (); } 반환 f; }} class hello {public static void main (String [] a)은 filenotfoundException, ioException {properties pro = init.getPro (); 과일 f = 팩토리. if (f! = null) {f.eat (); }}}【실행 결과】 : Apple
위의 것은 Java 반사 메커니즘에 대한 자세한 설명입니다. 우리는 향후 관련 정보를 계속 추가 할 것입니다. 이 사이트를 지원 해주셔서 감사합니다!