白话:
最先用到反射机制应该是在用数据库实例的时候,class.forName(“oracle.jdbc.OracleDriver”),当时就那么用了,现在想想虽然这么一行代码,还是很高级啊,若是没有这种机制,直接给每个驱动包都写实例,那岂不是疯了。
后来用到了一些像mybatis似的框架,其实用的都是反射的机制,我们只需要配置文件,然后就会自动传参执行了,我们穿的都是我们自己定义好的实体对象,而这些框架来着不拒,都是通过反射的原理将其解析,拼接到sql中,确实很厉害!
一、定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
通俗点儿理解,即在传递过来一个未知的对象时,我们可以通过反射来获取到其内部的信息以及可以调用其任意的方法;
动态语言与静态语言
“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
而java靠着自身的Reflection来实现动态。
二、作用
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法;
在运行时调用任意一个对象的方法;
生成动态代理。
三、反射机制的优点与缺点
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中
它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。
四,实例
不说这些没用的了,直接搞一段代码
1.先定义一个接口
package reflectTest;
public interface SubjectChild {
public void describe();
}
2.定义一个Test类
package reflectTest;
public class Test {
}
3.定义我们需要反射的类
package reflectTest;
public class Subject extends Test implements SubjectChild{
private int id;
private String name;
public Subject(){
System.out.println("prepare...");
}
public Subject(int id,String name){
System.out.println("instance:"+id+name);
}
public void describe(){
System.out.println("describe the world");
}
public void describe(int id){
System.out.println("describe the world"+id);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4.定义反射类
package reflectTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Properties;
public class Reflect {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, FileNotFoundException, IOException{
Class<?> cs = Class.forName("reflectTest.Subject");
//获取基本属性
cs.getPackage();
//获取类的属性(public)
System.out.println(Modifier.toString(cs.getModifiers())+","+Modifier.isInterface(cs.getModifiers()));//public,false
//获取类名
System.out.println("类名:"+cs.getName());
//获取所有接口
Class<?>[] inter = cs.getInterfaces();
for(int i=0;i<inter.length;i++){
System.out.println("实现的接口:"+inter[i].getName());
}
//获取继承的父类
System.out.println("继承类:"+cs.getSuperclass());
//获取所有的属性
Field[] fields = cs.getDeclaredFields();
for(int i=0;i<fields.length;i++){
System.out.println("属性:"+fields[i]);
// 权限修饰符
int mo = fields[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = fields[i].getType();
System.out.println(priv + " " + type.getName() + " "
+ fields[i].getName() + ";");
}
//给某个属性赋值
//获取id属性
Field idF = null;
try {
idF = cs.getDeclaredField("id");
} catch (NoSuchFieldException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//实例化这个类赋给o
Object o = cs.newInstance();
//打破封装
idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
//给o对象的id属性赋值"110"
idF.set(o, 11); //set
//get
System.out.println("id的值为"+idF.get(o)); //11
/*属性:private int reflectTest.Subject.id
private int id;
属性:private java.lang.String reflectTest.Subject.name
private java.lang.String name;*/
//获取所有构造函数
//又get到一点,Class对象的方法不是只适合让最大的类使用,方法也可以用,获取属性什么的
Constructor<?>[] constructors = cs.getConstructors();
for(int i=0;i<constructors.length;i++){
System.out.println("构造方法:"+constructors[i]);
}
for (int i = 0; i < constructors.length; i++) {
Class<?> p[]=constructors[i].getParameterTypes();
System.out.print("构造方法: ");
int mo=constructors[i].getModifiers();
System.out.print(Modifier.toString(mo)+" ");
System.out.print(constructors[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("){}");
}
//获取所有的方法
Method[] methods = cs.getMethods();
for(int i=0;i<methods.length;i++){
System.out.println("方法:"+methods[i]);
//方法具体的拼接就不写了吧
}
//调用某个方法
try {
//调用describe()方法
Method method = cs.getMethod("describe");
method.invoke(cs.newInstance());
//调用describe(id,name)方法
Method method1 = cs.getMethod("describe",int.class);
method1.invoke(cs.newInstance(),1);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//读取文件(工厂模式)
SubjectChild oj = (SubjectChild)Class.forName(Reflect.getPro().getProperty("subject")).newInstance();
oj.describe();
// 在泛型为Integer的ArrayList中存放一个String类型的对象。
ArrayList<Integer> list = new ArrayList<Integer>();
Method method = null;
try {
method = list.getClass().getMethod("add", Object.class);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
method.invoke(list, "Java反射机制实例。");
System.out.println(list.get(0));
//通过反射取得并修改数组的信息
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));
}
public static Properties getPro() throws FileNotFoundException, IOException{
Properties pro=new Properties();
File f=new File("subject.properties");
if(f.exists()){
System.out.println("aa");
pro.load(new FileInputStream(f));
}else{
pro.setProperty("subject", "reflectTest.Subject");
pro.store(new FileOutputStream(f), "SUBJECT CLASS");
}
return pro;
}
}
里面各种方法我都有注释,大家可以试试,然后看看作用就明白了,
不懂Class的可以直接去我上一篇博客查看。