什么是反射
反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
一切反射相关的代码都从获得类(java.lang.Class)对象开始
首先需要一个类:
package com.leiyuanlin.reflect;
import java.io.Serializable;
public class Student implements Serializable{
private String sid;
private String sname;
public Integer age;
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
static {
System.out.println("Student被加载到JVM中");
}
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 + "]";
}
}
获取类对象的3种方式:
1.Class.forName(完整类名)
package com.leiyuanlin.reflect;
/**
* 如何获取类对象(三种方式)
* 1、Class.forName("类的全路径名")
* 2、类名.class
* 3、类实例.getClass()
*
* 好处:1、提高代码的灵活性
* 2、安全性高
* @author 2018101801
*
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
// 如何获取类对象(三种方式)
// 1、Class.forName("类的全路径名")
Class cl = Class.forName("com.leiyuanlin.reflect.Student");
System.out.println(cl);
}
结果:
2、类名.class
package com.leiyuanlin.reflect;
/**
* 如何获取类对象(三种方式)
* 1、Class.forName("类的全路径名")
* 2、类名.class
* 3、类实例.getClass()
*
* 好处:1、提高代码的灵活性
* 2、安全性高
* @author 2018101801
*
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
// 如何获取类对象(三种方式)
// 2、类名.class
Class cl2 = Student.class;
System.out.println(cl2);
}
}
结果:
3、类(Class类的类对象)实例.getClass()
package com.leiyuanlin.reflect;
/**
* 如何获取类对象(三种方式)
* 1、Class.forName("类的全路径名")
* 2、类名.class
* 3、类实例.getClass()
*
* 好处:1、提高代码的灵活性
* 2、安全性高
* @author 2018101801
*
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
// 如何获取类对象(三种方式)
// 3、类(Class类的类对象)实例.getClass()
Student stu = new Student();
Class cl3 = stu.getClass();
System.out.println(cl3);
}
}
结果:
注意:
1.ClassNotFoundException(类名错|少jar包)
2. 同一类的类对象只会创建一个
反射三大作用(java.lang.reflect.*)
1、实例化对象
方法:c.newInstance()
Constructor.getConstructor/Constructor.getDeclaredConstructor
注意:一定要提供无参构造器
由上面的student类来做例子
第一种(反射调用无参构造方法创建一个学生对象):
package com.leiyuanlin.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 1、能够实例化未知的类
* 2、能够通过私有构造器创建实例
* @author 2018101801
*
*/
public class Demo2 {
public static void main(String[] args) throws Exception {
Class clz = Student.class;
// 反射调用无参构造方法创建一个学生对象
Student stu = (Student) clz.newInstance();
System.out.println(stu);
}
}
结果:
第二种(反射调用带一个参数的构造方法创建了一个学生对象):
package com.leiyuanlin.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 1、能够实例化未知的类
* 2、能够通过私有构造器创建实例
* @author 2018101801
*
*/
public class Demo2 {
public static void main(String[] args) throws Exception {
// 反射调用带一个参数的构造方法创建了一个学生对象
// 1、拿到构造器类
Constructor con = clz.getConstructor(String.class);
// 2、通过构造器实例化对象
Student stu1 = (Student)con.newInstance("s001");
}
}
结果:
第三种(反射调用带二个参数的构造方法创建了一个学生对象):
package com.leiyuanlin.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 1、能够实例化未知的类
* 2、能够通过私有构造器创建实例
* @author 2018101801
*
*/
public class Demo2 {
public static void main(String[] args) throws Exception {
// 反射调用带二个参数的构造方法创建了一个学生对象
// 1、拿到构造器类
Constructor con2 =clz.getConstructor(String.class,String.class);
// 2、通过构造器实例化对象
Student stu2 = (Student)con2.newInstance("s001","zs");
}
}
结果:
第四种(反射调用Student类私有的构造方法创建一个学生对象):
package com.leiyuanlin.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 1、能够实例化未知的类
* 2、能够通过私有构造器创建实例
* @author 2018101801
*
*/
public class Demo2 {
public static void main(String[] args) throws Exception {
// 反射调用Student类私有的构造方法创建一个学生对象
// getConstructor只能寻找到public修饰的构造器
// getDeclaredConstructor可以寻找到任何修饰符修饰的构造器
// java.lang.NoSuchMethodException(找不到方法)
// 1、拿到构造器类
// Constructor con3 = clz.getConstructor(Integer.class);
// java.lang.IllegalArgumentException: Class com.leiyuanlin.reflect.Demo2 can not access a member of class com.leiyuanlin.reflect.Student with modifiers "private"(不允许访问)
Constructor con3 = clz.getDeclaredConstructor(Integer.class);
// setAccessible(设置访问权限)默认不能访问私有方法,设置为true则允许访问
con3.setAccessible(true);
// 2、通过构造器实例化对象
Student stu3 = (Student)con3.newInstance(123);
}
}
结果:
2、动态调用方法
Method m;
m.invoke
同上用student类举例
第一种(调用无参方法):
package com.leiyuanlin.reflect;
import java.lang.reflect.Method;
/**
* 反射调用方法
* @author 2018101801
*
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
Student stu = new Student();
Class clz = stu.getClass();
// 调用无参方法
Method m = clz.getDeclaredMethod("hello");
m.invoke(stu);
}
}
结果:
第二种(调用有参方法):
package com.leiyuanlin.reflect;
import java.lang.reflect.Method;
/**
* 反射调用方法
* @author 2018101801
*
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
Student stu = new Student();
Class clz = stu.getClass();
// 调用有参方法
Method m = clz.getDeclaredMethod("hello",String.class);
m.invoke(stu,"zs");
}
}
结果:
第三种(调用私有方法):
package com.leiyuanlin.reflect;
import java.lang.reflect.Method;
/**
* 反射调用方法
* @author 2018101801
*
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
Student stu = new Student();
Class clz = stu.getClass();
// 调用私有方法
Method m = clz.getDeclaredMethod("add",Integer.class,Integer.class);
m.setAccessible(true);
// invoke 如果反射动态调用的方法是被void所修饰,那么返回的就是null
// 如果反射动态调用的方法是不被void所修饰,那么返回的就是被调用的方法的返回值
Object invoke = m.invoke(stu,3,4);
System.out.println(invoke);
}
}
结果:
3、读写属性
Field set/get
同上举例
赋值、取值:
package com.leiyuanlin.reflect;
import java.lang.reflect.Field;
/**
* 反射属性赋值取值
*
* 反射能将jsp传递过来的参数直接封装到实体类中
* @author 2018101801
*
*/
public class Demo4 {
public static void main(String[] args) throws Exception {
Student stu = new Student();
stu.age = 22;
Class clz = stu.getClass();
// 赋值
Field field = clz.getDeclaredField("sid");
field.setAccessible(true);
field.set(stu, "s001");
System.out.println(stu);
// 取值
System.out.println(field.get(stu));
}
结果:
取值:
package com.leiyuanlin.reflect;
import java.lang.reflect.Field;
/**
* 反射属性赋值取值
*
* 反射能将jsp传递过来的参数直接封装到实体类中
* @author 2018101801
*
*/
public class Demo4 {
public static void main(String[] args) throws Exception {
Student stu = new Student("s002","zs");
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));
}
}
}
结果:
感谢观看!