反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
Java反射机制是一个非常强大的功能,在很多大型项目比如Spring, Mybatis都可以看见反射的身影。通过反射机制我们可以在运行期间获取对象的类型信息,利用这一特性我们可以实现工厂模式和代理模式等设计模式,同时也可以解决Java泛型擦除等令人苦恼的问题 。
spring 的 ioc/di 也是反射…
javaBean和jsp之间调用也是反射…
struts的 FormBean 和页面之间…也是通过反射调用…
JDBC 的 classForName()也是反射…
hibernate的 find(Class clazz) 也是反射…
(所以说反射是框架的基础,我们得好好学习反射)
反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创和控制任何类的对象,无需提前硬编码目标类
性能问题,使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用
准备student.class的实体类
package com.wxm; 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());
}
}
1.获取类对象(三种方式)
1.1 Class.forName(“全路径名”); jdbc/自定义框架要用
Class forName=Class.forName("com.wxm.Student");
Class stuClas=Student.class;
System.out.println(stuClas);
效果
1.3. 类实例的类实例的getClass()获取 通用的增删改查
Student stu=new Student();
Class stuClas=stu.getClass();
System.out.println(stuClas);
效果
2. 利用反射进行对象的实例化
优点: 1.能够对未知的对象进行实例化 2.能够对私有的构造器实例化对象
2.1 调用无参构造器
第一种方法:
Student stu=new Student();
Class stuClas=stu.getClass();
System.out.println(stuClas);
Object stu2= stuClas.newInstance();
//newInstance默认调用无参构造器
System.out.println(stuClas);
如果我们注释掉实体类的无参构造器
会报如下的异常
2.2调用有参构造器
Class stuClas2=stu.getClass();
Constructor constructor=stuClas2.getConstructor(String.class);
Student stu1=(Student)constructor.newInstance("zs");
Class stuClas2=stu.getClass();
Constructor constructor=stuClas2.getConstructor(String.class,String.class);
Student stu2=(Student)constructor.newInstance("s001","刘翔");
错误示范:当时我少了一个对应的参数
2.3调用私有构造器去实例化对象
getConstructor与getDeclaredConstructor的区别(getConstructor只能被public修饰,不然要给权限****constructor.setAccessible(true))
错误示范:
java.lang.IllegalAccessException:
// java.lang.IllegalAccessException: //Class com.wxm.Demo2 can not access a member of class com.wxm.Student with modifiers "private 给权限就好了
constructor.setAccessible(true);//默认false
正确示范
Constructor constructor=stuClas2.getDeclaredConstructor(Integer.class);
constructor.setAccessible(true);//给权限
Student stu2=(Student)constructor.newInstance(18);
3.反射读写属性 自定义标签库,通用分页,自定义mvc
3.1.public修饰的属性
Student stu=new Student("s001","张三");
stu.age=22;
System.out.println(stu.getSid());
System.out.println(stu.getSname());
Student stu=new Student("s001","张三");
Class stuclas=stu.getClass();
Field f=stuclas.getDeclaredField("age");
f.setAccessible(true);//因为属性是private,私有属性必须给权限
System.out.println(f.get(stu));
Field [] fields= stuclas.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println(field.getName()+":"+field.get(stu));
}
5.访问修饰符
Modifier提供了很多静态方法,对类和成员访问修饰符进行解码。
Field [] fields= Student.class.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
//1.获得源类的访问修饰符
int mod=stuclas.getModifiers();
System.out.println(field.getName()+"访问修饰符是否包括private:"+Modifier.isPrivate(mod))
stem.out.println(field.getName()+"访问修饰符是否包括private:"+Modifier.isPublic(mod)); System.out.println(field.getName()+"访问修饰符是否包括private:"+Modifier.isStatic(mod)); }
6、通过Class对象,获得源类的父类、接口、注解
Class sClass=stuclas.getSuperclass();
System.out.println(“父类的类型:”+sClass.getName());
Class[] interfaces=stuclas.getInterfaces();
if(interfaces!=null) {
for (Class aclass : interfaces) {
System.out.println(“实现接口的类型”+aclass.getName());
} }
//获取当前类上的所有注解
Annotation[] annotations=stuclas.getAnnotations();
//Data data=(Data)stuclas.getAnnotation(Data.class);
if(annotations!=null) {
for (Annotation annotation : annotations) {
System.out.println(“类的注解的类型”+annotation.annotationType().getName()); }
}