Java 반사 메커니즘 상세 및 실례 코드

24392 단어 Java반사
Java 반사 상세 정보
이 글은 여전히 작은 예로 설명한다. 왜냐하면 나는 시종일관 사례 구동이 가장 좋다고 생각하기 때문이다. 그렇지 않으면 이론만 보면 봐도 이해하지 못하지만 여러분은 글을 본 후에 고개를 돌려 이론을 보면 더욱 좋은 이해를 할 수 있을 것이라고 건의한다.
다음은 본문을 시작합니다.
[사례1] 하나의 대상을 통해 완전한 가방 이름과 클래스 이름을 얻는다

package Reflect;
 
/**
 *  
 * */
class Demo{
  //other codes...
}
 
class hello{
  public static void main(String[] args) {
    Demo demo=new Demo();
    System.out.println(demo.getClass().getName());
  }
}
[실행 결과]: Reflect.Demo
한마디 추가: 모든 종류의 대상은 사실 Class의 실례입니다.
[사례2] 실례화된 클래스 대상

package Reflect;
class Demo{
  //other codes...
}
 
class hello{
  public static void main(String[] args) {
    Class<?> demo1=null;
    Class<?> demo2=null;
    Class<?> demo3=null;
    try{
      // 
      demo1=Class.forName("Reflect.Demo");
    }catch(Exception 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());
     
  }
}
[실행 결과]:
클래스 이름 Reflect.Demo
클래스 이름 Reflect.Demo
클래스 이름 Reflect.Demo
[사례 3] Class를 통해 다른 유형의 대상을 실례화하다
무참을 통해 실례화된 대상을 구성하다

package Reflect;
 
class Person{
   
  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;
  }
  @Override
  public String toString(){
    return "["+this.name+" "+this.age+"]";
  }
  private String name;
  private int age;
}
 
class hello{
  public static void main(String[] args) {
    Class<?> demo=null;
    try{
      demo=Class.forName("Reflect.Person");
    }catch (Exception e) {
      e.printStackTrace();
    }
    Person per=null;
    try {
      per=(Person)demo.newInstance();
    } catch (InstantiationException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    per.setName("Rollen");
    per.setAge(20);
    System.out.println(per);
  }
}
[실행 결과]:
[Rollen  20]
그러나 우리가 Person의 기본 무참구조 함수를 취소할 때, 예를 들어 매개 변수가 있는 구조 함수만 정의한 후에 오류가 발생할 수 있음을 주의하십시오.
예를 들어 나는 구조 함수를 정의했다.

public Person(String name, int age) {
    this.age=age;
    this.name=name;
  }
그리고 위의 프로그램을 계속 실행하면 다음과 같이 나타납니다.
java.lang.InstantiationException: Reflect.Person
    at java.lang.Class.newInstance0(Class.java:340)
    at java.lang.Class.newInstance(Class.java:308)
    at Reflect.hello.main(hello.java:39)
Exception in thread "main"java.lang.NullPointerException
    at Reflect.hello.main(hello.java:47)
그러므로 여러분은 나중에 Class를 사용하여 다른 종류의 대상을 실례화할 때 반드시 스스로 무참한 구조 함수를 정의해야 합니다
【사례】 Class를 통해 다른 클래스의 구조 함수를 호출할 수 있다(이런 방식으로 Class를 통해 다른 클래스의 대상을 만들 수도 있다)

package Reflect;
 
import java.lang.reflect.Constructor;
 
class Person{
   
  public Person() {
     
  }
  public Person(String name){
    this.name=name;
  }
  public Person(int age){
    this.age=age;
  }
  public Person(String name, int age) {
    this.age=age;
    this.name=name;
  }
  public String getName() {
    return name;
  }
  public int getAge() {
    return age;
  }
  @Override
  public String toString(){
    return "["+this.name+" "+this.age+"]";
  }
  private String name;
  private int age;
}
 
class hello{
  public static void main(String[] args) {
    Class<?> demo=null;
    try{
      demo=Class.forName("Reflect.Person");
    }catch (Exception e) {
      e.printStackTrace();
    }
    Person per1=null;
    Person per2=null;
    Person per3=null;
    Person per4=null;
    // 
    Constructor<?> cons[]=demo.getConstructors();
    try{
      per1=(Person)cons[0].newInstance();
      per2=(Person)cons[1].newInstance("Rollen");
      per3=(Person)cons[2].newInstance(20);
      per4=(Person)cons[3].newInstance("Rollen",20);
    }catch(Exception e){
      e.printStackTrace();
    }
    System.out.println(per1);
    System.out.println(per2);
    System.out.println(per3);
    System.out.println(per4);
  }
}
[실행 결과]:
[null  0]
[Rollen  0]
[null  20]
[Rollen  20]
[사례]
클래스 구현 인터페이스를 반환합니다.

package Reflect;
 
interface China{
  public static final String name="Rollen";
  public static int age=20;
  public void sayChina();
  public void sayHello(String name, int age);
}
 
class Person implements China{
  public Person() {
     
  }
  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(String name, 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("Reflect.Person");
    }catch (Exception e) {
      e.printStackTrace();
    }
    // 
    Class<?> intes[]=demo.getInterfaces();
    for (int i = 0; i < intes.length; i++) {
      System.out.println("   "+intes[i].getName());
    }
  }
}
[실행 결과]:
구현된 인터페이스 Reflect.China
(아래 몇 가지 예는 이 예의Person 클래스에 사용되기 때문에 편폭을 절약하기 위해 Person 코드 부분을 더 이상 붙이지 않고 메인 클래스인hello 코드만 붙인다)
[사례]: 다른 유형 중의 부류를 얻다

class hello{
  public static void main(String[] args) {
    Class<?> demo=null;
    try{
      demo=Class.forName("Reflect.Person");
    }catch (Exception e) {
      e.printStackTrace();
    }
    // 
    Class<?> temp=demo.getSuperclass();
    System.out.println(" :  "+temp.getName());
  }
}

[실행 결과]
상속된 부류는:java입니다.lang.Object
【사례】: 기타 클래스의 모든 구조 함수 획득
이 예는 프로그램 시작에 importjava를 추가해야 합니다.lang.reflect.*;
그런 다음 마스터 클래스를 다음과 같이 작성합니다.

class hello{
  public static void main(String[] args) {
    Class<?> demo=null;
    try{
      demo=Class.forName("Reflect.Person");
    }catch (Exception e) {
      e.printStackTrace();
    }
    Constructor<?>cons[]=demo.getConstructors();
    for (int i = 0; i < cons.length; i++) {
      System.out.println(" : "+cons[i]);
    }
  }
}
[실행 결과]:
구조 방법:public Reflect.Person()
구조 방법:public Reflect.Person(java.lang.String)
그러나 세심한 독자들은 위의 구조 함수는public나private 같은 수식자가 없다는 것을 알게 될 것이다
다음 예는 우리가 수식자를 얻는다

class hello{
  public static void main(String[] args) {
    Class<?> demo=null;
    try{
      demo=Class.forName("Reflect.Person");
    }catch (Exception e) {
      e.printStackTrace();
    }
    Constructor<?>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;j<p.length;++j){
        System.out.print(p[j].getName()+" arg"+i);
        if(j<p.length-1){
          System.out.print(",");
        }
      }
      System.out.println("){}");
    }
  }
}
[실행 결과]:
구조 방법:public Reflect.Person(){}
구조 방법:public Reflect.Person(java.lang.String arg1){}
때로는 한 가지 방법에 이상이 있을 수도 있어, 허허.다음은 다음과 같습니다.

class hello{
  public static void main(String[] args) {
    Class<?> demo=null;
    try{
      demo=Class.forName("Reflect.Person");
    }catch (Exception e) {
      e.printStackTrace();
    }
    Method method[]=demo.getMethods();
    for(int i=0;i<method.length;++i){
      Class<?> returnType=method[i].getReturnType();
      Class<?> para[]=method[i].getParameterTypes();
      int temp=method[i].getModifiers();
      System.out.print(Modifier.toString(temp)+" ");
      System.out.print(returnType.getName()+" ");
      System.out.print(method[i].getName()+" ");
      System.out.print("(");
      for(int j=0;j<para.length;++j){
        System.out.print(para[j].getName()+" "+"arg"+j);
        if(j<para.length-1){
          System.out.print(",");
        }
      }
      Class<?> exce[]=method[i].getExceptionTypes();
      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)
public void  sayChina ()
public void  sayHello (java.lang.String arg0,int arg1)
public final native void  wait (long arg0) throws java.lang.InterruptedException
public final void  wait () throws java.lang.InterruptedException
public final void  wait (long arg0,int arg1) throws java.lang.InterruptedException
public boolean  equals (java.lang.Object arg0)
public java.lang.String  toString ()
public native int  hashCode ()
public final native java.lang.Class  getClass ()
public final native void  notify ()
public final native void  notifyAll ()
[사례] 다음에 우리 다른 종류의 모든 속성을 얻자. 마지막으로 나는 이런 것들을 한데 정리했다. 즉class를 통해 하나의 종류의 모든 구조를 얻는 것이다.

class hello {
  public static void main(String[] args) {
    Class<?> demo = null;
    try {
      demo = Class.forName("Reflect.Person");
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("=============== ========================");
    //  
    Field[] field = demo.getDeclaredFields();
    for (int i = 0; i < field.length; i++) {
      //  
      int mo = field[i].getModifiers();
      String priv = Modifier.toString(mo);
      //  
      Class<?> type = field[i].getType();
      System.out.println(priv + " " + type.getName() + " "
          + field[i].getName() + ";");
    }
    System.out.println("=============== ========================");
    //  
    Field[] filed1 = demo.getFields();
    for (int j = 0; j < filed1.length; j++) {
      //  
      int mo = filed1[j].getModifiers();
      String priv = Modifier.toString(mo);
      //  
      Class<?> type = filed1[j].getType();
      System.out.println(priv + " " + type.getName() + " "
          + filed1[j].getName() + ";");
    }
  }
}
[실행 결과]:
============== 클래스 속성 ==========================
private java.lang.String sex;
============== 구현된 인터페이스 또는 상위 클래스의 속성 ===========================
public static final java.lang.String name;
public static final int age;
[사례] 다른 유형의 방법을 반사하여 호출할 수도 있습니다.

class hello {
  public static void main(String[] args) {
    Class<?> demo = null;
    try {
      demo = Class.forName("Reflect.Person");
    } catch (Exception e) {
      e.printStackTrace();
    }
    try{
      // Person sayChina 
      Method method=demo.getMethod("sayChina");
      method.invoke(demo.newInstance());
      // Person sayHello 
      method=demo.getMethod("sayHello", String.class,int.class);
      method.invoke(demo.newInstance(),"Rollen",20);
       
    }catch (Exception e) {
      e.printStackTrace();
    }
  }
}
[실행 결과]:
hello ,china
Rollen  20
[사례] 다른 종류의 set와 get 방법을 호출합니다

class hello {
  public static void main(String[] args) {
    Class<?> demo = null;
    Object obj=null;
    try {
      demo = Class.forName("Reflect.Person");
    } catch (Exception e) {
      e.printStackTrace();
    }
    try{
     obj=demo.newInstance();
    }catch (Exception e) {
      e.printStackTrace();
    }
    setter(obj,"Sex"," ",String.class);
    getter(obj,"Sex");
  }
 
  /**
   * @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 (Exception e) {
      e.printStackTrace();
    }
  }
 
  /**
   * @param obj
   *       
   * @param att
   *       
   * @param value
   *       
   * @param type
   *       
   * */
  public static void setter(Object obj, String att, Object value,
      Class<?> type) {
    try {
      Method method = obj.getClass().getMethod("set" + att, type);
      method.invoke(obj, value);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}// end class

[실행 결과]:
남자
[사례] 반사 조작 속성을 통해

class hello {
  public static void main(String[] args) throws Exception {
    Class<?> demo = null;
    Object obj = null;
 
    demo = Class.forName("Reflect.Person");
    obj = demo.newInstance();
 
    Field field = demo.getDeclaredField("sex");
    field.setAccessible(true);
    field.set(obj, " ");
    System.out.println(field.get(obj));
  }
}// end class
[사례] 반사를 통해 수조의 정보를 얻고 수정합니다.

import java.lang.reflect.*;
class hello{
  public static void main(String[] args) {
    int[] temp={1,2,3,4,5};
    Class<?>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
수정된 그룹의 첫 번째 요소는 100입니다.
[사례] 반사를 통해 그룹 크기 수정

class hello{
  public static void main(String[] args) {
    int[] temp={1,2,3,4,5,6,7,8,9};
    int[] newTemp=(int[])arrayInc(temp,15);
    print(newTemp);
    System.out.println("=====================");
    String[] atr={"a","b","c"};
    String[] str1=(String[])arrayInc(atr,8);
    print(str1);
  }
   
  /**
   *  
   * */
  public static Object arrayInc(Object obj,int len){
    Class<?>arr=obj.getClass().getComponentType();
    Object newArr=Array.newInstance(arr, len);
    int co=Array.getLength(obj);
    System.arraycopy(obj, 0, newArr, 0, co);
    return newArr;
  }
  /**
   *  
   * */
  public static void print(Object obj){
    Class<?>c=obj.getClass();
    if(!c.isArray()){
      return;
    }
    System.out.println(" : "+Array.getLength(obj));
    for (int i = 0; i < Array.getLength(obj); i++) {
      System.out.print(Array.get(obj, i)+" ");
    }
  }
}

[실행 결과]:
배열 길이: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================
배열 길이: 8
a b c null null null null null
동적 에이전트
[사례] 먼저 클래스 로더를 얻는 방법에 대해 살펴보겠습니다.

class test{
   
}
class hello{
  public static void main(String[] args) {
    test t=new test();
    System.out.println("  "+t.getClass().getClassLoader().getClass().getName());
  }
}

【프로그램 출력】:
클래스 캐리어 sun.misc.Launcher$AppClassLoader
사실 자바에는 세 종류의 캐리어가 있다.
1) Bootstrap ClassLoader 이 로더는 c++로 작성되었으며 일반적으로 개발되지 않습니다.
2) Extension ClassLoader는 확장 클래스를 불러오는 데 사용되며, 일반적으로 jre\lib\ext 디렉터리의 클래스에 대응한다
3) AppClassLoader는classpath가 지정한 클래스를 불러옵니다. 가장 자주 사용하는 마운트기입니다.자바의 기본 마운트이기도 합니다.
동적 에이전트를 완성하려면 먼저 InvocationHandler 인터페이스의 하위 클래스를 정의해야 합니다. 에이전트의 구체적인 작업이 완료되었습니다.

package Reflect;
import java.lang.reflect.*;
 
// 
interface Subject {
  public String say(String name, int age);
}
 
//  
class RealSubject implements Subject {
  @Override
  public String say(String name, int age) {
    return name + " " + age;
  }
}
 
class MyInvocationHandler implements InvocationHandler {
  private Object obj = null;
 
  public Object bind(Object obj) {
    this.obj = obj;
    return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
        .getClass().getInterfaces(), this);
  }
 
  @Override
  public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
    Object temp = method.invoke(this.obj, args);
    return temp;
  }
}
 
class hello {
  public static void main(String[] args) {
    MyInvocationHandler demo = new MyInvocationHandler();
    Subject sub = (Subject) demo.bind(new RealSubject());
    String info = sub.say("Rollen", 20);
    System.out.println(info);
  }
}
[실행 결과]:
Rollen  20
클래스 라이프 사이클
클래스 컴파일이 완료되면 다음 단계에서 클래스를 사용해야 합니다. 클래스를 사용하려면 JVM을 떠날 수 없습니다.프로그램 실행 중 JVM은 마운트, 링크, 초기화를 통해 3단계를 완료합니다.
클래스의 마운트는 클래스 마운트를 통해 완성됩니다. 마운트는class 파일의 바이너리 파일을 JVM 메소드 영역에 불러오고 이 클래스를 설명하는java를 만듭니다.lang. Class 객체.데이터를 봉인하는 데 쓰인다.하지만 같은 클래스는 클래스 마운트기에만 마운트되기 전에
링크는 2진 데이터를 실행할 수 있는 상태로 조립하는 것이다.
링크는 검증, 준비, 해석 3단계로 나뉜다
일반적으로 이 바이너리 파일이 현재 JVM(버전)에 적합한지 확인하는 데 사용됩니다.
준비는 정적 구성원을 위해 메모리 공간을 분배하는 것이다.기본값 설정
해석은 모든 기호 인용이 실행 프로그램에서 사용될 때까지 상수 탱크의 코드를 직접 인용하는 과정을 가리킨다(완전한 대응 관계 구축)
완성된 후에 유형도 초기화를 완성했고 초기화된 후에 유형의 대상은 정상적으로 사용할 수 있으며 한 대상이 더 이상 사용하지 않을 때까지 쓰레기로 회수될 것이다.공간을 방출하다.
클래스 대상을 가리키는 인용이 없을 때 제거되고 클래스의 생명주기가 끝납니다
공장 모드에 반사 사용하기
먼저 반사되지 않을 때의 공장 모델을 살펴보자.
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html

/**
 * @author Rollen-Holt    
 */
 
interface fruit{
  public abstract void eat();
}
 
class Apple implements fruit{
  public void eat(){
    System.out.println("Apple");
  }
}
 
class Orange implements fruit{
  public void eat(){
    System.out.println("Orange");
  }
}
 
//  
//  
class Factory{
  public static fruit getInstance(String fruitName){
    fruit f=null;
    if("Apple".equals(fruitName)){
      f=new Apple();
    }
    if("Orange".equals(fruitName)){
      f=new Orange();
    }
    return f;
  }
}
class hello{
  public static void main(String[] a){
    fruit f=Factory.getInstance("Orange");
    f.eat();
  }
 
}
이렇게 하면 우리가 하위 클래스를 추가할 때 공장 클래스를 수정해야 한다.만약 우리가 너무 많은 하위 클래스를 추가할 때, 고친 것이 매우 많을 것이다.
이제 반사 메커니즘을 활용해 보자.

package Reflect;
 
interface fruit{
  public abstract void eat();
}
 
class Apple implements fruit{
  public void eat(){
    System.out.println("Apple");
  }
}
 
class Orange implements fruit{
  public void eat(){
    System.out.println("Orange");
  }
}
 
class Factory{
  public static fruit getInstance(String ClassName){
    fruit f=null;
    try{
      f=(fruit)Class.forName(ClassName).newInstance();
    }catch (Exception e) {
      e.printStackTrace();
    }
    return f;
  }
}
class hello{
  public static void main(String[] a){
    fruit f=Factory.getInstance("Reflect.Apple");
    if(f!=null){
      f.eat();
    }
  }
}
지금 우리가 임의의 여러 개의 자류를 추가할 때에도 공장류는 수정할 필요가 없다.
위의 사랑은? 반사를 통해 인터페이스의 실례를 얻을 수 있지만 온전한 가방과 클래스를 전해야 한다.그리고 사용자도 하나의 인터페이스에 사용할 수 있는 하위 클래스가 얼마나 있는지 알 수 없기 때문에 우리는 속성 파일의 형식으로 필요한 하위 클래스를 설정합니다.
다음은 속성 파일을 결합한 공장 모델
우선fruit를 만듭니다.properties의 자원 파일,
내용은 다음과 같습니다.
apple=Reflect.Apple
orange=Reflect.Orange
그런 다음 마스터 클래스 코드를 작성합니다.

package Reflect;
 
import java.io.*;
import java.util.*;
 
interface fruit{
  public abstract void eat();
}
 
class Apple implements fruit{
  public void eat(){
    System.out.println("Apple");
  }
}
 
class Orange implements fruit{
  public void eat(){
    System.out.println("Orange");
  }
}
 
// 
class init{
  public static Properties getPro() throws FileNotFoundException, IOException{
    Properties pro=new Properties();
    File f=new File("fruit.properties");
    if(f.exists()){
      pro.load(new FileInputStream(f));
    }else{
      pro.setProperty("apple", "Reflect.Apple");
      pro.setProperty("orange", "Reflect.Orange");
      pro.store(new FileOutputStream(f), "FRUIT CLASS");
    }
    return pro;
  }
}
 
class Factory{
  public static fruit getInstance(String ClassName){
    fruit f=null;
    try{
      f=(fruit)Class.forName(ClassName).newInstance();
    }catch (Exception e) {
      e.printStackTrace();
    }
    return f;
  }
}
class hello{
  public static void main(String[] a) throws FileNotFoundException, IOException{
    Properties pro=init.getPro();
    fruit f=Factory.getInstance(pro.getProperty("apple"));
    if(f!=null){
      f.eat();
    }
  }
}

[실행 결과]: Apple
이상은 자바 반사 메커니즘에 대한 상세한 설명입니다. 후속적으로 관련 자료를 계속 보충합니다. 본 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기