Java反射的理解

news/2024/5/19 4:01:06 标签: Java反射, java, java基础, 反射

反射的概述

反射在程序运行过程中对类进行操作的一种机制
反射被大量应用在Spring,Hibernate等框架中,在IDEA中也有应用,比如,在我们调用一个对象的方法或者非私有成员变量的时候,智能补全也是反射的应用
强调一次,反射就是在程序运行过程中,对类进行操作(创建实例,调用方法,获得字段等等操作)的一种机制
在没有接触到反射之前我们也可以对类进行操作(创建实例,调用方法,获得字段等等操作),那么为什么会出现反射这种机制呢?
之前我们是直接对类进行操作,但是操作的时机是在运行之前,而反射操作的时机是程序运行过程中
附上一张创建对象的过程
在这里插入图片描述


## 反射的使用 既然反射是操作类的,在这里需要引入一个类,**Class类,也被称为字节码对象,亦乘坐类类型的类**在反射这种机制下,几乎所有的操作最开始都是通过Class来获得的,所以我们先看一下字节码对象包含什么,是如何获得的.
### 字节码对象的获取 有三种方法可以获取字节码对象 #### 对象名.class ``` Class classObject = Test.class; ``` **缺点:** 无法实现代码的解耦 常用于传递参数 `classObject.getMethod("test",String.class)` #### Class.forName("类的全限定名") ``` Class.forName("com.Study.Test"); ``` **注意**:此方法会抛出ClassNotFoundException 非常常用,可以实现代码解耦 比如在加载数据库驱动的时候就会用到

对象.getClass();

Test t = new Test();
Class<Test> classObject = t.getClass();

**缺点:**需要先获得对象


字节码对象主要包含什么

  • 获取对象信息的方法
  • 获取Constructor对象的方法
  • 获取Field对象的方法
  • 获取Method对象的方法
    在这里插入图片描述

接下来我们通过实际的代码来演示一下反射

平时我们怎么操作类现在我们就按照平时的习惯来操作
在这之前我创建了一个Person类用来演示,这个类会放在文章末尾

Q1.使用反射来创建一个对象(两种方法)
       //使用反射必须先获取字节码对象,有异常抛出即可
        Class<?> p = Class.forName("com.water.reflect.Person");
        //第一种方法,直接通过字节码对象来创建对象
        Person o = (Person)(p.newInstance());//注意这里的返回值是Object类型需要强转
        //第二种方法,通过字节码对象获得构造器,再用构造器创建对象,这里有异常,需要处理
        Constructor<?> constructor = p.getConstructor(String.class, String.class, int.class);
        Person o1 = (Person)(constructor.newInstance("张三","男",24));
        //输出结果
        System.out.println(o1);
        System.out.println(o);

打印结果

Student{name=‘张三’, gender=‘男’, age=24}
Student{name=‘null’, gender=‘null’, age=0}

Q2.获取类名,获取完整类名
        //获取字节码对象
        Class<?> p = Class.forName("com.water.reflect.Person");
        //获取完整类名
        String fullName = p.getName();
        //获取类名
        String name = p.getSimpleName();
        //输出结果
        System.out.println(fullName);
        System.out.println(name);

打印结果

com.water.reflect.Person
Person

Q3.Constructor对象的使用
//获取字节码对象
        Class<?> p = Class.forName("com.water.reflect.Person");

        // Constructor getConstructor(Class... parameterTypes)
        // 根据参数类型获取构造方法对象,只能获得public修饰的构造方法。
        Constructor<?> c1 = p.getConstructor();//获取无参构造
        Constructor<?> c2 = p.getConstructor(String.class,String.class,int.class);//获取有参构造

        //Constructor getDeclaredConstructor(Class... parameterTypes)
        //根据参数类型获取构造方法对象,包括private修饰的构造方法。
        Constructor<?> c3 = p.getDeclaredConstructor();//获取无参私有构造
        Constructor<?> c4 = p.getDeclaredConstructor(String.class,String.class,int.class);//获取有参私有构造

        //Constructor[] getConstructors()
        //获取所有的public修饰的构造方法
        Constructor<?>[] c5 = p.getConstructors();//获取所有public修饰的构造方法

        //Constructor[] getDeclaredConstructors()
        //获取所有构造方法,包括privat修饰的
        Constructor<?>[] c6 = p.getDeclaredConstructors();//获取所有的构造方法,包括private修饰的
Q4.Constructor对象的常用方法
// T newInstance(Object... initargs)
        //根据指定参数创建对象
        Person p1 = (Person) (c1.newInstance());

        //void setAccessible(true)
        //暴力反射,设置为可以直接访问私有类型的构造方法。配合Constructor[] getDeclaredConstructors()
        //Constructor getDeclaredConstructor(Class... parameterTypes)
        Constructor<?> c7 = p.getDeclaredConstructor(String.class,String.class,int.class);
        c7.setAccessible(true);
        Person o = (Person)(c7.newInstance());
Q5.Field对象的获取和使用.

Field对象的获取

1. Field getDeclaredField(String name) 
   根据属性名获得属性对象,包括private修饰的
 
2. Field getField(String name) 
   根据属性名获得属性对象,只能获取public修饰的
   
3. Field[]	getFields() 
    获取所有的public修饰的属性对象,返回数组。
    
4. Field[]	getDeclaredFields() 
  	获取所有的属性对象,包括private修饰的,返回数组。

Field的常用方法

void  set(Object obj, Object value) 
void setInt(Object obj, int i) 	
void setLong(Object obj, long l)
void setBoolean(Object obj, boolean z) 
void setDouble(Object obj, double d) 

Object get(Object obj)  
int	getInt(Object obj) 
long getLong(Object obj) 
boolean getBoolean(Object ob)
double getDouble(Object obj) 

void setAccessible(true);暴力反射,设置为可以直接访问私有类型的属性。
Class getType(); 获取属性的类型,返回Class对象。
  • setXxx方法都是给对象obj的属性设置使用,针对不同的类型选取不同的方法。
  • getXxx方法是获取对象obj对应的属性值的,针对不同的类型选取不同的方法。
Q6.Method对象的获取和常用方法

Method对象的获取

1. Method getMethod("方法名", 方法的参数类型... 类型) 
	根据方法名和参数类型获得一个方法对象,只能是获取public修饰的
	
2. Method getDeclaredMethod("方法名", 方法的参数类型... 类型)
  	根据方法名和参数类型获得一个方法对象,包括private修饰的
  	
3. Method[] getMethods()
  	获取所有的public修饰的成员方法,包括父类中。

4. Method[] getDeclaredMethods()
  	获取当前类中所有的方法,包含私有的,不包括父类中。

Method对象的常用方法

1.  Object invoke(Object obj, Object... args) 
  	根据参数args调用对象obj的该成员方法	
  	如果obj=null,则表示该方法是静态方法
  
2.  void setAccessible(boolean flag) 
  	暴力反射,设置为可以直接调用私有修饰的成员方法
package com.water.reflect;

/**
 * @Author: Purified
 * @Date: 2018/12/23 19:57
 * @Version 1.0
 */
public class Person {
    private String name;
    public String gender;
    private int age;

    public Person() {
    }

    public Person(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public void sleep(){
        System.out.println("睡觉");
    }
    public void sleep(int hour){
        System.out.println("public修饰---sleep---睡" + hour + "小时");
    }
    private void eat(){
        System.out.println("private修饰---eat方法---吃饭");
    }
    
    public static void study(){
        System.out.println("静态方法---study方法---好好学习Java");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                '}';
    }
}

http://www.niftyadmin.cn/n/677088.html

相关文章

mysql数据操作语句

声明&#xff1a;本栏目所使用的素材都是凯哥学堂VIP学员所写&#xff0c;学员有权匿名&#xff0c;对文章有最终解释权&#xff1b;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 mysql数据操作语句 在我操作数据库里的数据时我们有三种数据操作语句&#xff0c;分别是…

vue 跳转携带的参数如何获取_vue从一个页面跳转到另一个页面并携带参数的解决方法...

1.需求&#xff1a;点击商场跳转到商业体列表解决方案&#xff1a;元页面&#xff1a;a标签中添加跳转函数商场toMallInfo: function(mallCode){this.$router.push({path: /propertyInfo/mall/mallList,// name: mallList,query: {mallCode: M000989}})},将将跳转的url添加到 $…

JavaEE——JSP标签

声明&#xff1a;本栏目所使用的素材都是凯哥学堂VIP学员所写&#xff0c;学员有权匿名&#xff0c;对文章有最终解释权&#xff1b;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 JSP标签 JSTL:java自己开发出来的一套标记库&#xff0c;给你在JSP页面中使用的&#x…

OGG-00146 OGG抽取进程状态:ABENDED

问题描述&#xff1a; 启动源端ogg进程&#xff08;start *&#xff09;&#xff0c;检查进程状态&#xff08;info all&#xff09;&#xff0c;发现ext001状态为&#xff1a;ABENDED 检查进程日志:view report ext001&#xff0c;提示如下错误&#xff1a; 问题分析&#…

pythonflaskmock数据_【Python】学习笔记5-利用flask来mock接口

# 1、mock接口目的&#xff1a;mock|muk|接口&#xff0c;就是模拟接口1、暂时代替第三方接口测试&#xff0c;自己模拟一个接口2、辅助测试&#xff0c;用来代替没有开发好的接口3、查看数据# import flask #python的轻量级的开发框架# # 接口&#xff0c;后台服务的开发# # 在…

SQL——MySQL高级查询2

声明&#xff1a;本栏目所使用的素材都是凯哥学堂VIP学员所写&#xff0c;学员有权匿名&#xff0c;对文章有最终解释权&#xff1b;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 mysql高级查询2 select高级查询还有以下几个语法&#xff0c;模糊查询like&#xff0c;…

在Idea中集成Tomcat

确保您已经下载好了tomcat和Idea打开Idea新建一个java空项目run>edit Configuration左上角会有一个加号点击>Tomcat Server(如果没有,寻找 xx items more字样,点击)点击local,接下来请看图 看到最后一张图红框里出现Tomcat标志则成功.

JavaEE——Java导出Excel表

声明&#xff1a;本栏目所使用的素材都是凯哥学堂VIP学员所写&#xff0c;学员有权匿名&#xff0c;对文章有最终解释权&#xff1b;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 Java导出Excel表 首先去maven里面下载 upload 1.3.3 版本 下载到你的maven工程里面 上传文…