一.反射概述
反射是框架设计的核心部分
反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性;
反射的优点:
增加程序的灵活性,避免将程序写死到代码里,
列如:
实例化一个 person()对象, 不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码,并重新编译。
使用反射: class.forName("person").newInstance(); 而且这个类描述可以写到配置文件中,如 **.xml, 这样如果想实例化其他类,只要修改配置文件的"类描述"就可以了,不需要重新修改代码并编译。
二.反射中如何获取类对象(三种)
1· Class.forName("类的全路径名") 如:JDBC 自定义MVC框架
2· 类名.Class 如:通用查询
3· 类实例.getClass 如:通用的增删改查
写一个Student类
如:
1 package com.zjj.beike; 2 3 public class Student { 4 private String sid; 5 6 private String sname; 7 8 public Integer age; 9 10 static{ 11 System.out.println("加载进jvm中!"); 12 } 13 14 public Student() { 15 super(); 16 System.out.println("调用无参构造方法创建了一个学生对象"); 17 } 18 19 public Student(String sid) { 20 super(); 21 this.sid = sid; 22 System.out.println("调用带一个参数的构造方法创建了一个学生对象"); 23 } 24 25 public Student(String sid, String sname) { 26 super(); 27 this.sid = sid; 28 this.sname = sname; 29 System.out.println("调用带二个参数的构造方法创建了一个学生对象"); 30 } 31 32 @SuppressWarnings("unused") 33 private Student(Integer age) { 34 System.out.println("调用Student类私有的构造方法创建一个学生对象"); 35 this.age = age; 36 } 37 38 public String getSid() { 39 return sid; 40 } 41 42 public void setSid(String sid) { 43 this.sid = sid; 44 } 45 46 public String getSname() { 47 return sname; 48 } 49 50 public void setSname(String sname) { 51 this.sname = sname; 52 } 53 54 public void hello() { 55 System.out.println("你好!我是" + this.sname); 56 } 57 58 public void hello(String name) { 59 System.out.println(name + "你好!我是" + this.sname); 60 } 61 62 @SuppressWarnings("unused") 63 private Integer add(Integer a, Integer b) { 64 return new Integer(a.intValue() + b.intValue()); 65 } 66 }
1· Class.forName("类的全路径名")
代码:
1 package com.zking.reflect; 2 3 public class Demo1 { 4 5 public static void main(String[] args) throws ClassNotFoundException { 6 Class<?> forName = Class.forName("com.zking.reflect.Student"); 7 System.out.println(forName); 8 } 9 }
运行输出结果:
2· 类名.Class
代码:
package com.zking.reflect; public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { //Class<?> forName = Class.forName("com.zking.reflect.Student"); Class<?> forName = Student.class; System.out.println(forName); } }
运行输出结果:
3· 类实例.getClass
代码
package com.zking.reflect; public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { //Class<?> forName = Class.forName("com.zking.reflect.Student"); // System.out.println(cla2); Student stu=new Student(); Class forName = stu.getClass(); System.out.println(forName); }
/**
* 为什么jdbc连接要使用class.forName("com.jdbc.mysql.Driver");
* 无论是mysql的驱动Driver还是Oracle的驱动......;它必然需要实现jdbc的一个驱动接口;
* java.sql.Driver d = Class.forName("com.jdbc.mysql.Driver")
*
*
* web.xml
* <servlet>
* <servlet-name>Xxx</servlet-name>
* <servlet-class>com.caoguangli.XxxServlet</servlet-class>
* </servlet>
* .....
*
*
* com.caoguangli.XxxServlet extends httpServlet
* Class cla = Class.forName("com.caoguangli.XxxServlet");
* httpServlet httpServlet = cla.newInstanse;
*
* XxxServlet 实例
* new XxxServlet();
*
*/
}
运行输出结果:
三,反射的三大作用
1.实例化对象
2.动态调用方法
3.反射属性赋值与取值
(一)反射实例化
能够实例化未知的类
能够通过私有构造器创建实例
实例化对象 .newInstance()
getConstructor 获取的是public修饰的
getDeclaredConstrutor();获取单个构造方法
如果要调用有参构造函数就必须通过反射的方式调用带有参数的构造器来实例化对象
调用无参构造方法创建了一个学生对象
代码:
1 package com.zking.reflect; 2 3 public class Dome2 { 4 5 public static void main(String[] args) throws InstantiationException, IllegalAccessException { 6 Class Stu=Student.class; 7 Student student=(Student)Stu.newInstance(); 8 } 9 }
运行输出结果
通过反射方式调用带有参数的构造器来实例化对象
代码:
package com.zking.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Dome2 { public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { Class Stu=Student.class; // Student student=(Student)Stu.newInstance(); //调用一个带有参数的构造方法 //拿到构造器 Constructor con=Stu.getConstructor(String.class); Student student=(Student)con.newInstance("s001"); } }
运行输出结果
通过反射方式带有俩个参数的构造器来实例化对象
代码:
package com.zking.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Dome2 { public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { Class Stu=Student.class; // Student student=(Student)Stu.newInstance(); //调用俩个带有参数的构造方法 //拿到构造器 Constructor con=Stu.getConstructor(String.class,String.class); //通过构造器实例化对象 Student student=(Student)con.newInstance("s001","张三"); } }
运行输出结果
通过反射的方式调用私有的构造器来实例化对象
代码:
1 package com.zking.reflect; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.InvocationTargetException; 5 6 public class Dome2 { 7 8 public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { 9 Class Stu=Student.class; 10 11 Constructor con=Stu.getDeclaredConstructor(Integer.class); 12 con.setAccessible(true); 13 //通过构造器实例化对象 14 Student stu=(Student)con.newInstance(12); 15 } 16 }
运行输出结果
(二).动态调用方法
调用无参的方法
getDeclaredMethod("hello")
代码:
1 package com.zking.reflect; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 6 public class Demo3 { 7 8 public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { 9 Student stu=new Student(); 10 Class clz=stu.getClass(); 11 Method m=clz.getDeclaredMethod("hello"); 12 System.out.println(m.invoke(clz.newInstance())); 13 } 14 }
运行输出结果
调用有参的方法
代码:
1 package com.zking.reflect; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 6 public class Demo3 { 7 8 public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { 9 Student stu=new Student(); 10 Class clz=stu.getClass(); 11 Method m=clz.getDeclaredMethod("hello",String.class); 12 m.invoke(clz.newInstance(), "zs"); 13 } 14 }
运行输出结果
调用私有方法
要先设置访问权限setAccessible(true)
代码:
1 package com.zking.reflect; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 6 public class Demo3 { 7 8 public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { 9 Student stu=new Student(); 10 Class clz=stu.getClass(); 11 Method m=clz.getDeclaredMethod("add",Integer.class,Integer.class); 12 m.setAccessible(true); 13 //invoke:如果反射动态调用的方法是被void所修饰,那么返回的就是null 14 //如果反射动态调用的方法不是被void所修饰,那么返回的就是被调用的方法的返回值 15 Object invoke=m.invoke(stu, 20,5); 16 System.out.println(invoke); 17 } 18 }
运行输出结果
(三)反射属性赋值与取值
代码:
package com.zking.reflect; import java.lang.reflect.Field; /* * 反射属性赋值取值 * * */ public class Demo4 { public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Student stu=new Student(); stu.setSid("s001"); stu.age=18; System.out.println(stu); // 反射赋值 Class cla=stu.getClass(); Field f = cla.getDeclaredField("sid"); Field f1 = cla.getDeclaredField("age"); f.setAccessible(true); f.set(stu, "s002"); f1.set(stu, 18); System.out.println(stu); // 读 System.out.println(f.get(stu)); System.out.println(f1.get(stu)); // 使用反射读取 Field[] fields = cla.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); System.out.println(field.getName() + " : " + field.get(stu)); } } }
运行输出结果
Field field=cla.getField(“属性名”);
field.getName(); -->获取属性名
filed.getType(); -->获取属性类型
field.getModifiers(); -->获取属性访问修饰符
field.set(Object,Object); -->设置属性值,参数1:要设置属性所在对象;参数2:要设置的值;
field.get(Object); -->获取属性值,参数:要获取属性值的对象
field.getDeclaredField(“属性名”); -->获取单个属性(私有、公有、受保护、默认、静态)
field.getDeclaredFields(); -->获取所有属性(私有、公有、受保护、默认、静态)
JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符。
其中,该修饰符是java.lang.reflect.Modifier的静态属性。
对应表如下:
PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048