文章目录
- 一,什么是反射
- 二,反射,反射的作用
- 反射做通用框架
- 实现:简单的,模拟(mybatis框架)
一,什么是反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
获取Class对象
Class c = Student.class;
二,反射,反射的作用
- 可以在运行时获得一个类的全部成分,成员变量,方法,构造器,然后可以进行操作
- 可以破坏封装性,强制夺取该类中的成分
- 也可以破坏泛型的指定
- 最重要的用途就是做java的高级框架
反射的作用之获取类的信息:反射在运行时,可以获取类对象的所有信息,相当于做了一个类的类对象调用类的属性
Class c = 类名.class;
//构造器的获取;
getConstructors();//获取所有对象中的构造器
getConstructor(Sring.class);//根据参数填写,获取单个构造器
newInstance("参数");//创建对象的方式是调用该方法
---------------------------------------------------------
//获取成员变量,作用:在某个对象中取值和赋值
getDeclaredFields();
getDeclaredField(String name);
//取值,赋值
void set();
Object get(Object obj);
---------------------------------------------------------
//Fields[],装对象容器,看如下代码
//获取方法的API
Method[] method = c.getDeclaredFields();//装多个对象方法的容器。
getMethod();//只拿public的
getMethonds();
Method method = c.getDeclaredField("方法名",多个参数可填.....);//单个方法的获取
//方法的出发执行方法
Object result = method0.invoke(类对象);
反射的作用之强制反射:即无视任何封装修饰,private等,直接获取
主要使用到,setAssessible(true);方法访问private 的成员变量或是方法,构造器。
代码理解如下,这些代码是基于student实体类
//构造器的反射获取
@org.junit.Test
public void test(){
Class c = Student.class;
//把构造器容器创建出来
Constructor[] constructors = c.getConstructors();
//遍历所有的构造器
for (Constructor constructor : constructors) {
//打印构造器的信息
System.out.println(constructor.getName()+"=====>"+constructor.getParameterCount());
}
}
@org.junit.Test
public void test1() throws Exception {
Class c = Student.class;
Constructor constructors = c.getConstructor();
System.out.println(constructors.getName()+"=====>"+constructors.getParameterCount());
//取出单个构造器
Constructor constructor = c.getConstructor(String.class);
System.out.println(constructor.getName()+"=====>"+constructor.getParameterCount());
//构造器自己创建对象,以往是我们调用构造器创建对象,所以称为反射
Object o = constructor.newInstance("潘胜志");
System.out.println(o);
//如果有了私有构造器,可以使用暴力反射,拿到构造器创建对象
//constructor.setAccessible(true);
}
//反射可获取类对象,构造器对象,成员变量对象,方法对象的提取
@org.junit.Test
public void testObject(){
Class student = Student.class;
//装所有的成员变量
Field[] fields = student.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName()+"=======>"+field.getType());
}
}
@org.junit.Test
public void testObject1() throws NoSuchFieldException, IllegalAccessException {
Class student = Student.class;
//用Filed装属性
Field field = student.getDeclaredField("age");
//属性都是私有变量,所以要强制反射
field.setAccessible(true);
System.out.println(field.getName()+"=======>"+field.getType());
Student s = new Student();
field.set(s,18);
System.out.println(s);
System.out.println(s.getAge());
}
@org.junit.Test
public void MethodX() throws Exception {
//1.先得到类对象
Class student = Student.class;
//提取全部方法
Method[] methods = student.getDeclaredMethods();
Method method = student.getDeclaredMethod("exams", String.class);
Method method0 = student.getDeclaredMethod("exams");
System.out.println(method0.getParameterCount());
System.out.println("----------------------------------------------------");
method.setAccessible(true);
method0.setAccessible(true);
System.out.println(method.getName());
System.out.println("----------------------------------------------------");
for (Method method1 : methods) {
System.out.println(method1.getName()+":"+method1.getReturnType()+":"+method1.getParameterCount());
}
//如果方法没有返回,就会默认为null
Student student1 = new Student("潘胜志");
Object result = method0.invoke(student1);
System.out.println(result);
//以前是对象调用方法,现在是方法追着对象调用,所以关系反转了
System.out.println("----------------------------------------------");
Student student2 = new Student("潘胜志",18,180.0);
Object result1 = method.invoke(student2,"潘胜志2");
System.out.println(result1);
}
@org.junit.Test
public void ClassTest() throws Exception {
ArrayList<String> list = new ArrayList<>();
ArrayList<Integer> list1 = new ArrayList<>();
System.out.println(list.getClass());
System.out.println(list1.getClass());
System.out.println(list.getClass() == list1.getClass());
System.out.println("------------------------------------------");
ArrayList<Integer> list3 = new ArrayList<>();
list.add("潘胜志");
list.add("潘胜志2");
//
Class c= list.getClass();
Method ad = c.getDeclaredMethod("add", Object.class);
Object o = ad.invoke(list3, "黑马的");
System.out.println(list3);
}
反射的作用之泛型:反射是在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意值类型的元素的。
例如:利用反射就可以使以下代码不报错。
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
//list.add("潘胜志");此时会报错
原因:泛型只是在编译阶段可以约束ijhe只能操作魔种数据类型,在编译成Class文件进入运行阶段时,其真实类型都是ArrayList了,反省相当于被移除了。泛型的真实对象就是ArrayList 。这样的内部设计是为了节约内存。
@org.junit.Test
public void ClassTest() throws Exception {
//分别设置两个List集合对象使用泛型指定数据类型
ArrayList<String> list = new ArrayList<>();
ArrayList<Integer> list1 = new ArrayList<>();
System.out.println(list.getClass());
System.out.println(list1.getClass());
System.out.println(list.getClass() == list1.getClass());
System.out.println("------------------------------------------");
//创建第三个List集合类型,将其指定的泛型类型使用反射机制破坏。所以和原无泛型List无差别
ArrayList<Integer> list3 = new ArrayList<>();
list.add("潘胜志");
list.add("潘胜志2");
//反射修改,最后结果所有的数据的放入了集合容器
Class c= list.getClass();
Method ad = c.getDeclaredMethod("add", Object.class);
Object o = ad.invoke(list3, "黑马的");
System.out.println(list3);
}
反射做通用框架
给你一个任意对象,在不清楚对象字段的情况下,可以把对象的字段名称和对象的对应的值存储到数据文件中去
分析:
- 定义一个方法,可以接受任意对象
- 每次收到一个对象后,需要解析这个对象的全部成员变量名称
- 这个对象可能是任意的,那怎么可以直到这个对象的全部名称能(只有反射可以解决)
- 反射可以获取对象的Class类对象,然后获取全部成员变量的信息
- 遍历成员变量的信息,然后取出成员变量的具体值
- 存入成员变量和值到文件中去
实现:简单的,模拟(mybatis框架)
实体类students
package com.pan.OpClass;
public class Students {
private String name;
private int age;
private String className;
private String hobby;
public Students(){
}
public Students(String name, int age, String className, String hobby) {
this.name = name;
this.age = age;
this.className = className;
this.hobby = hobby;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
实体类teachers
package com.pan.OpClass;
public class TheacherS {
private String name;
private char sex;
private double salary;
public TheacherS(String name, char sex, double salary) {
this.name = name;
this.sex = sex;
this.salary = salary;
}
public TheacherS(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
工具类mybatisUtil
package com.pan.OpClass;
/*
* 设计保存任意对象
* */
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
public class MybatisUtil {
public static void save(Object obj){
//1.返回色解决获取对象以及对象信息的问题
try(
PrintStream ps = new PrintStream(new FileOutputStream("static-java/src/com/pan/OpClass/data.txt",true));
) {
//c.getSimpleName获取当前类名,c.getName()获取全限名:包名+类名
Class c = obj.getClass();
ps.println("========================"+c.getSimpleName()+"============================");
//2.提取他的全部成员变量
Field[] fields = c.getDeclaredFields();
//3.获取它的成员变量所有的信息
for (Field field : fields) {
//强制反射出private的对象信息
field.setAccessible(true);
String name = field.getName();
//提取变量中的值
String value = field.get(obj) + "";
ps.println(name+"--"+ value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行测试类ReflectDemo
package com.pan.OpClass;
/*
* 目标;提供一个通用框架,支持保证所有信息
* */
public class ReflectDemo {
public static void main(String[] args) {
Students students = new Students();
students.setName("潘胜志");
students.setClassName("软件设计师考试");
students.setAge(18);
students.setHobby("喜欢打篮球");
MybatisUtil.save(students);
TheacherS theacherS = new TheacherS();
theacherS.setName("涂毅晗1");
theacherS.setSalary(100000);
theacherS.setSex('女');
MybatisUtil.save(theacherS);
Students students1 = new Students();
students1.setName("潘胜志1");
students1.setClassName("网络工程师考试");
students1.setAge(20);
students1.setHobby("喜欢打篮球");
MybatisUtil.save(students1);
TheacherS theacherS1 = new TheacherS();
theacherS1.setName("涂毅晗");
theacherS1.setSalary(20000);
theacherS1.setSex('女');
MybatisUtil.save(theacherS1);
}
}
运行结果文件data.txt