Java反射机制详解——框架的灵魂所在


反射作为框架的核心,在Java中处于一个极为重要的地位,而且反射在Java中属于比较高级的技术,需要有对Java一定的理解才可以掌握好。反射可以在程序运行过程中修改程序的行为。但是与此同时反射也是极其危险的,需要谨慎使用。

Class

Class不同于创建类的关键字class,Class本质上也是一个类,Class对象用来表示为在虚拟机上运行的类和接口。

Class的获取

在反射当中获取Class的方法有三种

  1. 通过Object.getClass()
  2. 通过类名.class
  3. 通过Class.forName(“类的全限定类名”)

Class的名字

  1. Class.getName()

    1. 当Class代表一个引用时:其返回全限定类名:“com.clander.MyClander”
    2. 当Class代表一个基本数据类型时:其返回它本身。例如:int.class int
    3. 当Class代表是数组时:返回[[[I这样类型的名字,例如:int [] 的名字为[I

    这里写图片描述

String[].getClass().getName() = [L java.lang.String

  1. Class.getSimpleName()

simpleName用于获取内部类的简单类名

当获取类数组的SimpleName时不是在前面加[,而是在后面加[]。

  1. Class.getCanonicalName()
    • getCanonicalName() 返回的也是全限定类名,但是对于内部类不用$,而用.
    • getCanonicalName() 对于数组类型同simpleName一样,也是在后面加[]
    • getCanonicalName() 不同与simpleName的是,不存在的时候返回null,而不是空字符串。
    • 局部类和匿名内部类不存在CanonicalNameClass获取修饰符

获取修饰符

我们可以通过Class.getModifiers();来获取修饰符的值它打印出来是一个数字的形式;我们还可以使用Modifier 类内置的toString() 方法,来将修饰符打印出来。

获取Class的成员

获取Field

  1. Class.getField(String name) 获取的是非私有属性,并且当在当前Class中找不到时会向祖先类获取。
  2. Class.getDeclaredField(String name) 获取的是Class中呗private修饰的属性。
  3. Field[] getDeclaredFields() 获取自身所有的属性但不包含从父类继承下来的属性。
  4. Field[] getFields() 获取自身所有public属性,包括从父类继承下来的。

获取Method

  1. Class.getMethod(String name,Class<?>…parameterTypes) 获取的是非私有方法,并且当在当前Class中找不到时会向祖先类获取。

  2. Class.getDeclaredMethod(String name,Class<?>…parameterTypes) 获取的是Class中呗private修饰的方法。

  3. Method[] getDeclaredMethods() 获取自身所有的方法但不包含从父类继承下来的方法。

  4. Method[] getMethods() 获取自身所有public方法,包括从父类继承下来的。

获取Constructor构造器

与Method和Field基本一致这里不再赘述

Field

Field类型获取
  1. Type getGenericType() 可以返回泛型的类型
  2. Class<?> getType() 返回类型与Class.getName()返回基本相同
获取修饰符

与Class获取修饰符方法一致。

Field的读取和赋值

读取:

  1. Object get(Object o)
  2. byte getByte(Object o)
  3. int getInt(Object o)
  4. long getLong(Object o)
  5. float getFloat(Object o)
  6. double getDouble(Object o)
  7. boolean getBoolean(Object o)
  8. char getChar(Object o)

赋值:

  1. void set(Object o,Object value)
  2. void setByte(Object o,byte value)
  3. void setInt(Object o,int value)
  4. void setLong(Object o,long value)
  5. void setFloat(Object o,float value)
  6. void setDouble(Object o,double value)
  7. void setBoolean(Object o,boolean value)
  8. void setChar(Object o,char value)

Method

获取方法名

**Method.getName()**放回方法名

获取方法参数

Class<?>[] getParameterTypes() 获取所有的参数类型

Type[] getGenericParameterTypes() 获取所有的参数类型包括泛型

获取返回值类型

**Class<?> getReturnType()**获取返回值类型

**Type getGenericReturnType()**获取返回值类型包括泛型

方法的执行(重点!!!)

**public Object invoke(Object obj,Object…args)**invoke方法中的第一个参数表示方法所属类的实例对象,如果这个方法属于静态方法那么这个值为null,后面的可变参数列表为对应参数,返回值为Object。

如果在Method被invoke的过程中本身抛出了异常那么这个异常会被包装在InvocationTargetException中,而通过**InvocationTargetException.getCause()**可以获取真正的异常。在一个private方法被执行之前一定要提前setAccessible(true)

Constructor

Constructor表示为构造方法,主要用于创建类对象。它的方法大体与Method一致,主要重要的方法为创建类对象的方法newInstance()

实验

使用反射解析某个你创建的类,把类中所有的属性、方法、接口都提取出来。要求:通过三种不同的方式获取 Class 对象;
修改解析出来的类的属性值,然后再给类添加新的属性;
调用类方法(包括私有方法、静态方法和构造方法),执行后打印结果;
解析出该类的父类对象,并同样修改其父类的属性值并调用父类的方法。

package T08reflection;

/**
 * @Author: Administrator
 * Date: 2021/12/10 15:41
 * @Version:
 * @Description:
 */
public interface Impl {
    void showMe();

}

package T08reflection;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Administrator
 * Date: 2021/12/10 15:33
 * @Version:
 * @Description:
 */
public class A implements Impl {
    public int a = 10;
    private List<String> list = new ArrayList<>();

    public A() {
    }

    public A(int a) {
        this.a = a;
    }

    private void hello() {
        System.out.println("hello");
    }

    private static void a() {
        System.out.println("A!");
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    @Override
    public void showMe() {
        System.out.println("showMe");
    }
}

package T08reflection;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @Author: Administrator
 * Date: 2021/12/10 15:59
 * @Version:
 * @Description:
 */
public class Exemple {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        A a = new A();
        Class<? extends A> aClass = a.getClass();
        Class<A> aClass1 = A.class;
        Class<?> aClass2 = Class.forName("T08reflection.A");
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field.getName());
            System.out.println(Modifier.toString(field.getModifiers()));
            System.out.println("--------------------");
        }
        Field a1 = aClass1.getField("a");
        int a2 = a1.getInt(a);
        System.out.println(a2);
        a1.set(a, 15);
        a2 = a1.getInt(a);
        System.out.println(a2);
        System.out.println("-----------------------------------");
        Method[] declaredMethods = aClass2.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method.getName());
            System.out.println(Modifier.toString(method.getModifiers()));
            System.out.println("----------------------------");
        }
        Method hello = aClass2.getDeclaredMethod("hello");
        hello.setAccessible(true);
        hello.invoke(a);
        Method a3 = aClass.getDeclaredMethod("a");
        a3.setAccessible(true);
        a3.invoke(null);
        Class<?>[] interfaces = aClass1.getInterfaces();
        for (Class<?> tClass:interfaces){
            System.out.println(tClass.getName());
        }

    }
}

感谢您的阅读,如果本篇文章对您有帮助,欢迎点赞,关注,您的阅读是我莫大的鼓励!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值