个人博客网:https://wushaopei.github.io/    (你想要这里多有)

1、反射(JAVA Reflection)的理解

1.1 什么是反射(JAVA Reflection)

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

1.2 Java 反射机制提供的功能

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的成员变量和方法
  • 生成动态代理

1.3 反射相关的主要API:

  • java.lang.Class:代表一个类
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造方法

2、Class 的理解

2.1 Class 类的 原理

在Object类中定义了以下的方法,此方法将被所有子类继承:
●  public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

反射获取class区别于以往正常的new 创建对象来对类内部方法、属性进行操作。

2.2 Class类的存在与定义

  • 对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
  • Class本身也是一个类
  • Class 对象只能由系统建立对象
  • 一个类在 JVM 中只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件
  • 每个类的实例都会记得自己是由哪个 Class 实例所生成
  • 通过Class可以完整地得到一个类中的完整结构

3、 Class 的获取

3.1 Class 类的常用方法

3.2 应用案例

3.3 实例化Class类对象(四种方法)

4、 ClassLoader (理解)

ClassLoader :类加载机制加载流程

案例:

5、 创建运行时类的对象

5.1 有了Class对象,能做什么?

   答案: 可以用来创建类的对象

5.2 要  求:

1)类必须有一个无参数的构造器。
    2)类的构造器的访问权限需要足够。

5.3 难道没有无参的构造器就不能创建对象了吗?

不是!只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作。

步骤如下:
1)通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器
2)向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。

3)在Constructor 类中存在一个方法: public T newInstance(Object... initargs)

5.4 案例

6、获取运行时类的完整结构

通过Class类获取到类的对象后,有什么用呢?

答案可以通过类的对象来获取类的完整结构,并进行赋值或更新数据

6.1 通过反射获取运行时类的完整结构

Field、Method、Constructor、Superclass、Interface、Annotation

  • 实现的全部接口
  • 所继承的父类
  • 全部的构造器
  • 全部的方法
  • 全部的Field

6.2 获取完整结构的实现方式:

(1)实现的全部接口

    public Class<?>[] getInterfaces()   

确定此对象所表示的类或接口实现的接口。

(2)所继承的父类

        public Class<? Super T> getSuperclass()

返回表示此 Class 所表示的实体(类、接口、基本类型)的父类的 Class。

(3)全部的构造器

        public Constructor<T>[] getConstructors()

返回此 Class 对象所表示的类的所有public构造方法。

        public Constructor<T>[] getDeclaredConstructors()

返回此 Class 对象表示的类声明的所有构造方法。

  • Constructor类中:

取得修饰符: public int getModifiers();
          取得方法名称: public String getName();
          取得参数的类型:public Class<?>[] getParameterTypes();

(4)全部的方法

        public Method[] getDeclaredMethods()

返回此Class对象所表示的类或接口的全部方法

        public Method[] getMethods()  

返回此Class对象所表示的类或接口的public的方法

  • Method类中:

public Class<?> getReturnType()取得全部的返回值
        public Class<?>[] getParameterTypes()取得全部的参数
        public int getModifiers()取得修饰符
        public Class<?>[] getExceptionTypes()取得异常信息

(5)全部的Field

        public Field[] getFields()

返回此Class对象所表示的类或接口的public的Field。

        public Field[] getDeclaredFields()

返回此Class对象所表示的类或接口的全部Field。

  • Field方法中:

public int getModifiers()  以整数形式返回此Field的修饰符
          public Class<?> getType()  得到Field的属性类型
          public String getName()  返回Field的名称。

(6)Annotation相关

  • get Annotation(Class<T> annotationClass)
  • getDeclaredAnnotations()

(7)泛型相关
        获取父类泛型类型:Type getGenericSuperclass()
        泛型类型:ParameterizedType
        获取实际的泛型类型参数数组:getActualTypeArguments()

(8)类所在的包    Package getPackage()

6.2 调用运行时类的指定属性、指定方法等

(1)调用指定方法

通过反射,调用类中的方法,通过Method类完成。步骤:

  1. 通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
  2. 之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。

Object invoke(Object obj, Object …  args)

说明:
    1.Object 对应原方法的返回值,若原方法无返回值,此时返回null
    2.若原方法若为静态方法,此时形参Object obj可为null
    3.若原方法形参列表为空,则Object[] args为null
    4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。

(2)调用指定属性

在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。

  • public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。
  • public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。

在Field中:

  • public Object get(Object obj) 取得指定对象obj上此Field的属性内容
  • public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容

:在类中属性都设置为private的前提下,在使用set()和get()方法时,首先要使用Field类中的setAccessible(true)方法将需要操作的属性设置为可以被外部访问。

  • public void setAccessible(true)访问私有属性时,让这个属性可见。

6.3 案例:反射的应用

/*
* 获取类中属性的详细信息
*/
@Test
public void test() throws Exception, Exception{ Class<Student> clazz = Student.class;
//获取本类中所的属性
Field[] declaredFields = clazz.getDeclaredFields(); for (Field field : declaredFields) {
//获取注解
Annotation[] annotations = field.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//权限修饰符
int modifiers = field.getModifiers();
System.out.print(Modifier.toString(modifiers) + " "); //属性的类型
Class<?> type = field.getType();
System.out.print(type + " "); //获取属性的名字
String fieldName = field.getName();
System.out.print(fieldName); System.out.println();
}
}

                /*
* 需求 : 给对象中的私有属性进行赋值
*/
//getDeclaredField("age") : 可以获取任何权限修饰符修饰的属性
Field declaredField = clazz.getDeclaredField("age");
//setAccessible(true) : 获取访问权限
declaredField.setAccessible(true);
//给属性进行赋值
//第一个参数 : 给哪个对象中的该属性进行赋值
//第二个参数 : 赋值的内容
declaredField.set(student, 123);
System.out.println(student.getAge()); //获取方法 - public修饰且有参
/*
* 第一个参数 : 方法名
* 第二个参数 :形参的类型(因为是可变形参也可不写)
*/
Method declaredMethod = clazz.getDeclaredMethod("info", String.class);
//获取访问权限
declaredMethod.setAccessible(true);
//调用参的方法
/*
* 第一个参数 : 通过哪个对象去调用该方法
* 第二个参数 : 实参
*/
declaredMethod.invoke(student, "ccc"); @Test
public void test5(){
Class clazz = Student.class;
//获取带泛型的父类
Type genericSuperclass = clazz.getGenericSuperclass();
//将父接口转成子接口
ParameterizedType t = (ParameterizedType) genericSuperclass;
//获取该类的所的泛型
Type[] actualTypeArguments = t.getActualTypeArguments();
//遍历数组
for (Type type : actualTypeArguments) {
System.out.println(type);
}
}

7、 动态代理

代理机制的操作,属于静态代理,特征是代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。

7.1 动态代理的概述

     动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。

7.2 动态代理使用场合:

  • 调试
  • 远程方法调用

7.3 代理设计模式的原理:
     使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上.

7.4 代理类介绍-Proxy

Proxy :专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态地生成实现类。

提供用于创建动态代理类和动态代理对象的静态方法

7.5 案例

(1)创建一个实现接口InvocationHandler的类,它必须实现invoke方法,以完成代理的具体操作。

*
* 用来创建代理对象的
*/
public class XiaoMi implements InvocationHandler {
// 被代理对象
private Object tartetObject;
public XiaoMi() {
}
/*
* 获取代理对象 targetObject : 被代理对象 (根据被代理对象创建代理对象)
*/
public Object getXiaoMi(Object targetObject){
this.tartetObject = targetObject;
//创建代理对象
/*
* ClassLoader : 类加载器 (被代理对象的类加载器是什么就传什么)
* Class<?>[] interfaces : 被代理对象的所的接口(通过接口代理对象才能知道需要代理的方法)
* InvocationHandler : 是一个接口,传一个实现了该接口的实现类的对象
*/ Object object = Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this
);
return object;
} /*
* 用来完成代理的具体操作
* 作用 : 用来调用被代理对象中的方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---------代理开始了----------"); /*
* proxy : com.sun.proxy.$Proxy4
* 调用方法 : 第一个参数是调用哪个对象的方法,第二个参数是调用方法传递的实参
*/
Object obj = method.invoke(tartetObject, args);
System.out.println("---------代理结束了----------");
return obj;
}
}

JAVASE(十八) 反射: Class的获取、ClassLoader、反射的应用、动态代理的更多相关文章

  1. 十八、泛型 l 注解 l Servlet3.0 l 动态代理 l 类加载器基础加强

    l 泛型 l 注解 l Servlet3.0 l 动态代理 l 类加载器 泛型 1 回顾泛型类 泛型类:具有一个或多个泛型变量的类被称之为泛型类. public class A<T> { ...

  2. WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]

    原文:WCF技术剖析之二十八:自己动手获取元数据[附源代码下载] 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-ME ...

  3. Java反射机制剖析(四)-深度剖析动态代理原理及总结

    动态代理类原理(示例代码参见java反射机制剖析(三)) a)  理解上面的动态代理示例流程 a)  理解上面的动态代理示例流程 b)  代理接口实现类源代码剖析 咱们一起来剖析一下代理实现类($Pr ...

  4. Java反射机制剖析(三)-简单谈谈动态代理

    通过Java反射机制剖析(一)和Java反射机制剖析(二)的学习,已经对反射有了一定的了解,这一篇通过动态代理的例子来进一步学习反射机制. 1.     代理模式 代理模式就是为其他对象提供一种代理来 ...

  5. java 编程基础 Class对象 反射:动态代理 和AOP:java.lang.reflect.Proxy:(Proxy.newProxyInstance(newProxyInstance​(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h))

    为什么我们使用动态代理 静态代理会让类变多了,多了代理类,工作量变大了,且不易扩展.比如我们上节课的例子,要实现不同的扩展方法就要编写不同的代理类,非常麻烦.   Proxy类的使用规则 Proxy提 ...

  6. Java的反射机制和动态代理

    介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大的功能,可以原 ...

  7. 杨晓峰-Java核心技术-6 动态代理 反射 MD

    目录 第6讲 | 动态代理是基于什么原理? 典型回答 考点分析 知识扩展 反射机制及其演进 动态代理 精选留言 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAnd ...

  8. 反射、静态代理、动态代理(jdk、cglib)

    一.反射 反射在之前的文章中详细的解释过了,简单概括就是:可以动态的获取到一个类内部的所有的信息,动态的去创建对象和使用对象以及可以操作对象的属性和方法. 二.代理 首先解释一下代理:使用一个代理对象 ...

  9. sonar-scanner的执行流程和对ClassLoader,动态代理的使用

    最近项目上使用了sonarqube来提供静态代码检查的服务,在看sonar-scanner的源码的时候,发现sonar-scanner用来分析的jar包是从sonar的服务器上下载下来的,使用自定义的 ...

随机推荐

  1. Polar码快速入门

    Polar码快速入门 本科生在学习极化码时,并不是件简单的事情.网上极化码的资料很少,而且基本上都是较难的论文.这篇文章是用来帮你快速入门极化码. Poalr码背景 2015 年,国际电信联盟无线通信 ...

  2. Linux dts 设备树详解(二) 动手编写设备树dts

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 前言 硬件结构 设备树dts文件 前言 在简单了解概念之后,我们可以开始尝试写一个 ...

  3. Spring IOC使用详解

    SpringIOC使用详解 一.IOC简介 IOC(Inversion of Control):控制反转,即对象创建的问题.通俗地讲就是把创建对象的代码交给了Spring的配置文件来进行的.这样做的优 ...

  4. 使用IR2104S搭建的H桥-机器人队比赛经典版(原作者答疑)

    原理图地址:http://bbs.ednchina.com/BLOG_ARTICLE_3020313.HTM?click_from=8800020962,4950449047,2014-05-01,E ...

  5. vue-multi-module【多模块集成的vue项目,多项目共用一份配置,可以互相依赖,也可以独立打包部署】

    基于 vue-cli 2 实现,vue 多模块.vue多项目集成工程 Github项目地址 : https://github.com/BothEyes1993/vue-multi-module 目标: ...

  6. Python内置函数列表

    函数 用途 abs() 返回数字绝对值 all() 判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False any() 判断给定的可迭代参数 ...

  7. like模糊查询是否走索引

    1.模糊查询 后通配 走索引 前通配 走全表 2.where条件用in或or 不会走索引索引的本质是平衡b+数,是为了方便查询的平衡多路查找树 B-Tree相比,B+Tree有以下不同点: 每个节点的 ...

  8. 【转载】文件上传那些事儿,文件ajax无刷上传

    导语 正好新人导师让我看看能否把产品目前使用的FileUploader从老的组件库分离出来的,自己也查阅了相关的各种资料,对文件上传的这些事有了更进一步的了解.把这些知识点总结一下,供自己日后回顾,也 ...

  9. java ->动态页面技术(JSP)

    动态页面技术(JSP/EL/JSTL) JSP技术 jsp脚本和注释 jsp脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 2)<%= ...

  10. 一文读懂Java注解

    什么是注解 Java官方文档上说,注解是元数据的一种形式,它提供不属于程序一部分的数据,注解对被注解的代码没有直接的影响. 准确上说,注解只不过是一种特殊的注释而已,如果没有解析它的代码,它可能连注释 ...