意义
反射是java中的动态机制,它允许我们在程序运行期间再确定类的实例化,方法的调用,属性的调用等,而不是传统意义上的在编码期间确定。
因此,反射可以大大的提高代码的灵活度,但是随之而来的是更多的系统开销和较慢的运行速度,因此不能过度的依赖反射。
反射机制第一步:在程序运行期间获取要操作的类的类对象。 类对象:Class类的实例 JVM加载一个类时,就会实例化一个Class的实例与其绑定,并且这个Class实例中会记录加载的类的一切信息: 类名,包名,属性,方法,构造器。
类对象有三种获取方式
第一种:通过类名点class
package reflectt;
import java.io.File;
import java.lang.reflect.Method;
public class reflecT {
public static void main(String[] args) throws Exception {
Class cla=String.class;
System.out.println(cla.getname());//class java.lang.String
//注意:基本类型只有这种用着种方式来获取类对象
Class cl=int.class;
System.out.println(cl.getName());//int
Class cc=reflecT.class;
System.out.println(cc.getName());//reflectt.reflecT
}
}
注意:基本类型只能用这种方式来获取!
第二种:
Class.forname();
完整的类名 即:包名点类名 以此处为例:reflectt.reclecT
package reflectt;
import java.io.File;
import java.lang.reflect.Method;
public class reflecT {
public static void main(String[] args) throws Exception {
Class cla=Class.forname("relfectt.rflecT");
Class c=Class.forname("java.lang.String");
第三种:
用CLass 类名点 class点getClassL=点oader.getResouse点toUri
reflecT.class.getClassLoader.getResouse.toUri
package reflect;
import java.io.File;
import java.lang.reflect.Method;
public class reflecT {
public static void main(String[] args) throws Exception {
//该文件所在目录的上一个目录下,即:上两级下的
File cls=new File(reflecT.class.getResource(".").toURI());
//该文件所在目录下的,即:上以及下的
File c=new File(reflecT.class.getClassLoader().getResource(".").toURI());
File[] files=cls.listFiles();
for (File file : files) {
System.out.println(file.getName());//与其项目同级的
}
System.out.println("----------------------------");
File[] ff= c.listFiles();//与本类同级的
for (File file : ff) {
System.out.println(file.getName());
}
2,获取方法
Method称为方法对象,该类的每一个实例用于表示一个方法,该对象上记录这其表示的方法里的所有信息 如:方法的访问修饰符,返回值类型,方法名,参数列表信息等。
package reflect;
import java.io.File;
import java.lang.reflect.Method;
public class reflecT {
public static void main(String[] args) throws Exception {
//获取指定的类
Class cls = Class.forname("reflect");
//或取指定类的方法 hello方法
Method method = cls.getMethod("hello");
//获取指定类的所有方法
Method[] methods = clss.getMethods();
//增强for循环
for(Method m : methods){
System.out.println(m.getName);//reflect类里面的所有方法名
}
}
}
利用反射机制实例化对象,并调用有参和无参构造器。
package reflect;
import java.io.File;
import java.lang.reflect.Method;
public class reflecT {
public static void main(String[] args) throws Exception {
Class cla = Class.forName("good");//获取类对象
Object obj = cla.newInstance();//该方法会调用Class所表示的类的[无参构造器]实例化对象
System.out.println(obj);
//Person{name='张三', age=22}
// Class提供的获取特定构造器的方法:
// Constructor getConstructor(Class... argsType)
// 要将特定构造器的参数类型对应的类对象有序传入即可
Constructor cc = cla.getConstructor(String.class,int.class);//这里传入每个参数类型对应
//的类对象
Object oo = cc.newInstance("王五",26);
System.out.println(oo);//Person{name="王五", age=26}
}
}
利用反射机制进行上述操作的步骤: 1:获取类对象 2:实例化对象 3:通过类对象获取要调用的方法对象 4:利用方法对象进行方法的调用
利用反射机制调用方法
Method对象提供了调用该方法的操作: Object invoke(Object obj,Object[] args) 参数1:当前Method对象表示的方法的所属对象 参数2:该方法的实参列表 返回值:实际调用该方法后该方法的返回值。
package reflect;
import java.io.File;
import java.lang.reflect.Method;
public class reflecT {
public static void main(String[] args) throws Exception {
Class cls = Class.forName(reflect.reflecT);
Object o = cls.newInstance();//实例化对象
Method method = cls.getMethod("hi");
method.invoke(o);//调用该对象的对应方法
//调用有参方法
Class cc = Class.forName(reflect.reflecT);
Object oo = cc.newInstance();
Method methodd = cc.getMethod("hello",String.class,int.class);//参数类型,顺序,个数必
须与方法一致
methodd.invock(o,"study",80);//实参的个数,类型,顺序也必须与方法定义一致
}
}
通过反射机制可以调用私有方法
Class提供了对应的方法:
Method getDeclaredMethod(String method,Class... argsType)
Method[] getDeclearMethods()
hehe();是私有方法
package reflect;
import java.io.File;
import java.lang.reflect.Method;
public class reflecT {
public static void main(String[] args) throws Exception {
Class cl=Class.foeName("reflect.reflecT");
Object obj=cl.newInstance();
Method method =cl.getDeclaredMethod("hehe");
method.setAccessible(true);//强行打开访问权限,此时下面就不会出现非法访问异常,并可调
//用私有方法!!!
//获取当前类定义的指定方法(可以获取本类定义的私有方法)
// Method[] getDeclaredMethods()
//获取当前类定义的所有方法(不包含从超类继承的)
method.invoke(o);
}
}
操作属性
实际开发中,我们几乎不会对属性直接操作,都是借助于属性提供的get,set方法进行的。
反射中也差不多直接获取setxxx,getxxx方法后做后续的操作
package reflect;
import java.io.File;
import java.lang.reflect.Method;
public class reflecT {
public static void main(String[] args) throws Exception {
Class cls =Class.getName("reflect.reflecT);
Object o =cls.newInstance();
Method m =cls.getMethod("setname",String.class);
m.invoke(o,"路非");
}
}