Java基础之反射、注解、代理
反射
笔者对反射的理解就是解剖class文件,来进行一系列操作。
Class类
获取Class类实例的三种方式:
- 类名.class
- 对象.getClass()
static Class forName(String className)根据类的名称获取类的Class对象(这里的className必须是类的全名)
一般使用第三种方式获取Class对象。
常用成员方法:
Field getField(String name)获取类中的成员变量的对象String getName()获取类的全名:包名.类名String getSimpleName()获取类的简称:类名String getPackageName()获取包名Field getField(String name)获取公共成员变量对象Method getMethod(String name, Class<?>... parameterTypes)获取类中的公共成员函数的对象Constructor<T> getConstructor(Class<?>... parameterTypes)获取类中的公共构造函数的对象newInstance()获取该类的实例(JDK 9已过期,使用clazz.getDeclaredConstructor().newInstance() 实例化)
静态:
forName(String className)加载类
其中成员变量、成员函数、构造函数要素过多,使用了独立的类来描述:
| 类 | 描述 |
|---|---|
| Field | 成员变量 |
| Method | 成员方法 |
| Constructor | 构造方法 |
预定义对象:八中基本类型以及void,其class对象就是其本身
Constructor、Method、Field
Constructor
newInstance(Object... initargs)获取实例setAccessible(boolean)是否可以暴力访问,即越过私有权限的检验
setAccessible(boolean)是其父类的方法,Field、Method、Constructor都可以设置暴力访问私有方法/变量。
Method
Object invoke(Object obj, Object... args)调用方法,返回值为该方法的返回值(void方法返回null),第一个参数为调用的对象,第二个参数为方法的参数
类加载器
常见的类加载器有三种,每个类加载器负责加载不同位置的类:
| 加载器 | 说明 |
|---|---|
| Bootstrap 根类加载器 | Bootstrap是最顶级的类加载器。它加载类文件不是我们自己书写的,负责Java核心类的,比如System,String等。只有所有类加载到内存中,我们才可以使用。(Bootstrap自动加载) |
| ExtClassLoader 扩展类加载器 | ExtClassLoader 扩展类加载器,加载的是扩展类的,我们是用不到的,都是jdk内部自己使用的。(ExtClassLoader类被BootStrap加载) |
| AppClassLoader 系统/应用类加载器 | AppClassLoader 系统/应用类加载器,是用来加载ClassPath 指定的所有jar或目录,ClassPath表示存放类路径的,我们如果不配置ClassPath,那么就表示当前文件夹,在idea环境下的ClassPath是out目录。在out目录存放的都是我们书写好的class文件,也就是说 AppClassLoader 类加载器是用来加载我们书写的out目录下的class文件。(AppClassLoader类被ExtClassLoader加载) |
默认相对目录(文件路径)为相对项目目录,加载器相对目录为src
注解
JDK 常用注解:
| 注解 | 用途 |
|---|---|
@Override |
重写 |
@SuppressWarnings() |
抑制警告 |
@FunctionalInterface |
函数式接口 |
@SuppressWarnings()参数关键字列表:
| 参数 | 描述 |
|---|---|
| all | to suppress all warnings (抑制所有警告) |
| boxing | to suppress warnings relative to boxing/unboxing operations(抑制装箱、拆箱操作时候的警告) |
| cast | to suppress warnings relative to cast operations (抑制映射相关的警告) |
| dep-ann | to suppress warnings relative to deprecated annotation(抑制启用注释的警告) |
| deprecation | to suppress warnings relative to deprecation(抑制过期方法警告) |
| fallthrough | to suppress warnings relative to missing breaks in switch statements(抑制确在switch中缺失breaks的警告) |
| finally | to suppress warnings relative to finally block that don’t return (抑制finally模块没有返回的警告) |
| hiding | to suppress warnings relative to locals that hide variable() |
| incomplete-switch | to suppress warnings relative to missing entries in a switch statement (enum case)(忽略没有完整的switch语句) |
| nls | to suppress warnings relative to non-nls string literals(忽略非nls格式的字符) |
| null | to suppress warnings relative to null analysis(忽略对null的操作) |
| rawtypes | to suppress warnings relative to un-specific types when using generics on class params(使用generics时忽略没有指定相应的类型) |
| restriction | to suppress warnings relative to usage of discouraged or forbidden references |
| serial | to suppress warnings relative to missing serialVersionUID field for a serializable class(忽略在serializable类中没有声明serialVersionUID变量) |
| static-access | to suppress warnings relative to incorrect static access(抑制不正确的静态访问方式警告) |
| synthetic-access | to suppress warnings relative to unoptimized access from inner classes(抑制子类没有按最优方法访问内部类的警告) |
| unchecked | to suppress warnings relative to unchecked operations(抑制没有进行类型检查操作的警告) |
| unqualified-field-access | to suppress warnings relative to field access unqualified (抑制没有权限访问的域的警告) |
| unused | to suppress warnings relative to unused code (抑制没被使用过的代码的警告) |
自定义注解
声明注解
自定义注解使用@interface声明
其内可以有属性:public abstract 属性类型 属性名() default 属性的默认值;
注解中public abstract可以省略,并且属性类型只能是是:基本类型、String、Class、注解,以及以上类型的一维数组,属性可以没有默认值。
使用注解
注解可以没有属性,如果有属性需要在括号内赋值,有默认值可以不赋值。
相同注解在同一方法只能使用一次。
解析自定义注解
元注解
元注解是用来标记注解的注解。
一共有四种:
@Target用于确定被修饰的注解使用的位置(主要)@Retention用于确定被修饰的自定义注解生命周期(主要)@Documented将此注解包含在Javadoc中@Inherited允许子类继承父类中的注解
@Target:表示该注解可以用于什么地方。可能的ElementType参数包括:CONSTRUCTOR:构造器的生命FIELD:域声明(包括enum实例)LOCAL_VARIABLE:局部变量声明METHOD:方法声明PACKAGE:包声明PARAMETER:参数声明TYPE:类、接口(包括注解类型)和enum声明ANNOTATION_TYPE:注解声明(与TYPE的区别?专门用在注解上的TYPE)TYPE_PARAMETER:Java8TYPE_USE:Java8
@Retention:
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:SOURCE:注解将在编译器丢弃CLASS:注解在class文件中可用,但会被VM丢弃RUNTIME:VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息
可以通过反射拿到方法,然后拿到注解,通过拿到的注解便可以拿到注解中的值。
代理
静态代理
代理:代理对象主要用来拦截目标业务对象的访问
- 代理对象要持有真实业务对象。(在代理类中创建被代理类的对象。)
- 代理对象要和真实业务对象,具备相同的行为方法。实现同一个接口。
- 代理对象拦截对真实对象的访问,可以修改访问的参数、返回值,甚至拦截访问。
静态代理使用较少。
动态代理
动态代理:就是在程序运行的过程中,动态的生成一个类,这个类要代理目标业务对象,并且可以动态生成这个代理类的对象。
在Java中当某个类需要被代理的时候,要求这个类中的被代理的方法必须抽取到一个接口中,然后这个类需要实现那个接口,只有在这个接口中的方法,代理类才能代理它。
Proxy类
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h):
获得代理类实例,参数:
ClassLoader loader类加载器,一般给被代理对象的类加载器即可
Class<?>[] interfaces被代理对象的所有的接口数组
InvocationHandler h调用处理器,是一个接口。
InvocationHandler接口有一个静态方法:public Object invoke(Object proxy, Method method, Object[] args)
第一个参数是代理本身,第二个参数是调用的方法,第三个参数是调用方法的参数(在方法中this是这个接口的实现类,proxy才是代理本身,通过返回代理本身可以实现链式调用,参考这里)
上个栗子:
@Test
public void proxyTest() throws Exception {
//获取自定义类的Class对象
Class clazz = Class.forName("org.junit.sh.n1.Person");
//获取该类的类加载器
ClassLoader loader = clazz.getClassLoader();
//获取接口数组
Class[] interfaces = clazz.getInterfaces();
// @SuppressWarnings("all")//clazz.newInstance()方法在JDK9中过期了,懒得改了,注解一下
//实例化一个对象作为调用者
Person p = (Person) clazz.newInstance();
//使用Lambda实现InvocationHandler
InvocationHandler h = (proxy, method, args) -> {
if ("show".equals(method.getName())) {
System.out.println("修改方法");
return method.invoke(p, args);
}
return null;
};
//自定义类实现的接口
Showable theProxy = (Showable) Proxy.newProxyInstance(loader, interfaces, h);
//调用方法
theProxy.show();
}
真正理解反射和注解还是得结合框架(。・∀・)ノ
Java基础之反射、注解、代理的更多相关文章
- Java基础笔记 – Annotation注解的介绍和使用 自定义注解
Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 | 被围观 25,969 views+ 1.Anno ...
- 黑马程序员:Java基础总结----反射
黑马程序员:Java基础总结 反射 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 反射 反射的基石:Class类 Class类代表Java类,它的各个实例对象又分别 ...
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
- 【Java基础】反射和注解
前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...
- 学习Spring必学的Java基础知识(2)----动态代理
Spring AOP使用动态代理技术在运行期织入增强的代码,为了揭示Spring AOP底层的工作机理,有必要对涉及到的Java知识进行学习.Spring AOP使用了两种代理机制:一种是基于JDK的 ...
- Java基础之一反射
反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一.反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够 ...
- Java基础之—反射
反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一.反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够 ...
- java基础篇---反射机制
一.JAVA是动态语言吗? 一般而言,说到动态言,都是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,JAVA和C++一样,都不是动态语言. 但JAVA它却有着一个非常突出的动态相关机制:反 ...
- Java基础教程(16)--注解
一.注解基础知识 1.注解的格式 最简单的注解就像下面这样: @Entity @符号指示编译器其后面的内容是注解.在下面的例子中,注解的名称为Override: @Override void ...
- JAVA基础知识|反射
一.理解反射 1.1.基础概念 反射:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为ja ...
随机推荐
- docker 运行ubuntu镜像 apt-get update 问题
docker运行ubuntu镜像后,apt-getupdate出现问题如下: 根据上面的报错大概是因为....文件上没有生效(生效还需要10d 13h 33min 45s),看来是时间不够啊,需要等待 ...
- xcode windows版安装使用教程
随着iPhone.iPad.Mac等苹果产品越来越火爆,越来越多的初学者想要了解和尝试苹果平台,包括苹果操作系统Mac OS X.苹果演示软件Keynote.苹果开发工具Xcode等.然而,苹果电脑价 ...
- 《新标准C++程序设计》4.6(C++学习笔记16)
重载流插入运算符和流提取运算符 流插入运算符:“<<” 流提取运算符:“>>” cout 是在 iostream 中定义的,ostream 类的对象. “<<” 能 ...
- centos7创建ssh公钥
步骤1:使用ssh-keygen命令创建公钥和私钥 [root@model /]# [root@model /]# ssh-keygen -t rsa -P '' Generating public/ ...
- 初学者的困惑:OOP与一般编程的区别
*在写<程序猿的思维修炼>随笔中,我们大概猜想到了,OOP的思想更趋于模块化,更独立,因此称为一个个对象,本次随笔将对OOP和一般编程的区别有更详细的解释 面向对象编程的含义: 面向对象编 ...
- B. Yet Another Crosses Problem
B. Yet Another Crosses Problem time limit per test 2 seconds memory limit per test 256 megabytes inp ...
- EditText标签的使用
前文: 介绍EditText的使用,这个是文本输入控件,用来输入文本内容 使用: EditText继承TextView所以TextView的东西EditText都可以使用 text:显示文本 text ...
- Photoshop 更换证件照底色
1.打开photoshop CS6. 2.打开照片 (上栏)文件---->打开 或者,直接把照片拖进ps中. 3.复制图层 右击背景,点击复制图层 (复制图层的作用是,如果对图层操作错误,可以 ...
- 剑指offer_2.3_Day_6
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). n<=39 public class Solution { public int Fibo ...
- jQuery原理系列-css选择器实现
jQuery最强大的功能在于它可以通过css选择器查找元素,它的源码中有一半是sizzle css选择器引擎的代码,在html5规范出来之后,增加了document.querySelector和doc ...