反射是java语言中的一种机制,通过这种机制可以动态的实例化对象、读写性、调用方法
获取类类的类对象的三种方式
1、Class.forName
2、类.class(以后会用到通用查询的方法)
3、类类的类对象的类实例.getClass() (通用增删改)
辅助类Student
package com.lxy.reflect; 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()); } }
package com.lxy.reflect; public class Test { public static void main(String[] args) throws Exception { //Student.class Class stu = Class.forName("com.lxy.reflect"); //通用查询 Class stu2=Student.class; //通用增删改 Class stu3=new Student().getClass(); } }
package com.lxy.reflect; import java.lang.reflect.Constructor; public class Test2 { public static void main(String[] args) throws Exception { Class<Student> stu = (Class<Student>) Class.forName("com.lxy.reflect.Student"); Student s=(Student)stu.newInstance(); s.hello(); //反射调用有参构造器 //getDeclaredConstructor与getConstructor的区别 Constructor<Student> c = stu.getConstructor(String.class); Student s1=c.newInstance("s001"); Constructor<Student> c2 = stu.getConstructor(String.class,String.class); Student s2=c2.newInstance("s001","zs"); Constructor<Student> c3 = stu.getDeclaredConstructor(Integer.class); //打开访问权限 c2.setAccessible(true); Student s3=c3.newInstance(26); } }
运行结果
注意:如果它报IllegalAccessException 的错
解决方法:把访问权限打开就好了setAccessible(true)
package com.lxy.reflect; import java.lang.reflect.Method; public class Test3 { public static void main(String[] args) throws Exception { Class<Student> stu = (Class<Student>) Class.forName("com.lxy.reflect.Student"); Student s=stu.newInstance(); Method m=stu.getDeclaredMethod("hello"); //invoke参数1:类实例,在这里指的是Student类实例 //参数2:当前被调用的方法,传递的参数值 //invoke的返回值,就是被反射调用的方法的返回值,如果被调用的方法是void,那么返回null System.out.println(m.invoke(s)); Method m2=stu.getDeclaredMethod("hello",String.class); System.out.println(m2.invoke(s, "zs")); Method m3=stu.getDeclaredMethod("add",Integer.class,Integer.class); //打开访问权限 m3.setAccessible(true); System.out.println(m3.invoke(s, 10, 5)); } }
运行结果
getDeclaredFields()可以通过遍历的方式获取类里面的每个属性,相比于oop来说,取值更方便
package com.lxy.reflect; import java.lang.reflect.Field; public class Test4 { public static void main(String[] args) throws Exception { Class<Student> stu = (Class<Student>) Class.forName("com.lxy.reflect.Student"); Student s=stu.newInstance(); Field f=stu.getDeclaredField("sname"); f.setAccessible(true); //反射写属性 f.set(s, "zs"); System.out.println(s.getSname()); //反射读属性 System.out.println(f.get(s)); //比较oop与反射读取属性值的方式 Student st=new Student("s002", "ls"); st.age=22; System.out.println(st.getSid()); System.out.println(st.getSname()); System.out.println(st.age); //反射获取该对象所有属性值 Field[] fields=stu.getDeclaredFields(); for (Field ff : fields) { ff.setAccessible(true); System.out.println(ff.getName()+":"+ff.get(st)); } } }
运行结果