①什么是反射?
概念:
反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
作用:
能够让代码更具灵活性,能够将未知的对象进行实例化
②反射的调取方法
核心点:一切反射相关的代码都从获得类对象开始
1.获取类对象的三种方式
方法 | 介绍 |
---|---|
Class.forName(“完整类名”) | 通过class.forName获取类对象 |
Xxx.class | 类名点class返回一个Class类对象 |
对象点getClass() | 先实例化对象在调取.getClass返回去类对象 |
这里以实例给大家展示
package com.tanle.reflect;
/**
*
* @author tanle
* 获取类对象的三种方式
* Class.forName("")
* Xxx.class
* 对象.getClass
*
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
//调取
//①
Class<?> forName = Class.forName("com.tanle.reflect.Student");
System.out.println(forName);
//②
Class forName2=Student.class;
System.out.println(forName2);
//③
Student stu=new Student();
Class forName3 = stu.getClass();
System.out.println(forName3);
}
}
代码执行结果
2.反射实例化对象
都需要先获取类对象(以代码的方式给大家看,里面书写了一些可能会报的错误)
方法 | 介绍 |
---|---|
newInstance(); | 无参共有的实例化 |
getConstructor(类型.class) | 有一个参数的共有构造器实例化 |
getConstructor(类型.class,类型.class) | 有两个参数的共有构造器实例化 |
getDeclaredConstructor(类型.class) | 私有的构造器实例化 |
package com.tanle.reflect;
import java.lang.reflect.Constructor;
/**
*
* @author tanle
*
* 反射实例化对象
* 1.无参共有的实例化
* 2.有一个参数的共有构造器实例化
* 3.有两个参数的共有构造器实例化
* 4.私有的构造器实例化
*/
public class Demo2 {
public static void main(String[] args) throws Exception{
//oop实例化对象
Student stu=new Student();
Class<? extends Student> cla = stu.getClass();
//反射实例化对象
//1.无参共有的实例化
System.out.println("1.无参共有的实例化");
Student stu2 = (Student) cla.newInstance();
System.out.println(stu2);
//可能会报的错误
//java.lang.NoSuchMethodException:student类中没有Interger为参数的构造方法
//getConstructor是获取到public 修饰的构造方法
//getDeclaredConstructor能够获取到任意修饰符的构造器
//Exception in thread "main" java.lang.IllegalAccessException:非法访问,应为这个构造器是private修饰
//2.有一个参数的共有构造器实例化
System.out.println("2.有一个参数的共有构造器实例化:");
Constructor<? extends Student> c= cla.getConstructor(String.class);
Student stu3 = c.newInstance("s001");
System.out.println(stu3);
//3.有两个参数的共有构造器实例化
System.out.println("3.有两个参数的共有构造器实例化:");
Constructor<? extends Student> c1= cla.getConstructor(String.class,String.class);
Student stu4 = c1.newInstance("s001","张三");
System.out.println(stu4);
//4.私有的构造器实例化
System.out.println("4.私有的构造器实例化:");
Constructor<? extends Student> c2= cla.getDeclaredConstructor(Integer.class);
c2.setAccessible(true);
Student stu5 = c2.newInstance(2);
System.out.println(stu5);
}
}
代码执行结果
3.反射调用方法
都是以类对象为前提的
动态被调用的方法,如果该方法是void类型的返回值,那么invoke,此时结果为null
方法 | 介绍 |
---|---|
getMethod(“方法名”); | 类对象 点getMethod返回一个Method |
getMethod(“方法名”,数据类型.class) | 有一个参数的方法调用 |
getDeclaredMethod(“方法名”, 数据类型.class) | 私有的方法调用 |
package com.tanle.reflect;
import java.lang.reflect.Method;
/**
*
* @author tanle
*
* 调用方法
* 1.无参共有的方法调用
* 2.有一个参数的方法调用
* 3.私有的方法调用
*
*/
public class Demo3 {
public static void main(String[] args) throws Exception{
Student stu=new Student();
Class<? extends Student> cla=stu.getClass();
Method m = cla.getMethod("hello");
Object invoke = m.invoke(stu);
//动态被调用的方法,如果该方法是void类型的返回值,那么invoke,此时结果为null
System.out.println(invoke);
//2.有一个参数的方法调用
Method m2 = cla.getMethod("hello",String.class);
Object invoke2 = m2.invoke(stu, "狗蛋");
System.out.println(invoke2);
//3.私有的方法调用
Method m3 = cla.getDeclaredMethod("add", Integer.class,Integer.class);
m3.setAccessible(true);
Object invoke3 = m3.invoke(stu, 20,5);
//动态被调用的方法,如果该方法是非void类型的返回值,那么invoke后就是该方法被调用的结果
System.out.println(invoke3);
}
}
代码执行结果
4.反射读取属性
1.共有的属性 2.私有的属性
一般都使用私有的方法进行调用
package com.tanle.reflect;
import java.lang.reflect.Field;
/**
*
* @author tanle
*
* 反射读写属性
* 1.共有的属性
* 2.私有的属性
*
*/
public class Demo4 {
//获取success这个变量被那些修饰符所修饰
//private 代表1
//public 代表2
private static final String success="登录成功";
public static void main(String[] args) throws Exception{
Student stu=new Student("s001","狗蛋");
stu.age=22;
Class<? extends Student> cla = stu.getClass();
//2.私有的属性
Field f = cla.getDeclaredField("sname");
f.setAccessible(true);
System.out.println(f.get(stu));
//反射读写属性的常用方法(一次性获取该类的所有属性值)
Field[] fs = cla.getDeclaredFields();
for (Field fi : fs) {
fi.setAccessible(true);
System.out.println(fi.get(stu));
}
//设置
//通过反射改变sname对应的值
f.set(stu, "铁蛋");
System.out.println(stu.getSname());
}
}
代码运行结果
③Student类代码展示
package com.tanle.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());
}
}
④总结
反射对其他一些框架来说是基础代码块,所有一定要整明白o