Java 反射

标签: java

目录

 

简介

Class类

反射--获取Class对象的三种方式:

反射--获取指定构造方法创建一个对象

反射--获取属性值,为指定属性赋值

反射--普通方法的调用

反射--static方法调用

反射--破坏泛型检查

关于泛型--请参考博文


简介

1.定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射机制中,一个类的属性,方法,构造方法,以及注释 都有与之对应的类对其进行描述,反射的核心思想就是把原有类的属性、方法、构造方法、注释乃至包命用一个又一个的类去拆解。

 

Class类

  1. final类。
  2. 运行中的类、接口是Class类的实例。
  3. 枚举是一种类、注解是一种接口、数组将被映射成一个Class类对象,具有相同元素类型与维度的数组将共享该对象。
  4. boolean, byte, char, short, int, long, float, and double,void 也是Class的实例对象。
  5. Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

 

反射--获取Class对象的三种方式:

(别说创建Class对象、因为Class类的对象早就在内存中存在了,我们所要做的就是拿到这些对象直接使用)

package com.knowledge.system.java_system.reflection_system.bok_instance;

public class Student {
    private Integer age;
    private String name;
    private String address;
    private boolean sex;

    public Student() {
        System.out.println("公有无参构造函数");
    }

    private  Student(Integer age) {
        this.age = age;
        System.out.println("私有一个参数构造函数");
    }

    protected Student(String name) {
        this.name = name;
        System.out.println("受保护一个参数构造函数");
    }

    public Student(boolean sex) {
        this.sex = sex;
        System.out.println("公有一个参数构造函数");
    }

    public Student(Integer age, String name, String address, boolean sex) {
        this.age = age;
        this.name = name;
        this.address = address;
        this.sex = sex;
    }

    public void testFun1(String msg){
        System.out.println(msg);
    }

    public void testFun2(String msg){
        System.out.println(msg);
    }

    public void testFun3(String msg){
        System.out.println(msg);
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    public static void main(String[] args) {
        System.out.println("main 方法执行了。");
    }

    public static void testMain(String msg){
        System.out.println("static  方法执行了,入参"+msg);
    }
}
package com.knowledge.system.java_system.reflection_system.bok_instance;

import com.alibaba.fastjson.JSON;
import lombok.SneakyThrows;
import org.junit.Test;

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.List;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-03-05 16:59
 **/

public class ReflectionTest {
    @Test
    public void testGetClassObject(){
        Student student=new Student();
        Class clz=student.getClass();//对象角度---不常用,对象都有了还反射干啥
        Class clz2=Student.class;//类角度---业务开发中常用(但要导包,依赖太强,不导包编译会出问题)
        Class clz3=null;//静态方法角度---常用(全路径名可以通过配置文件搞进去)
        try {
            clz3=Class.forName("com.knowledge.system.java_system.reflection_system.bok_instance.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(clz.getName());
        System.out.println(JSON.toJSONString(clz3.getPackage()));
        System.out.println("constructors  "+JSON.toJSONString(clz.getDeclaredConstructors()[0]));
        System.out.println("fields  "+JSON.toJSONString(clz.getDeclaredFields()[0]));
        System.out.println("method  "+JSON.toJSONString(clz.getDeclaredMethods()[0]));
        System.out.println("annotation  "+JSON.toJSONString(clz.getDeclaredAnnotations()[0]));
    }

}

 

反射--获取指定构造方法创建一个对象

  1. Constructor  :可以调用任何构造方法,可强行访问

  2. Class.newInstance:只能够调用   共有  无参构造方法。当无参方法私有时,报错:java.lang.IllegalAccessException

    @Test
    public void testConstructors() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        //通过反射获取指定的构造方法--主要用来创建对象
        Class clz=Student.class;
        Constructor con=clz.getDeclaredConstructor(Integer.class);
        if(!con.isAccessible()){
            con.setAccessible(true);
        }
        Student student= (Student) con.newInstance(23);
        System.out.println("student:"+JSON.toJSONString(student));

        Student student1= (Student) clz.newInstance();
        System.out.println("student1:"+JSON.toJSONString(student1));
    }

 

反射--获取属性值,为指定属性赋值

    @Test
    public void testField() throws NoSuchFieldException, IllegalAccessException {
        //获取指定属性值
        Student student=new Student();
        student.setAge(20);
        Class clz=Student.class;
        Field f=clz.getDeclaredField("age");
        if(!f.isAccessible()){
            f.setAccessible(true);
        }
        Object value=f.get(student);
        System.out.println(value);
        //设置指定属性值
        Field field=clz.getDeclaredField("name");
        if(!field.isAccessible()){
            field.setAccessible(true);
        }
        field.set(student,"afgahgdahgahdhas");
        System.out.println(JSON.toJSONString(student));
    }

 

反射--普通方法的调用

   @Test
    public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class clz=Student.class;
        Student student=new Student();
        Method method=clz.getDeclaredMethod("setName",String.class);
        if(!method.isAccessible()){
            method.setAccessible(true);
        }
        method.invoke(student,"adghashasd;gasdhgasdfgiophpuioh");
        System.out.println(JSON.toJSONString(student, SerializerFeature.WriteMapNullValue));
    }

 

反射--static方法调用

    @Test
    public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class clz=Student.class;
        Student student=new Student();
        Method method=clz.getDeclaredMethod("testMain", String.class);
        if(!method.isAccessible()){
            method.setAccessible(true);
        }
        method.invoke(null,"adghashasd;gasdhgasdfgiophpuioh");
        System.out.println(JSON.toJSONString(student, SerializerFeature.WriteMapNullValue));
    }

    @Test
    public void testMain() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class clz=Student.class;
        Method m1=clz.getDeclaredMethod("main",String[].class);
        m1.invoke(null,(Object)new String[]{"a","a","a"});
    }

 

反射--破坏泛型检查

    @SneakyThrows
    @Test
    public void testTEF(){
        List <String> arrayList=new ArrayList <>();
        arrayList.add("adddd");
        arrayList.add("bbbbbb");
        Class clz=arrayList.getClass();
        Method m=clz.getDeclaredMethod("add",Object.class);
        m.invoke(arrayList,1000);
        System.out.println(JSON.toJSONString(arrayList));
    }

关于泛型--请参考博文

Java 泛型使用

版权声明:本文为cincoutcin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/cincoutcin/article/details/104733810

智能推荐

【Spark 内核】 Spark 内核解析-下

Spark内核泛指Spark的核心运行机制,包括Spark核心组件的运行机制、Spark任务调度机制、Spark内存管理机制、Spark核心功能的运行原理等,熟练掌握Spark内核原理,能够帮助我们更好地完成Spark代码设计,并能够帮助我们准确锁定项目运行过程中出现的问题的症结所在。 Spark Shuffle 解析 Shuffle 的核心要点 ShuffleMapStage与ResultSta...

Reflect反射的基础知识

写个父类: 写个子类: 利用反射获得该子类中的属性,方法,构造,父类及接口: 运行结果:...

spring cloud netflix (07) 服务的消费者(feign)

前言 完整知识点:spring cloud netflix 系列技术栈 Feign (同步通信 HTTP通信) feign是基于接口完成服务与服务之间的通信的 搭建Feign服务 项目结构 项目搭建 pom.xml application类 application.yml 使用feign完成服务与服务之间的通信 feign是基于接口完成服务与服务之间的通信的...

AtCoder Beginner Contest 174 E.Logs

AtCoder Beginner Contest 174 E.Logs 题目链接 到最后才发现是二分,菜菜的我/(ㄒoㄒ)/~~ 我们直接二分 [1,max{a[i]}][1,max\lbrace a[i]\rbrace][1,max{a[i]}] 即可,对每一个 midmidmid,每个数 a[i]a[i]a[i] 只需要切 a[i]−1mid\frac{a[i]-1}{mid}mi...

小程序基础与实战案例

小程序开发工具与基础 小程序开发准备: 申请小程序账号( appid ) 下载并安装微信开发者工具 具体步骤如下: 先进入 微信公众平台 ,下拉页面,把鼠标悬浮在小程序图标上 然后点击 小程序开发文档 照着里面给的步骤,就可以申请到小程序账号了。 然后就可以下载 开发者工具 了 下载完打开后的界面就是这个样子 下面让我们来新建一个小程序开发项目: 在AppID输入自己刚刚注册的AppID就可以,或...

猜你喜欢

VMware centOS7 下通过minikube部署Kubernetes

1、环境准备: VMware CentOS-7-x86_64 CPU:2*2core 内存:8G 宿主机和虚拟机需网络互通,虚拟机外网访问正常 Centos发行版版本查看:cat /etc/centos-release root用户操作 2、禁用swap分区 Kubernetes 1.8开始要求关闭系统的Swap,可暂时关闭或永久禁用, 使用 $ free -m 确认swap是否为开启状态 $ s...

逻辑回归与scikit-learn

欢迎关注本人的微信公众号AI_Engine LogisticRegression 算法原理 一句话概括:逻辑回归假设数据服从伯努利分布,通过极大化似然函数(损失函数)的方法,运用梯度下降或其他优化算法来求解参数,来达到将数据二分类的目的。 定义:逻辑回归(Logistic Regression)是一种用于解决二分类(0 or 1)问题的机器学习方法,用于估计某种事物的可能性(不是概率)。比如某用户...

指针OR数组?用他们来表达字符串又有何不同?

cocowy的编程之旅 在学习C语言的过程中我们经常可以看到或者听到这样一句话:数组其实等价于指针,例如: 在这里可以轻松的看出输出后他们的值相等,其实在计算机内存里面,p为本地变量,有着他自己的作用域。而指针变量q保存着这个数组的首地址,通过*号指向这个地址保存的变量值。 然而我们再看一个例子: 这个时候计算机报错,这是为什么呢? 其实原因很简单,指针说指向的这个字符串的地址是位于计算机代码段地...

广度搜索

广度搜索的基本使用方法 广度搜索不同于深度搜索,是一种一步一步进行的过程,每一个点只记录一遍。需要用到队列记录每一步可以走到的位置,找到目标位置输出步数即可。 用到的知识:结构体、队列 如图 首先我们需要定义一个结构体来存储每个遍历到的点和步数 广搜不会用到递归,所以可以直接在主函数里写,这里需要定义一个结构体队列 初始化队列并将起始点入列 遍历 完整代码...

NIO Socket 编程实现tcp通信入门(二)

1、NIO简介 NIO面向通道和缓冲区进行工作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。可以双向传输数据,是同步非阻塞式IO。NIO还引入了选择器机制,从而实现了一个选择器监听多个底层通道,减少了线程并发数。用NIO实现socket的Tcp通信需要掌握下面三个知识点: Buffer 缓冲区 Channel 通道 Selector 选择器   2、java.nio.Buff...