java反射知识点小结

该博客围绕Java反射展开,介绍了通过反射获取类以及获取反射类实例后的操作,还给出了项目结构示意图。同时提供了参考代码的链接、springboot版本代码链接,以及腾讯课堂和网易云课堂的相关视频教程链接。

参考代码:https://github.com/ZhangXiaoixiang/reflectdemo

springboot版本的(找java-base分支)https://gitee.com/zhang-xiao-xiang/all-demo-parent.git

说明:收集的网上资料,自己整理收集

视频教程(腾讯课堂): https://ke.qq.com/webcourse/index.html#cid=298879&term_id=100354189&taid=2094161629319039&vid=t1426y3hmoz
视频教程(网易云课堂): https://study.163.com/course/courseLearn.htm?courseId=1005927016#/learn/video?lessonId=1053358058&courseId=1005927016

1:通过反射获取类

package com.example.java.base.reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * ReflectDemo01:反射获取类相关(基本操作)
 *
 * @author zhangxiaoxiang
 * @date 2020/11/3
 */
public class ReflectTest {
    /**
     * 通过反射获取类(获取反射对象的3种方式 意区别,有的需要抛异常有的不需要)
     */
    public static void demo01() {
        try {
            Class<?> perClazz = Class.forName("com.example.java.base.reflect.Person");
            System.out.println("方式1===>通过Class.forName(\"全类名\")\t" + perClazz);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        Class<?> perClazz2 = Person.class;
        System.out.println("方式2===>类名.class\t" + perClazz2);

        Person per = new Person();
        Class<?> perClazz3 = per.getClass();
        System.out.println("方式3===>对象.getClass()\t" + perClazz3);
    }


    /**
     * 为了方便,这里定义一个方法获取反射,方便后面测试,这里使用的方式一为示例
     *
     * @return 获取到的反射对象
     */
    public static Class<?> getClassTest() {
        //Class入口
        Class<?> perClazz = null;
        try {
            perClazz = Class.forName("com.example.java.base.reflect.Person");
            return perClazz;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取方法(所有的都可以)
     */
    public static void demo02() throws IllegalAccessException, InstantiationException {
        //Class入口
        Class<?> perClazz = getClassTest();
        //获取所有的 公共的方法(1.本类 以及 父类、接口中的所有方法  2.符合访问修饰符规律),注意空指针
        System.out.println("===================================获取方法(所有的都可以)===========================");
        Method[] methods = Objects.requireNonNull(perClazz).getMethods();
        System.out.println("公共的方法==========");
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("所有的方法==========");
        //获取当前类的所有方法(1.只能是当前类   2.忽略访问修饰符限制)
        Method[] declaredMethods = perClazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("===================================获取所有的接口===========================");

        Class<?>[] interfaces = perClazz.getInterfaces();
        for (Class<?> inter : interfaces) {
            System.out.println(inter);
        }
        System.out.println("===================================获取所有的父类===========================");
        Class<?> superclass = perClazz.getSuperclass();
        System.out.println(superclass);
        System.out.println("===================================获取所有的构造方法===========================");
        Constructor<?>[] constructors = perClazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("===================================获取所有的构造方法===========================");
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("===================================获取所有的属性(公共和私有等)===========================");
        System.out.println("所有公共属性====");
        Field[] fields = perClazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("所有属性  (属性的 :公共属性 所有属性的区别 同“方法”)====");
        Field[] declaredFields = perClazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("============================获取当前反射所代表类(接口) 的对象(实例)===========================");
        Object instance = perClazz.newInstance();
        Person per = (Person) instance;
        per.interface2Method();
    }

    /**
     * 测试
     *
     * @throws InstantiationException 异常1
     * @throws IllegalAccessException 异常2
     */
    @Test
    public void test2() throws InstantiationException, IllegalAccessException {
        System.out.println("************************获取反射对象的3种方式************************");
        demo01();
        System.out.println("************************获取反射其他信息********************************");
        demo02();
    }
}

2获取到反射类实例后操作

package com.example.java.base.reflect;

import org.junit.Test;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Properties;

/**
 * ReflectDemo02:反射获取类的实例,并操作
 *
 * @author zhangxiaoxiang
 * @date 2020/11/3
 */
public class Reflect2Test {
    /**
     * 为了方便,这里定义一个方法获取反射,方便后面测试,这里使用的方式一为示例
     *
     * @return 获取到的反射对象
     */
    public static Class<?> getClassTest() {
        Class<?> perClazz = null;
        try {
            perClazz = Class.forName("com.example.java.base.reflect.Person");
            return perClazz;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取对象的实例,并操作对象
     *
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static void demo01() throws IllegalAccessException, InstantiationException, NoSuchFieldException,
            NoSuchMethodException, InvocationTargetException, IOException {
        Class<?> perClazz = getClassTest();
        Person per = (Person) Objects.requireNonNull(perClazz).newInstance();
        per.setId(1);
        per.setName("zs");
        per.setAge(23);
        per.setDesc("我是描述属性");
        System.out.println("===============================为对象赋值============================================");
        System.out.println(per.toString());
        System.out.println("===============================操作属性============================================");
        Field idField = perClazz.getDeclaredField("id");
        //访问的是private修饰的id,但是private是私有
        //修改属性的访问权限  使用反射时,如果 因为访问修饰符限制造成异常,可以通过  Field/Method/Constructor.setAccessible(true)
        idField.setAccessible(true);
        //per.setId(1);
        idField.set(per, 2);
        System.out.println("修改私有属性后:"+per.toString());
        Method method = perClazz.getDeclaredMethod("privateMethodTest", null);
        method.setAccessible(true);
        //方法的调用:invoke()
        method.invoke(per, null);
        //per.say(xxx);
        Method method2 = perClazz.getDeclaredMethod("privateMethodTest", String.class);
        method2.setAccessible(true);
        method2.invoke(per, "我是pram");
        System.out.println("===============================操作构造方法============================================");
        //		Constructor<?>[] constructors = perClazz.getConstructors() ;//公共
        //		for(Constructor constructor:constructors) {
        //			System.out.println(constructor);
        //		}
        
        //		Constructor<?>[] constructors = perClazz.getDeclaredConstructors() ;//本类
        //		for(Constructor constructor:constructors) {
        //			System.out.println(constructor);
        //		}

        //获取指定的构造方法
        //在反射中,根据类型 获取方法时:基本类型(int、char...)和包装类(Integer,Character)是不同的类型
        // Constructor<?> constructor = perClazz.getConstructor(Integer.class);
        Constructor<?> constructor = perClazz.getConstructor(int.class);
        System.out.println("获取指定的构造方法===>"+constructor);

        Constructor<?> constructor2 = perClazz.getDeclaredConstructor(String.class);
        System.out.println("获取指定的构造方法===>"+constructor2);
        //Person per = new Person() ;


        //根据获取的private构造方法,获取对象实例
        constructor2.setAccessible(true);
        Person per3 = (Person) constructor2.newInstance("zs");
        System.out.println("获取带有String的构造方法" + per3);
        //因为constructor是 有参构造方法(Integer还是int这里构造的就是什么值)
        Person instance2 = (Person) constructor.newInstance(23);
        System.out.println("获取带有Integer的构造方法" +instance2);

        Constructor<?> constructor3 = perClazz.getConstructor();
        //因为constructor3是 无参构造方法,因此不需要传值
        Person instance = (Person) constructor3.newInstance();
        System.out.println("无参构造"+instance);
        System.out.println("===============================动态加载 类名 和方法===============================");
        Properties prop = new Properties();
        prop.load(new FileReader("src/main/resources/class.txt"));
        String classname = prop.getProperty("classname");
        String methodname = prop.getProperty("methodname");
        Class<?> perClazz1 = null;
        try {
            perClazz1 = Class.forName(classname);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        method = perClazz1.getMethod(methodname);
        System.out.println("===>反射读取配置文件并调用");
        method.invoke(perClazz1.newInstance());
        System.out.println("===============================反射可以 越过泛型检查===============================");
        System.out.println("虽然可以通过反射 访问private等访问修饰符不允许访问的属性/方法,也可以忽略掉泛型的约束;" +
                "但实际开发 不建议这样使用,因此可能造成程序的混乱。");
        ArrayList<Integer> list = new ArrayList<>();
        list.add(123);
        list.add(3);
        list.add(2);
//		list.add("zs") ;

        Class<?> listClazz = list.getClass();
         method = listClazz.getMethod("add", Object.class);
        method.invoke(list, "zs...");

        System.out.println("反射可以 越过泛型检查===>"+list);

        System.out.println("===============================使用工具类复制===============================");
        Person person = new Person();
        PropertyUtil.setProperty(person, "name", "长草颜团子");
        PropertyUtil.setProperty(person, "age", 18);
        Student stu = new Student();
        PropertyUtil.setProperty(stu, "score", 98);

        System.out.println(person.toString());
        System.out.println(stu.getScore());
    }
    @Test
    public void test2() throws InstantiationException, IllegalAccessException, NoSuchMethodException,
            NoSuchFieldException, InvocationTargetException, IOException {
        System.out.println("************************反射获取类的实例,并操作************************");
        demo01();
    }


}

 3项目结构示意图

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值