文章目录

  • 一,什么是反射
  • 二,反射,反射的作用
  • 反射做通用框架
  • 实现:简单的,模拟(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);
}

反射做通用框架

给你一个任意对象,在不清楚对象字段的情况下,可以把对象的字段名称和对象的对应的值存储到数据文件中去

分析:

  1. 定义一个方法,可以接受任意对象
  2. 每次收到一个对象后,需要解析这个对象的全部成员变量名称
  3. 这个对象可能是任意的,那怎么可以直到这个对象的全部名称能(只有反射可以解决)
  4. 反射可以获取对象的Class类对象,然后获取全部成员变量的信息
  5. 遍历成员变量的信息,然后取出成员变量的具体值
  6. 存入成员变量和值到文件中去

实现:简单的,模拟(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

java 反射机制过程 java反射机制的作用_junit