JAVA反射机制、注解JAVA反射机制一. 概念二. 优缺点三. Class类的常用方法四. 通过反射机制获取获取Class对象获取构造方法的信息(Constructor)Constructor类中的常用方法获取成员变量的信息(Field)Field类中的常用方法获取方法的信息(Method)Method类中的常用方法注解一. 概念二. 注解的用途三. 注解类型元注解@Retention@Target@Documented@Inherited@Repeatable内置注释(用于预警)自定义注解注解的属性注解的快捷方式注解不支持继承

JAVA反射机制

一. 概念

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的功能称为Java语言的的反射机制。

二. 优缺点

优点: 在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

缺点:(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;

(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

三. Class类的常用方法

方法名

功能说明

static Class forName(String name)

返回指定类名的Class对象

Object newInstance()

调用缺省构造函数,返回Class对象的一个实例

getName()

返回此Class对象所表示的实体(类,接口,数组类或void)的名称

Class getSuperClass()

返回当前Class对象的父类的Class对象

Class[] getInterfaces()

获取当前Class对象的接口

ClassLoader getClassLoader()

返回该类的类加载器

Constructor[] getConstructors()

返回一个包含某些Construtor对象的数组

Method getMethod(String name, Class<?>… T)

返回一个指定名称和参数列表的Method对象

Field getDeclaredFields()

返回一个Field对象的数组

四. 通过反射机制获取

获取Class对象

任何一个类都有一个隐含的静态成员变量class,通过该静态成员获取Class对象的引用。


1. 类名.class Class c1 = Student.class;


使用对象的getClass()方法获取Class对象的引用


2. 对象.getClass() Student stu = new Student(); Class c2 = stu.getClass();


使用Class类的静态方法forName(),它使用一个包含目标类的字符串作为输入,返回一个Class对象的引用。通过该方法获取Class对象时需要处理ClassNotFoundException异常,该异常代表找不到类或者类无法加载。


3. Class.forName(类的全限定名) // 全限定名:包名.类名 Class c3 = Class.forName("包名.类名");


4. 基本类型的包装类可以直接使用 类名.Type


获取构造方法的信息(Constructor)

方法

功能描述

getConstructors()

返回一个Constructor对象的数组,这些对象为此Class对象所表示的类的所有公共构造方法;

getDeclaredConstructors()

返回一个Constructor对象的数组,这些对象为此Class对象所表示的类的所有构造方法

getConstructor(Class<?>...parameterTypes)

返回一个Constructor对象,他代表此Class对象所表示的类的指定公共构造方法

getDeclaredConstructor(Class<?>...parameterTypes)

返回一个Constructor对象,他代表此Class对象所表示的类或接口的指定公共构造方法

Constructor类中的常用方法

方法

功能描述

newInstance()

使用Constructor对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

isVarArgs()

如果声明此构造方法可以带可变数量的参数,则返回true;否则,返回false

setAccessible(boolean flag)

返回值为true表示反射的对象在使用时应该取消Java语言访问检查;返回值为false则表示反射的对象应该实施Java语言访问检查

getParameterTypes()

返回一组Class对象,这些对象表示此Constructor对象所表示的构造方法的形参类型

获取成员变量的信息(Field)

方法

功能描述

getField(String name)

返回一个Field对象,它反映此Class对象所表示的类或接口的指定公共成员字段

getFields()

返回一个Field对象的数组,这些对象反映此Class对象所表示的类或接口的所有可访问公共字段(public),包括父类中的字段(all + 非私有)

getDeclaredField(String name)

返回一个Field对象,该对象反映此Class对象所表示的类或接口的指定已声明字段。name参数是一个String,它指定所需字段的简称

getDeclaredFields()

返回一个Field对象的数组,这些对象反映此Class对象所表示的类或接口的所声明的所有字段。包括公共、保护、默认访问和私有字段,但不包括继承的字段(自身 + 私有)

Field类中的常用方法

方法

功能描述

get(Object obj)

返回指定对象上此Field表示的字段的值

set(Object obj,Object value)

将指定对象变量上此Field对象表示的字段设置为指定的新值

getName()

返回此Field对象表示的字段的名称

getType()

返回一个Calss对象,他代表此Field对象所表示字段的声明类型

getInt(Object obj)

获取int类型或另一个通过扩展转换可以转换为int 类型 的基本类型的静态或实例字段的值。

setInt(Object obj,int i)

讲字段的值设置为指定对象上的一个int值

getBoolean(Object obj)

获取一个静态或实例boolean字段的值

setBoolean(Object obj,boolean z)

将字段的值设置未指定对象上的一个boolean值

getFloat(Object obj)

获取float类型或另一个通过扩展转换可以转换为float类型的基本类型的静态或实例字段的值

setFloat(Object obj,float f)

将字段的值设置为指定对象上的一个float值

获取方法的信息(Method)

方法

功能描述

getMethods()

返回一个Method对象的数组,这些对象反映此Class对象所表示的类或接口的公共方法(all + 非私有)

getDeclaredMethods()

返回一个Method对象的一个数组,这些对象反映此Class对象表示的类或接口声明的所有方法,包括公共、保护、默认访问和私有方法,但不包括继承的方法(自身+私有)

getMethod(String name,Class<?>..parameterTypes)

返回一个Method对象,它反映此Class对象所表示的类或接口的指定公共成员方法

getDeclaredMethod(String name,Class<?>..parameterTypes)

返回一个Method对象,它反映此Class对象所表示的类或接口的指定已声明方法

Method类中的常用方法

方法

功能描述

getName()

以String形式返回此Method对象表示的方法名称

getParameterTypes()

按照声明顺序返回Class对象的数组,这些对象描述了此Method对象所表示的方法的形参类型

getReturnType()

返回一个Class对象,该对象描述此Method对象所表示的方法的正式返回类型

getExceptionTypes()

返回Class对象的数组,这些对象描述了声明将此Method对象表示的底层方法抛出的异常类型

invoke(Object obj,Object...args)

对带有指定参数的指定对象该调用由此Method对象表示的底层方法

注解

一. 概念

注解也叫元数据,即一种描述数据的数据。,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解。

一个注解准确意义上来说,只不过时一种特殊的注释而已。

注解的本质就是一个继承了Annotation接口的接口。

二. 注解的用途

1.生成文档,通过代码里的标识的元数据生成javadoc文档。

2.编译检查,通过代码里表示的元数据让编译器在编译期间进行检查验证。

3.编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码。

4.编译时动态处理,运行时通过代码里标识的元数据动态处理,例如使用反射注入实例。

三. 注解类型

  • 元注解(用于定义注解的注解)
  • 内置注解(Java自带的标准注解)
  • 自定义注解

元注解

元注解是用于修饰注解的注解,元注解有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 种。

@Retention

当@Retention应用到一个注解上的时候,它解释说明了这个注解的存活时间。

方法名

功能

RetentionPolicy.SOURCE

注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。

RetentionPolicy.CLASS

注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。

RetentionPolicy.RUNTIME

注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

@Target

Target 是目标的意思,@Target 指定了注解运用的地方。

方法名

功能

ElementType.ANNOTATION_TYPE

可以给一个注解进行注解

ElementType.CONSTRUCTOR

可以给构造方法进行注解

ElementType.FIELD

可以给属性进行注解

ElementType.LOCAL_VARIABLE

可以给局部变量进行注解

ElementType.METHOD

可以给方法进行注解

ElementType.PACKAGE

可以给一个包进行注解

ElementType.PARAMETER

可以给一个方法内的参数进行注解

ElementType.TYPE

可以给一个类型进行注解,比如类、接口、枚举

@Documented

Documented和文档有关,它的作用是能够将注解中的元素包含到Javadoc中去。

@Inherited

Inherited是继承的意思,如果一个超类使用了@Inherited注解,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。

@Repeatable

Repeatable是可重复的意思,@Repeatable在需要对同一种注解多次使用时使用。

内置注释(用于预警)

注解类型

说明

@Override

检查该方法是否是重新加载

@Deprecated

标记已过时的方法

@SuppressWarning

只是表一起忽略注解中声明的警告

@FunctionalInterface

函数式接口 (Functional Interface) 就是一个具有一个方法的普通接口

自定义注解


public @interface 注解名{ //属性 }


注解的属性

注解的属性也叫做成员变量。注解只有成员变量没有方法。

注解的成员变量在注解的定义中以"无形参的方法"形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    int id();

    String msg();
}


注解的快捷方式

所谓的快捷方式就是注解中定义了名为value的元素,并且在使用该注解时,如果该元素是唯一需要赋值的一个元素,那么此时无需使用key=value的语法,而只需在括号内给出value元素所需的值即可。


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface IntegerVaule{
   int value() default 0;
   String name() default "";
}

public class QuicklyWay {

   @IntegerVaule(20)
   public int age;

   @IntegerVaule(value = 10000, name = "MONEY")
   public int money;

}


注解不支持继承

注解是不支持继承的,因此不能使用关键字extends来继承某个@interface,但注解在编译后,编译器会自动继承java.lang.annotation.Annotation接口