概念既定
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。简单的来说反射是:指程序可以访问、检测和修改它本身状态或行为的一种能力
用途用法
在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法
一切反射相关的代码都从获得类(java.lang.Class)对象开始,下面是获取类对象三种方法
1 Class.forName(完整类名)
2 类名.class
3 类实例对象.getClass()
在获取类对象是如果报ClassNotFoundException异常,则是类名错误,或者没有导包。
同一个类的、类对象只会创建一个
先创建一个Student类,如下:
public class Student { private String sid; private String sname; public Integer age; static{ System.out.println("加载进jvm中!"); } public Student() { super(); System.out.println("调用无参构造方法创建了一个学生对象"); } public Student(String sid) { super(); this.sid = sid; System.out.println("调用带一个参数的构造方法创建了一个学生对象"); } public Student(String sid, String sname) { super(); this.sid = sid; this.sname = sname; System.out.println("调用带二个参数的构造方法创建了一个学生对象"); } @SuppressWarnings("unused") private Student(Integer age) { System.out.println("调用Student类私有的构造方法创建一个学生对象"); this.age = age; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public void hello() { System.out.println("你好!我是" + this.sname); } public void hello(String name) { System.out.println(name + "你好!我是" + this.sname); } @SuppressWarnings("unused") private Integer add(Integer a, Integer b) { return new Integer(a.intValue() + b.intValue()); } @Override public String toString() { return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]"; } }
获取类对象
public class Dome1 { public static void main(String[] args) throws ClassNotFoundException { // 1,类名.Class.forName Class<?> clz = Class.forName("com.zking.reflect.Student"); // 2,类名.class Class<?> clz1 = Student.class; // 3,类实例对象.getClass() Student stu = new Student(); Class<?> clz2 = stu.getClass(); System.out.println(clz); System.out.println(clz1); System.out.println(clz2); }
反射三大作用
1 实例化对象(能够实例化未知的对象 能够通过私有构造器创建实例)
c实例.newInstance()
getConstructor只能寻找到public的修饰的构造器,getDeclaredConstructor可以寻找到任何修饰符修饰的构造器
如果报java.lang.NoSuchMethodException的错,表示构造器方法是private修饰的,要使用getDeclaredConstructor方法
如果使用getDeclaredConstructor报错:
java.lang.IllegalAccessException: Class com.zking.reflect.Demo2 can not access a member of class com.zking.reflect.Student with modifiers "private"
是因为,private方法无法访问,需设置;
.setAccessible(true);
注:一定要提供一个无参构造器
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Demo2 { public static void main(String[] args) throws Exception { Class clz = Student.class; // 反射调用无参构造方法创建了一个学生对象 Student stu = (Student) clz.newInstance(); // 要拿到构造类 Constructor con=clz.getConstructor(String.class); // 通过构造器实例化对象 Student stu1=(Student)con.newInstance("s001"); // 调用带二个参数的构造方法创建了一个学生对象 Constructor con2=clz.getConstructor(String.class,String.class); // 通过构造器实例化对象 Student stu2=(Student)con2.newInstance("s001","zs"); // 调用Student类共有的构造方法创建一个学生对象 Constructor con3=clz.getConstructor(String.class); Student stu3=(Student)con3.newInstance("s001"); // 调用Student类私有的构造方法创建一个学生对象 Constructor con4=clz.getDeclaredConstructor(Integer.class); con4.setAccessible(true); //通过构造器实例化对象 Student stu4=(Student)con4.newInstance(12); } }
2 动态调用方法
public class Demo3 { public static void main(String[] args) throws Exception { Student stu=new Student(); stu.hello(); Class clz=stu.getClass(); Method m= clz.getDeclaredMethod("hello"); m.invoke(stu); Method m1= clz.getDeclaredMethod("add",Integer.class,Integer.class); m1.setAccessible(true); // invoke:如果反射动态调用的方法是被void所修饰,那么返回的就是null // 如果反射动态调用的方法不被void所修饰, 那么返回的就是被调用的方法的返回值 Object invoke=m1.invoke(stu,20,5); System.out.println(invoke); } }
3 读写属性
public class Demo4 { public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Student stu=new Student("s001","ls"); stu.age=22; Class clz=stu.getClass(); Field[] fields=clz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); System.out.println(field.getName()+" : "+field.get(stu)); } } }