java:反射

系列文章目录

文章目录

  • 系列文章目录
  • 前言
  • 什么是反射
  • 获取Class对象
    • 方式一:forName
    • 方式二:类字面常量
    • 方式三:getClass
    • 方式四:LoadClass
  • 使用Class对象
    • 实例化对象
    • 获取域
    • 获取构造器
    • 获取方法
    • 获取注解
    • 获取实现接口
    • 获取父类
    • 获取类加载器
    • 获取泛型类型变量
  • Field类
  • Method类
  • Constructor类
  • Modifier类
  • ClassLoader类
  • AccessibleObject类
  • 动态代理
    • 基于接口的动态代理
      • 使用步骤
      • InvocationHandler
        • invoke
    • 基于子类的动态代理
      • 使用步骤
      • MethodInterceptor
        • invoke

前言

学习之前应该掌握的英文单词:

Constructor 构造器
Field
method 方法
Modifier 修饰符
Parameter 参数

什么是反射

反射应该是java最容易学的东西了,那么什么是反射,其实能够分析类能力的程序称为反射,既然我们将各种事物抽象为类,那么我们也可以将所有的类再抽象一次.当我们java程序编译后每个类都会生成一个.class文件,当用到某个类时就会加载这个类的.class文件,此时类加载器程序就会创建一个Class对象保存在堆中,这个Class对象包含着当前类的所有类型信息。

获取Class对象

我们要想使反射就必须获取Class对象,然后通过Class对象获取类的类型信息,获取Class对象有以下几种方式

方式一:forName

  • static Class forName(Sring classname )
    传入的参数必须是全类名
    使用此方法获取类的Class对象时会初始化类
public class reflect {
     
    public static void main(String[] args) {
     
        try {
     
            System.out.println(Class.forName("com.chinesecooly.thinkingInJava.package8.father"));
        } catch (ClassNotFoundException e) {
     
            e.printStackTrace();
        }
    }
}
class father{
     
    static {
     
        System.out.println("fatherInit");
    }
}

在这里插入图片描述

方式二:类字面常量

这也是java提供的一种可以生成Class引用的方式,而且不需要进行异常处理,当使用类字面常量创建一个类的Class对象时不会初始化该类,推荐使用。使用时只需要在名字后面后加上.class即可.

  • 可以使用类字面量的类型
    外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
    接口
    数组
    枚举
    注解
    基本数据类型
public class reflect {
     
    public static void main(String[] args) {
     
        System.out.println(father.class);
    }
}
class father{
     
    static {
     
        System.out.println("fatherInit");
    }
}

在这里插入图片描述

方式三:getClass

  • public final ClassgetClass()
    Object中的一个方法,如果你拥有了一个类的对象,可以用这个方法来获得该对象类的Class对象
public class reflect {
     
    public static void main(String[] args) {
     
        father father = new father();
        System.out.println(father.getClass());
    }
}
class father{
     
    static {
     
        System.out.println("fatherInit");
    }
}

在这里插入图片描述

方式四:LoadClass

ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(“类的全类名”);

使用Class对象

实例化对象

  • T newInstance()
    创建由此Class对象表示的类的新实例,该方法 默认调用类的无参构造器,如果没有会出现异常

获取域

  • Field getField(String name)
  • Field[] getFields()
    获取类中public修饰的域,包括继承的域
  • Field getDeclaredField(String name)
  • Field[] getDeclaredFields()
    获取仅在当前类声明的所有域
public class reflect {
     
    public static void main(String[] args) {
     
        Class clazz=son.class;
        Field[] fields = clazz.getFields();
        Field[] declaredFields = clazz.getDeclaredFields();
        print(fields);
        print(declaredFields);
    }
   static <T >void print(T[] ts){
     
	   for (T t : ts) {
     
	       System.out.println(t);
	   }
	   System.out.println("------------");
	}
}
class father{
     
    public int a;
    private int b;
}
class son extends father{
     
    public int c;
    private int d;
}

java:反射_第1张图片

获取构造器

  • Constructor[] getConstructors()
  • Constructor< T> getConstructor(Class… parameterTypes)
    获取public构造器
  • Constructor< T> getDeclaredConstructor(Class< ?>… parameterTypes)
  • Constructor[] getDeclaredConstructors()
    获取任意构造器
    java:反射_第2张图片

获取方法

  • Method[] getMethods()
  • Method getMethod(String name, Class… parameterTypes)
    获取public修饰的方法 ,包括继承的方法
  • Method[] getDeclaredMethods()
  • Method getDeclaredMethod(String name, Class… parameterTypes)
    获取任意方法,不包括继承的方法
    java:反射_第3张图片

获取注解

  • Annotation[] getDeclaredAnnotations()
  • Annotation get Annotation(Class< T> annotationClass)
    在这里插入图片描述

获取实现接口

  • public Class[] getInterfaces()
    获取不带泛型信息的实现的接口
  • Type[] getGenericInterfaces()
    获取带有泛型信息的实现的接口

获取父类

  • public Class getSuperclass()
    获取不带泛型信息的父类
  • Type[] getGenericInterfaces()
    获取带有泛型信息的父类

获取类加载器

  • ClassLoader getClassLoader()

获取泛型类型变量

  • TypeVariable<类>[] getTypeParameters()

Field类

  • String getName()
    返回由此域的名称
  • Class getType()
    返回此域的类型
  • Object get(Object obj)
    返回指定对象此域的值
  • void set(Object obj, Object value)
    将指定对象参数此域表示的字段设置为指定的新值

Method类

  • String getName()
    返回该方法的名字
  • Class getReturnType()
    返回此方法的返回类型
  • int getModifiers()
    返回此方法的修饰符
  • int getParameterCount()
    返回此方法的参数个数
  • Class[] getParameterTypes()
    返回此方法的参数类型
  • Object invoke(Object obj, Object… args)
    执行指定对象的此方法
    对于静态方法,第一个参数可以被忽略, 即可以将它设置为 null
  • Class[] getExceptionTypes ( )
    返回一个用于描述方法抛出的异常类型的 Class 对象数组。

Constructor类

  • String getName()
    返回此构造函数的名称
  • int getModifiers()
    返回此构造函数的修饰符
  • int getParameterCount()
    返回此构造函数的参数个数
  • Class[] getParameterTypes()
    返回此构造函数的参数类型
  • T newInstance(Object… initargs)
    指明参数创建实例
  • Class[] getExceptionTypes ( )
    返回一个用于描述方法抛出的异常类型的 Class 对象数组。

Modifier类

  • static String toString(int modifiers )
    返回对应 modifiers 中位设置的修饰符的字符串表
  • static boolean isAbstract(int modifiers )
  • static boolean isFinal (int modifiers )
  • static boolean islnterface(int modifiers )
  • static boolean isNative(int modifiers )
  • static boolean isPrivate(int modifiers )
  • static boolean isProtected(int modifiers )
  • static boolean isPublic(int modifiers )
  • static boolean isStatic(int modifiers )
  • static boolean isStrict(int modifiers )
  • static boolean isSynchronized(int modifiers )
  • static booleani sVolatile(int modifiers )
    这些方法将检测方法名中对应的修饰符在 modffiers 值中的位

ClassLoader类

  • static ClassLoader getSystemClassLoader()
    返回用于委派的系统类加载器
  • InputStream getResourceAsStream(String name)
    返回用于读取指定资源的输入流
  • Class loadClass(String name)
    加载指定类型

AccessibleObject类

此类取消java private权限限制

  • void setAccessible(boolean flag)
    为反射对象设置可访问标志。flag 为 true 表明屏蔽 Java 语言的访问检查,使得对象的私有属性也可以被査询和设置。

动态代理

动态代理的作用是字节码随用随加载,作用是在不修改源码的基础上对现有方法进行加强.

基于接口的动态代理

该方式使用JDK官方提供的Proxy类实现

使用步骤

创建代理对象

  • 使用Proxy类中的newProxyInstance方法
  • 要求:代理类最少实现一个接口否则不能用
  • 参数:
    ClassLoader:用于加载代理类字节码,和被代理对象使用相同的类加载器
    Class[]:用于让代理对象和被代理对象拥有相同的方法
    InvocationHandler:让我们写如何代理,一般都是写一个该接口的实现类,但不是必须的

InvocationHandler

invoke

  • 执行被代理对象任何方法时都会经过此方法
  • 参数:
    proxy:代理对象的引用
    method:当前执行的方法
    args:当前执行方法所需的参数
    返回值:和被代理对象方法有相同的返回值
package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class clint {
     
    public static void main(String[] args) {
     
        produser produser=new producer();
        produser produserProxy = (proxy.produser) Proxy.newProxyInstance(produser.getClass().getClassLoader(), produser.getClass().getInterfaces(), new handler(produser));
        produserProxy.saleProduct(10000f);
    }
}
class handler implements InvocationHandler{
     
    private produser produser;

    public handler(proxy.produser produser) {
     
        this.produser = produser;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     
        Float money=(Float)args[0];
        Object returnVaule=null;
        if ("saleProduct".equals(method.getName())){
     
            returnVaule= method.invoke(produser,money*0.8f);
        }
        return returnVaule;
    }
}

基于子类的动态代理

该方式使用第三方提供的Enhancer类实现

使用步骤

创建代理对象

  • 使用nhancer类中的creat方法
  • 要求:被代理类不能是最终类
  • 参数:
    Class:用于指定被代理对象的字节码
    Callback:增强被代理类,一般写的都是子接口MethodInterceptor的实现类,

MethodInterceptor

invoke

  • 执行被代理对象任何方法时都会经过此方法
  • 参数:
    proxy:代理对象的引用
    method:当前执行的方法
    args:当前执行方法所需的参数
    返回值:和被代理对象方法有相同的返回值
package cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import proxy.producer;
import proxy.produser;

import java.lang.reflect.Method;

public class clint {
     
    public static void main(String[] args) {
     
        produser produser=new producer();
        produser por = (produser) Enhancer.create(produser.getClass(),new handler(produser) );
        por.saleProduct(12000f);
    }
}
class handler implements MethodInterceptor{
     
    private produser produser;

    public handler(proxy.produser produser) {
     
        this.produser = produser;
    }
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
     
        Float money=(Float)objects[0];
        Object returnVaule=null;
        if ("saleProduct".equals(method.getName())){
     
            returnVaule= method.invoke(produser,money*0.8f);
        }
        return returnVaule;
    }
}

你可能感兴趣的:(java,java,反射,编程语言,jvm,类)