反射(框架之基础)

一.什么是反射与应用

反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法

Java反射机制是一个非常强大的功能,在很多大型项目比如Spring, Mybatis都可以看见反射的身影。通过反射机制我们可以在运行期间获取对象的类型信息,利用这一特性我们可以实现工厂模式和代理模式等设计模式,同时也可以解决Java泛型擦除等令人苦恼的问题 。

spring 的 ioc/di 也是反射…
javaBean和jsp之间调用也是反射…
struts的 FormBean 和页面之间…也是通过反射调用…
JDBC 的 classForName()也是反射…
hibernate的 find(Class clazz) 也是反射…
(所以说反射是框架的基础,我们得好好学习反射)

1.反射的优点

反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创和控制任何类的对象,无需提前硬编码目标类

2.反射的缺点

性能问题,使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用

3.反射的API示范

准备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");

效果:反射(框架之基础)_第1张图片
1.2 类名.class 结合泛型做通用分页查询

Class  stuClas=Student.class;
System.out.println(stuClas);

效果
反射(框架之基础)_第2张图片
1.3. 类实例的类实例的getClass()获取 通用的增删改查

	Student stu=new Student();
	Class stuClas=stu.getClass();
	System.out.println(stuClas);

效果
反射(框架之基础)_第3张图片
2. 利用反射进行对象的实例化
优点: 1.能够对未知的对象进行实例化 2.能够对私有的构造器实例化对象

2.1 调用无参构造器
第一种方法:

Student stu=new Student(); 
Class stuClas=stu.getClass();
System.out.println(stuClas);

效果
反射(框架之基础)_第4张图片
第二种方法

Object stu2= stuClas.newInstance();
//newInstance默认调用无参构造器	
System.out.println(stuClas);

反射(框架之基础)_第5张图片
如果我们注释掉实体类的无参构造器
反射(框架之基础)_第6张图片
会报如下的异常反射(框架之基础)_第7张图片
2.2调用有参构造器

Class stuClas2=stu.getClass(); 
Constructor constructor=stuClas2.getConstructor(String.class); 	
Student stu1=(Student)constructor.newInstance("zs");

反射(框架之基础)_第8张图片
2.2.1调用有两个参数构造器

Class stuClas2=stu.getClass(); 	
Constructor constructor=stuClas2.getConstructor(String.class,String.class);	
Student stu2=(Student)constructor.newInstance("s001","刘翔");

反射(框架之基础)_第9张图片
错误示范:当时我少了一个对应的参数
反射(框架之基础)_第10张图片
2.3调用私有构造器去实例化对象
getConstructor与getDeclaredConstructor的区别(getConstructor只能被public修饰,不然要给权限****constructor.setAccessible(true))

错误示范:
反射(框架之基础)_第11张图片
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);

效果如下
反射(框架之基础)_第12张图片

3.反射读写属性 自定义标签库,通用分页,自定义mvc

3.1.public修饰的属性

  Student stu=new Student("s001","张三");
   stu.age=22;
System.out.println(stu.getSid());
 System.out.println(stu.getSname());

反射(框架之基础)_第13张图片
3.2.private修饰的属性
一定要给于权限!!!

 Student stu=new Student("s001","张三"); 
 Class stuclas=stu.getClass();
 Field f=stuclas.getDeclaredField("age");  
 f.setAccessible(true);//因为属性是private,私有属性必须给权限
 System.out.println(f.get(stu));

反射(框架之基础)_第14张图片
3.3 获取student实例中的所有属性及属性值

  Field [] fields= stuclas.getDeclaredFields();
  for (Field field : fields) {
   field.setAccessible(true);
   System.out.println(field.getName()+":"+field.get(stu));
  }  

反射(框架之基础)_第15张图片
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));				}

反射(框架之基础)_第16张图片
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()); }
}
反射(框架之基础)_第17张图片

你可能感兴趣的:(我的第一课,面试题,后端)