>类库下载 >java类库 >자바 반사

자바 반사

高洛峰
高洛峰원래의
2016-10-17 09:35:041617검색

Java 언어의 반사 메커니즘:

실행 상태에서 Java 반사 메커니즘은 모든 클래스(클래스 파일)의 모든 속성과 메서드를 알 수 있습니다.

모든 객체에 대해 해당 메소드와 속성을 호출할 수 있습니다.

이 동적으로 얻은 정보와 객체의 메소드를 동적으로 호출하는 운동 에너지를 Java 언어의 반사 메커니즘이라고 합니다.

클래스 내 정보의 동적 획득은 클래스의 구조를 이해할 수 있는 자바 리플렉션입니다. 일부 응용 프로그램은 새 개체를 만들 수 없지만 클래스 정보를 얻기 위해 클래스를 동적으로 로드할 수 있습니다.

자바 반사

그림과 같이 클래스가 객체에 대한 설명인 것처럼 Class 클래스는 바이트코드 파일(.class 파일) 객체를 설명할 수 있습니다.

자바 반사

//초기: 신규일 때 먼저 신규 클래스 이름을 기준으로 클래스의 바이트코드 파일을 찾아 메모리에 로드하고,
//Merse 바이트코드 파일 객체를 생성한 다음 바이트코드 파일의 해당 Person 객체를 생성합니다.
com.xidian.Person p=new com.xidian.Person();

//Now
String name="com.xidian.Person";
//파일 찾기 클래스 파일이 메모리에 로드되고 Class 객체가 생성됩니다.
Class clazz=Class.forName(name);
//이 클래스의 객체를 생성하는 방법은 무엇입니까?
Object obj=clazz.newInstance();

Reflective 클래스 로딩을 사용하면 형태는 표면적으로는 더 복잡하지만 확장성은 더 강해집니다. 이전에는 프로그램 파일에서 수동으로 개체를 생성해야 했습니다.

이제 해당 개체를 생성하려면 구성 파일에 문자열만 작성하면 됩니다.

질문: clazz.newInstance()를 사용하면 빈 매개변수 생성자만 사용할 수 있습니다. 매개변수 목록 생성자를 사용하려면 어떻게 해야 하나요?

/*
* 지정된 이름에 해당하는 클래스에 구현된 객체를 얻을 때
* 빈 매개변수 생성자를 사용하지 않고 객체를 초기화하는 경우 어떻게 해야 하나요?
*
* 지정된 생성자를 통해 객체가 초기화되므로
* 먼저 생성자를 얻어야 합니다. 이는 바이트코드 파일을 통해 수행될 수 있습니다.
* 이 메소드는 다음과 같습니다: getConstructor(parameterTypes)
*
* 리플렉션에서는 생성자, 필드 및 메소드가 모두 객체입니다.
*/

String name="com.xidian.Person";
Class clazz=Class.forName(name);
//지정된 생성자 객체 가져오기
생성자 생성자 =clazz.getConstructor(String.class,int.class); //모든 데이터 유형은 바이트코드 파일로 설명 가능 .class
//생성자 객체의 newInstance 메소드를 통해 객체를 초기화합니다.
Object obj=constructor.newInstance("xiaoming",12);

지정된 필드의 값 가져오기:

//학교 전체 액세스 대상 비공개 필드를 검사합니다. 폭력적인 접근.
field_1.setAccessible(true);

객체 obj=clazz.newInstance();
field_1.set(obj,88);

객체 o=field_1.get( obj);

System.out.println(o);

Get 함수:

메서드 method=clazz.getMethod("show", null); //매개변수 없이 메서드 가져오기
Object obj=clazz.newInstance();
method.invoke(obj, null)

Method method2=clazz.getMethod("paramMethod" ,String.class,int.class); //매개변수, 메소드 이름, 매개변수 목록이 포함된 메소드 가져오기
Object obj2=clazz.newInstance();
method2.invoke(obj2, "Xiaoqiang",89) ; //invoke: 지정된 매개변수를 사용하여 지정된 개체에서 이 Method 개체가 나타내는 기본 메서드를 호출합니다.

reflection 적용:

인터페이스 정의:

package com.xidian;
public interface PCI {
    public void open();
    public void close();
}

인터페이스 구현 클래스 정의:

package com.xidian;
public class SoundCard implements PCI{
    
    public void open(){
        System.out.println("sound open");
    }
    
    public void close(){
        System.out.println("sound close");
    }

}

메인보드 정의:

package com.xidian;
public class Mainboard {
    
    public void run(){
        System.out.println("main run...");
    }    
    public void usePCI(PCI p){
    if(p!=null){
        p.open();
        p.close();
    }
    }
}

테스트:

package com.xidian;

public class Test {
    
    public static void main(String[] args){
        Mainboard mb=new Mainboard();
        mb.run();
        mb.usePCI(new SoundCard());      //如果主板需要使用其他设备,必须重新修改代码,传递一个新创建的对象,可扩展性不好。
        
    }
}

인터페이스의 사용으로 인해 프로그램의 결합이 줄어들었지만 코드의 확장성은 좋지 않습니다.

마더보드에 장치를 추가하고 싶지만 코드를 수정하고 싶지 않다면 대신 리플렉션을 사용하세요.

완료하기 위해 new를 사용할 필요는 없지만, 클래스 파일을 가져오고 그 안에 개체를 만듭니다.

리플렉션을 사용하여 구성하려면 .xml을 사용해야 더 정확합니다. 여기서는 이를 달성하기 위해 속성 개체를 사용합니다.

주요 기능 코드 수정:

public class Test {
    
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException{
        Mainboard mb=new Mainboard();
        mb.run();
        //mb.usePCI(new SoundCard());      //如果主板需要使用其他设备,必须重新修改代码,可扩展性不好。
                                               
        File configFile=new File("pci.properties");
        
        Properties prop=new Properties();             //注意是将配置文件放在项目的一级目录下。
        FileInputStream fis=new FileInputStream(configFile);
        
        prop.load(fis);
        
        for(int x=0;x<prop.size();x++){
            String pciName=prop.getProperty("pci"+(x+1));
            Class clazz=Class.forName(pciName);
            PCI p=(PCI)clazz.newInstance();
            mb.usePCI(p);
        }
        
        fis.close();
    }
}

구성 파일 pci.properties: pci1=com.xidian.SoundCard

장치 확장 시 추가만 하면 됩니다. 장치 프로그램 일단 작성되면 기본 프로그램 코드를 변경하지 않고도 구성 파일을 사용할 수 있습니다.


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.