------
Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
package cn.fuxi._02reflect;
/**
* 反射
* JAVA反射机制是在运行状态中,对任意一个类(class文件),都能够知道这个类的所有属性
* 和方法,对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及
* 动态调用对象方法的功能称为java的反射机制.
*
* 动态获取类中信息,就是Java反射.可以理解为对类的解剖.
*
* 如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就用到了反射技术.
*
* P.S.
* 所谓的框架就是对外提供一些接口,也就是功能拓展的标准,由实现类按照这个接口标准去实
* 现.框架内部如果需要操纵这些实现类的对象完成某些操纵,那么只需要把这些实现类的全名(包
* 名+类名)写在某个配置文件中,框架代码只需要读取这个配置文件,就可以获取这个实现类的字
* 节码文件,然后利用反射技术创建这个实现类的对象,并且调用相应的方法完成一些操作.
*
* 用于描述字节码的类就是class类,创建对象,可以提取字节码文件中的内容,如字段,构造函数,
* 一般函数.该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的.想要对一个类
* 文件进行解剖,只要获取到该类的字节码文件对象即可.
*/
//示例:获取字节码文件对象的3种方式
class Person{
private int age;
private String name;
public Person(int age,String name){
this.name = name;
this.age = age;
System.out.println("Person param run..."+ this.name+":"+this.age);
}
public Person(){
System.out.println("Person run");
}
public void show(){
System.out.println(name +"...show run..."+age);
}
private void privateMethod(){
System.out.println("method run");
}
public void paramMethod(String str,int num){
System.out.println("paramMethod run..."+str+":"+num);
}
public static void staticMethod(){
System.out.println("static method run...");
}
}
//要想对字节码文件进行解剖,必须要有字节码文件对象.
public class _01ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException {
getClassObject_1();
System.out.println("---------------------");
getClassObject_2();
System.out.println("---------------------");
getClassObject_3();
}
/*
*获取字节码对象的方式:
*方式一:Object类中的getClass()方法.
*想要用这种方式,必须要明确具体的类,并创建对象.
*麻烦.
*/
public static void getClassObject_1(){
Person p = new Person();
Class clazz = p.getClass();
Person p1 = new Person();
Class clazz1 = p1.getClass();
System.out.println(clazz == clazz1);//true
}
/*
*方式二:任何数据类型都具备一个静态的属性.class来获取其对应的Class对象.
*相对简单,但是还是要明确用到类中的静态成员.
*还是不够扩展.
*/
public static void getClassObject_2(){
Class clazz = Person.class;
Class clazz1 = Person.class;
System.out.println(clazz==clazz1);//true
}
/*
* 方式三:只要通过给定的类的字符串名称就可以获取该类,更为扩展.
* 可以用Class类中的方法完成.
* 该方法就是forName.
* 这种方法只要有名称即可,更为方便,扩展性更强.
*/
public static void getClassObject_3() throws ClassNotFoundException{
//可以把类的字符串名称写到配置文件中,然后读取出来.
String className = "cn.fuxi._02reflect.Person";
Class clazz = Class.forName(className);
System.out.println(clazz);
}
}
输出结果:
Person run
Person run
true
---------------------
true
---------------------
class cn.fuxi._02reflect.Person
Person run
true
---------------------
true
---------------------
class cn.fuxi._02reflect.Person
package cn.fuxi._02reflect;
/**
* 获取Class中的构造函数.
*/
import java.lang.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import cn.fuxi._02reflect.*;
public class _02ReflectDemo02 {
public static void main(String[] args) throws Exception {
createNewObject_1();
System.out.println("--------------");
createNewObject_2();
}
public static void createNewObject_1() throws ClassNotFoundException,InstantiationException,IllegalAccessException{
//早期:new时候,先根据被new的类的名称寻找该类的字节码文件,并加载进内存.
//并创建该字节码文件对象,并接着创建该字节文件的对应Person对象.
//Person p = new Person();
//现在:
String name = "cn.fuxi._02reflect.Person";
//找寻文件类文件,并加载进内存,并产生Class对象.
Class clazz = Class.forName(name);
//如何产生该类的对象呢?
Object obj = clazz.newInstance();//调用Person的空参构造函数
}
public static void createNewObject_2() throws ClassNotFoundException,InstantiationException,NoSuchMethodException,IllegalAccessException,InvocationTargetException{
//Person p = new Person("小强",39);
/*
* 当获取指定名称对应类中的所体现的对象时.
* 而该对象初始化不使用空参数构造函数该怎么办呢?
* 既然是通过指定的构造函数经行对象的初始化.
* 所以应该先获取到该构造函数,通过字节码文件对象即可完成.
* 该方法是:getConstructor(parameterTypes);
*/
String className = "cn.fuxi._02reflect.Person";
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor(int.class,String.class);
Object obj = constructor.newInstance(38,"小明");
}
}
输出结果:
Person run
--------------
Person param run...小明:38
--------------
Person param run...小明:38
package cn.fuxi._02reflect;
/**
* 获取Class的字段
*/
import cn.fuxi._02reflect.*;
import java.lang.reflect.*;
public class _03ReflectDemo03 {
public static void main(String[] args) throws Exception {
getFiledDemo();
}
/*
*获取字节码文件中的字段.
*/
public static void getFiledDemo() throws Exception{
Class clazz = Class.forName("cn.fuxi._02reflect.Person");
//getFiled只能获取所有可访问的公共字段,private获取不到.
//Field field = clazz.getField("age");
//getDeclaredField可以获取到的公共字段,也可以获取到私有字段.
Field field = clazz.getDeclaredField("age");
//对私有字段的访问取消权限检查,暴力访问.
field.setAccessible(true);
Object obj = clazz.newInstance();
//为对象的属性赋值
field.set(obj, 27);
//获取某对象的某属性值
Object o = field.get(obj);
System.out.println(o);
}
}
输出结果:
Person run
27
27
package cn.fuxi._02reflect;
/**
* 获取Class中的方法
*/
import java.lang.reflect.*;
public class _04ReflectDemo04 {
public static void main(String[] args) throws Exception{
getMethodDemo_1();
System.out.println("--------------------");
getMethodDemo_2();
System.out.println("--------------------");
getMethodDemo_3();
}
/*
* 获取指定Class中的公共函数.
*/
public static void getMethodDemo_1() throws Exception{
Class clazz = Class.forName("cn.fuxi._02reflect.Person");
Method[] methods = clazz.getMethods();//获取的都是公有的方法
methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包括私有.
for(Method method: methods){
System.out.println(method);
}
}
public static void getMethodDemo_2() throws Exception{
Class clazz = Class.forName("cn.fuxi._02reflect.Person");
Method method = clazz.getMethod("show",null);//获取空参数一般方法
Object obj = clazz.newInstance();
Constructor constructor = clazz.getConstructor(int.class,String.class);
obj = constructor.newInstance(26,"小芳");
method.invoke(obj, null);
}
public static void getMethodDemo_3() throws Exception{
Class clazz = Class.forName("cn.fuxi._02reflect.Person");
Method method = clazz.getMethod("paramMethod", String.class,int.class);//获取空参数一般方法
Object obj = clazz.newInstance();
Constructor constructor = clazz.getConstructor();
obj = constructor.newInstance();
method.invoke(obj, "小强",89);
}
}
输出结果:
public void cn.fuxi._02reflect.Person.show()
public void cn.fuxi._02reflect.Person.paramMethod(java.lang.String,int)
private void cn.fuxi._02reflect.Person.privateMethod()
public static void cn.fuxi._02reflect.Person.staticMethod()
--------------------
Person run
Person param run...小芳:26
小芳...show run...26
--------------------
Person run
Person run
paramMethod run...小强:89
public void cn.fuxi._02reflect.Person.paramMethod(java.lang.String,int)
private void cn.fuxi._02reflect.Person.privateMethod()
public static void cn.fuxi._02reflect.Person.staticMethod()
--------------------
Person run
Person param run...小芳:26
小芳...show run...26
--------------------
Person run
Person run
paramMethod run...小强:89
package cn.fuxi._02reflect;
import java.io.*;
import java.util.Properties;
interface PCI{
public void open();
public void close();
}
class SoundCard implements PCI{
public void open(){
System.out.println("sound open");
}
public void close(){
System.out.println("sound close");
}
}
class NetCard implements PCI{
public void open(){
System.out.println("net open");
}
public void close(){
System.out.println("net close");
}
}
class MainBoard{
public void run(){
System.out.println("main board run...");
}
public void usePCI(PCI p){
p.open();
p.close();
}
}
/**
* 电脑运行
*/
public class _05reflectTest {
public static void main(String[] args) throws Exception {
MainBoard mb = new MainBoard();
mb.run();
//每次日案件一个设备都需要修改代码传递一个新创建的对象
//mb.usePCI(new SoundCard());
//能不能不修改代码就可以完成这个动作
//不用new完成,而是只获取其class文件,在内部实现创建对象的动作.
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);//用Class去加载这个子类
PCI p = (PCI)clazz.newInstance();
mb.usePCI(p);
}
fis.close();
}
}
输出结果:
main board run...
sound open
sound close
net open
net close
sound open
sound close
net open
net close