博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java反射机制、自定义注解以及元注解的使用
阅读量:3960 次
发布时间:2019-05-24

本文共 7304 字,大约阅读时间需要 24 分钟。

什么是注解

1.Annotation是从JDK5.0开始引入的新技术
2.Annotation作用:

不是程序本身,可以对程序作出解释

可以被其他程序(比如:解析器等)读取

3.Annotation的格式:

注解是以“@注释名”在代码重存在的,还可以添加一些参数值

例如:@SuppressWarnings(value=“unchecked”);

4.Annotation在哪里使用?

可以在package、class、method、field等上面;

内置注解

1.Override注解

表示方法声明旨在覆盖超类型中的方法声明。如果使用此注释类型注释方法,则除非至少满足以下条件之一,否则需要编译器生成错误消息:

该方法将覆盖或实现在超类型中声明的方法。

该方法具有与Object中声明的任何公共方法的 。

2.@Deprecated注解

注释@Deprecated的程序元素是程序员不鼓励使用的程序元素,通常是因为它是危险的,或者因为存在更好的替代方法。 编译器在不被弃用的代码中使用或覆盖不推荐使用的程序元素时发出警告。

3.@SuppressWarnings注解

表示在注释元素(以及注释元素中包含的所有程序元素)中应该抑制命名的编译器警告。请注意,给定元素中抑制的一组警告是所有包含元素中抑制的警告的超集。例如,如果您注释一个类来抑制一个警告并注释方法来抑制另一个警告,则两个警告将在该方法中被抑制。

作为一种风格,程序员应该始终将这个注释用于最有效的嵌套元素。 如果要在特定方法中抑制警告,则应该注释该方法而不是其类。

元注解

元注解的作用就是赋值注解奇特注解,JAVA定义了4个表中的meta-annotation类型,他们被用来提供对其他annotation类型做说明.

这些类型和它们所支持的类在java.lang.annotation包中可以找到(@Target、@Retention、@Documented、@Inherited)

  • @Target:用于描述注解的使用范围(即:表示我们的注解可以用在什么地方)

  • @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期 (即:我们的注解在哪亦然保持效果)

(SOURCE<CLASS<RUNTIME)

  • @Document:说明该注解将被包含在javadoc中

  • @Inherited:说明子类可以继承父类中的该注解

自定义注解

1.使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation注解

  • 分析
    • @interface用来声明一个注解,格式public @interface 注解名{定义内容}
    • 其中的每一个方法实际上是声明了一个配置参数
    • 方法的名称就是参数的名称
    • 返回值类型就是参数的类型(返回值只能是基本类型,class、String、enum)
    • 可以通过default来声明参数的默认值
    • 如果只有一个参数成员,一般参数名为value
    • 注解元素必须要有值,我们定义注解元素时,经常使用空字符串或0作为默认值
1.自定义注解使用
/** * @Target 能在什么地方使用:类、接口、方法 * @Retention 能在什么领域使用 */@Target(value{
ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {
//MyAnnotation注解名 String value() default""; //value 注解属性名、String注解类型、default注解默认值}

反射概念

Reflection(反射)

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

2.加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射

在这里插入图片描述

  • 反射的优点:

    • 可以实现动态创建对象和编译,体现出很大的灵活性
  • 反射的缺点:

    • 对性能有影响,使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求,这类操作总是慢于直接执行相同的操作。
  • 反射的作用:

    • 在程序运行中动态获取堆内存中任意类的Class对象,实现动态创建对象和编译,反射机制的灵活性非常强大,大部分框架都使用了反射机制,反射的缺点就是影响性能。
获取reflection(反射)对象
/** * 创建人: 渣高帆 
* 创建时间: 2020/6/15 10:54
* JDK 1.8 * 作用:通过反射获取类的Class对象 */public class RefletionTest {
public static void main(String[] args) {
//创建一个Class对象 Class
aClass = null; try {
//通过反射获取类的Class对象,一个类只有一个Class对象 //类被加载后整个类的结构都会被封装在Class对象中 aClass = Class.forName("com.zgf.annotation01.entity.Phone"); } catch (ClassNotFoundException e) {
e.printStackTrace(); } System.out.println(aClass); }}
Class类的常用方法
  1. static forName(String name):返回指定类名name的Class对象(完整限定名)
  2. Object newInstance():调用缺省构造函数,返回Class对象的一个实例
  3. getName():返回此Class对象所表示的实体(类、接口、数组类或void)的名称。
  4. Class getSuperClass():返回此Class对象的父类的Class对象
  5. Class [] getinterfaces():获取当前Class对象的接口
  6. ClassLoader getClassLoader():返回该类的类加载器
  7. Constructor [] getConstructors():返回一个包含某些Constructor对象的数组。
  8. Method getMothed(String name,Class… T):返回一个Method对象,此对象的形参类型为paramType;
  9. Field [] getDeclaredFields():返回File对象的一个数组
Class类的创建方式

在这里插入图片描述

哪些类型可以有Class对象?
  1. class: 外部类,成员(成员内部类,静态内部类)
  2. interface:接口
  3. []:数组
  4. enum:枚举
  5. annotation:注解@interface
  6. primitive type:基本数据类型
  7. void
类加载内测分析
  1. java内存分析图:
    在这里插入图片描述
    2.类的加载:
    在这里插入图片描述

3.类的加载与ClassLoader的理解

在这里插入图片描述

什么时候会发生类初始化

在这里插入图片描述

类加载器的作用

在这里插入图片描述

在这里插入图片描述

创建运行时类的对象

在这里插入图片描述

获取运行时类的完整结构
/** * 创建人: 渣高帆 
* 创建时间: 2020/6/15 10:54
* JDK 1.8 * 作用:通过反射获取类的Class对象,以及获取类中结构 */public class RefletionTest {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
//创建一个Class对象 Class
aClass = null; try {
//通过反射获取类的Class对象,一个类只有一个Class对象 //类被加载后整个类的结构都会被封装在Class对象中 aClass = Class.forName("com.zgf.annotation01.entity.Phone"); } catch (ClassNotFoundException e) {
e.printStackTrace(); } //aClass.getName():通过反射获取类的完全限定名 System.out.println(aClass.getName()); //aClass.getSimpleName():通过反射获取类的名字 System.out.println(aClass.getSimpleName()); //aClass.getField(属性名):反射获取单个属性,属性只能是公开的 Field field = aClass.getField("phonename"); System.out.println(field); //aClass.getFields():反射获取多个属性数值,只能获取公开属性 Field[] fields = aClass.getFields(); for (Field fields1 : fields) {
System.out.println(fields1); } //aClass.getDeclaredField(属性名):反射获取单个所有访问权限的属性,例如:private、public Field phonename = aClass.getDeclaredField("phonename"); System.out.println(phonename); //aClass.getDeclaredFields():反射获取多个所有访问权限的属性,例如:private、public Field[] declaredFields = aClass.getDeclaredFields(); for (Field declaredFields1 : declaredFields) {
System.out.println(declaredFields1); } //aClass.getMethod("方法名"):反射获取类中单个公开的方法,包括基类和父类 Method method = aClass.getMethod("方法名"); //aClass.getMethods():反射获取类中所有公开的方法,包括基类和父类 Method[] methods = aClass.getMethods(); //aClass.getDeclaredMethods():反射获取类中任何访问权限,单个公开的方法,不包括基类和父类 Method declaredMethod = aClass.getDeclaredMethod("方法名"); //aClass.getDeclaredMethods():反射获取类中任何访问权限,所有公开的方法,不包括基类和父类 Method[] declaredMethods = aClass.getDeclaredMethods(); }}

动态创建对象执行方法

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

动态创建对象操作类结构

/** * 创建人: 渣高帆 
* 创建时间: 2020/6/16 8:56
* JDK 1.8 * 作用:通过反射动态创建对象 */public class RefletionTest01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class
c1 = Class.forName("com.zgf.annotation.entity.User"); //通过反射无参构造来创建一个对象,c1.newInstance()这里获取的是一个构造方法 User user = (User) c1.newInstance(); System.out.println(user); //通过反射有参构造来创建一个对象,getDeclaredConstructor(传入你需要使用构造方法的参数类型) //在Java反射机制中,此方法为暴力获取一个Class文件的私有构造。 Constructor
constructor = c1.getDeclaredConstructor(String.class, String.class, String.class); //根据获取的有参构造方法来创建对象并赋予初始值 User user2 = (User) constructor.newInstance("渣高帆", "18", "男"); System.out.println(user2); //反射无参构造创建对象 User user3= (User) c1.newInstance(); //得到一个公开的方法,c1.getDeclaredMethod(方法名,参数类型...); Method method = c1.getDeclaredMethod("setName", String.class); //执行方法, 方法.invoke(对象,传递的参数); method.invoke(user3,"赵盼"); System.out.println(user3); //通过反射获取属性 User user4= (User) c1.newInstance(); //得到一个公开的方法 Field name = c1.getDeclaredField("name"); //关掉权限检查,关掉权限后可以访问任何访问权限修饰的属性,true为关掉、false为开启 name.setAccessible(true); //为当前类属性赋值 name.set(user4,"李黑狗"); System.out.println(name.get(user4)); }}

反射操作注解

/** * 创建人: 渣高帆 
* 创建时间: 2020/6/16 11:04
* JDK 1.8 * 作用:反射操作注解 */public class RefletionTest02 {
public static void main(String[] args) throws ClassNotFoundException {
//反射获取Class对象 Class
c1 = Class.forName("com.zgf.annotation.entity.User"); //getAnnotation(自定义注解):获取当前Class对象注解信息 DataClass annotation = c1.getAnnotation(DataClass.class); //根据注解的属性名获取值 System.out.println(annotation.name()); }}
//反射获取Class对象        Class
c1 = Class.forName("com.zgf.annotation.entity.User"); //getAnnotation(自定义注解):获取当前Class对象注解信息 DataClass annotation = c1.getAnnotation(DataClass.class); //根据注解的属性名获取值 System.out.println(annotation.name()); }}

转载地址:http://omqzi.baihongyu.com/

你可能感兴趣的文章
安装 docker-compose (实测可用,妈妈再也不用担心被墙了)
查看>>
docker下删除none的images
查看>>
Linux提权获取敏感信息方法
查看>>
Ubuntu 16.04开机A start job is running for Raise network interface(5min 4s)解决方法
查看>>
Ubuntu 16.04开机隐藏菜单缩短时间
查看>>
Ubuntu 更换国内源
查看>>
Ubuntu16.04下Docker pull connection refused 解决办法
查看>>
通过 三大机制 揭秘 IPFS 工作原理
查看>>
Ubuntu 16.04卸载PostgresQL
查看>>
华为路由器交换机配置命令
查看>>
docker下运行kalilinux并配置ssh访问
查看>>
使用 Docker 容器应该避免的 10 个事情
查看>>
postgres基本操作(个人总结版)
查看>>
求数组中最长递增子序列
查看>>
用C++设计一个不能被继承的类
查看>>
linux core文件机制
查看>>
私有继承中的派生类对象与基类对象间的转换
查看>>
5.7 观察者模式observer(行为模式)
查看>>
建造者模式Builder(创建模式)
查看>>
Linux文件系统目录结构的详细解说(一)
查看>>