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 +
                '}';
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值