黑马程序员技术交流社区

标题: [石家庄校区]--反射技术和注解 [打印本页]

作者: 毕业后八块腹肌    时间: 2018-12-2 15:56
标题: [石家庄校区]--反射技术和注解
反射

反射: 将类的各个组成部分, 封装为其他对象, 这就是反射机制

成员变量(字段): Field类的对象

构造方法: Constructor类的对象

成员方法: Method类的对象


好处:

1. 可以在程序运行过程中, 操作这些对象

2. 可以解耦, 提高程序的可扩展性



Java代码在计算机中的3个阶段:

SOURCE: 源代码阶段

CLASS: 类对象阶段

RUNTIME: 运行时阶段


获取一个类的字节码对象的3种方式:

1. Class.forName("全类名")

将字节码文件加载进内存,返回Class对象

适用场景: 多用于配置文件,将类名定义在配置文件中. 读取文件, 加载类

2. 类名.class

通过类名的属性class获取

适用场景: 多用于参数的传递 getConstructor(String.class, int.class)

3. 对象.getClass()

getClass()方法在Object类中定义

适用场景: 多用于对象的获取字节码的方式 p.getClass()

同一个类的字节码对象, 只有"唯一的一个"


Class类

java.lang.Class类: 表示一个类的字节码对象, 其中包含该类中定义的内容

// 成员方法

// 1. 获取成员变量们

Field[] getFields(): 获取所有 public 的成员变量

Field getField(String name): 获取指定名称的 public 的成员变量

Field[] getDeclaredFields(): 获取所有的成员变量, 不考虑权限修饰符

Field getDeclaredField(String name): 获取指定名称的成员变量, 不考虑权限修饰符

// 2. 获取构造方法们

Constructor[] getConstructors(): 获取所有 public 的构造方法

Constructor getConstructor(Class... parameterTypes): 获取指定的 public 构造方法

Constructor[] getDeclaredConstructors(): 获取所有的构造方法, 不考虑权限修饰符

Constructor getDeclaredConstructor(Class... parameterTypes): 获取指定的构造方法,

// 3. 获取成员方法们

Method[] getMethods(): 获取所有 public 的成员方法

Method getMethod(String name, Class... parameterTypes) : 获取指定的 public 成员方法

Method[] getDeclaredMethods(): 获取所有的成员方法, 不考虑权限修饰符

Method getDeclaredMethod(String name, Class... parameterTypes): 获取指定的成员方法, 不考虑权限修饰符

// 4. 获取Class对象代表的类的全类名

String getName(): 获取当前Class对象代表的类的全类名

// 5. 创建对象

T newInstance(): 使用当前类的空参构造, 创建一个对象

反射获取成员变量Filed

1. 获取成员变量们

Field[] getFields(): 获取所有 public 的成员变量

Field getField(String name): 获取指定名称的 public 的成员变量

Field[] getDeclaredFields(): 获取所有的成员变量, 不考虑权限修饰符

Field getDeclaredField(String name): 获取指定名称的成员变量, 不考虑权限修饰符




java.lang.reflect.Field: 表示一个成员变量

// 成员方法 String name; Person p = new Person(); p2.name = "abc";

void set(Object obj, Object value): 设置指定对象的成员变量的值 field.set(p1, "abc")

Object get(Object obj): 获取指定对象的成员变量的值 field.get(p1)

void setAccessible(boolean flag): 传true时忽略访问权限修饰符的安全检查. 暴力反射 field.set



反射获取构造方法Constructor

java.lang.Class类: 表示一个类的字节码对象, 其中包含该类中定义的内容

// 获取构造方法们

Constructor[] getConstructors(): 获取所有 public 的构造方法

Constructor getConstructor(Class... parameterTypes): 获取指定的 public 构造方法

Constructor[] getDeclaredConstructors(): 获取所有的构造方法, 不考虑权限修饰符

Constructor getDeclaredConstructor(Class... parameterTypes): 获取指定的构造方法, 不 考虑权限修饰符

T newInstance(): 使用当前类的空参构造创建一个对象


Constructor con = c.getConstructor(String.class, int.class);

con.newInstance("zhangsan", 18);

new Person("zhangsan", 18);


java.lang.reflect.Constructor: 表示一个构造方法

// 成员方法

T newInstance(Object... initargs): 使用当前构造方法传入参数, 创建对象

void setAccessible(boolean flag): 注意: 构造方法不能利用此方法忽略权限, 会抛异常



反射获取成员方法Method

java.lang.Class类: 表示一个类的字节码对象, 其中包含该类中定义的内容

// 获取成员方法们:

Method[] getMethods(): 获取所有 public 的成员方法

Method getMethod(String name, Class... parameterTypes) : 获取指定的 public 成员方法

Method[] getDeclaredMethods(): 获取所有的成员方法, 不考虑权限修饰符

Method getDeclaredMethod(String name, Class... parameterTypes): 获取指定的成员方法, 不考虑权限修饰符


java.lang.reflect.Method类: 表示一个成员方法

// 成员方法 Person p = new Person(); p.eat("adf", 123);

Object invoke(Object obj, Object... args): 使用指定对象和指定参数值调用此方法

String getName(): 获取方法名

void setAccessible(boolean flag): 传true时忽略访问权限修饰符的安全检查. 暴力反射


注解

注解: 说明程序的。给计算机看的

注释: 用文字描述程序的。给程序员看的

使用注解: @注解名称


作用分类:

1. 编写文档: 通过代码里标识的注解生成文档

(生成API文档 @author @version @since @param @return)

2. 代码分析: 通过代码里标识的注解对代码进行分析 (使用反射)

(JUnit提供的 @Test @Before @After)

3. 编译检查: 通过代码里标识的注解让编译器能够实现基本的编译检查

(@Override @FunctionalInterface)


JDK中预定义的一些注解:

@Override: 检测被该注解标注的方法是否是"重写"父类(接口)的

@Deprecated: 该注解标注的内容,表示已过时

@SuppressWarnings: 压制警告. 一般传递参数all @SuppressWarnings("all")


注解本质上就是一个接口,该接口默认继承Annotation接口

public interface MyAnno extends java.lang.annotation.Annotation {}


枚举:

enum, enumeration. JDK 1.5 引入

主要是用于定义一些"相关的"常量, 比如星期, 颜色, 用来进行区分

枚举定义方式:

public enum 枚举名 {

枚举常量1, 枚举常量2, 枚举常量3;

}

使用方式:枚举名.常量名



元注解

元注解:             用于描述注解的注解

public @interface 注解名称 {
属性; (接口中的抽象方法)
属性;
属性;
...

}
常用元注解:
@Target: 描述注解能够作用的位置
ElementType枚举的常用取值:
TYPE:可以作用于类上
METHOD:可以作用于方法上
FIELD:可以作用于成员变量上
示例: @Target(value = {ElementType.TYPE, ElementType.METHOD})

@Retention: 描述注解被保留的阶段
RetentionPolicy枚举的取值:
SOURCE: 保留到源代码阶段
CLASS: 保留到类对象阶段
RUNTIME: 保留到运行时阶段
示例: @Retention(RetentionPolicy.RUNTIME):保留注解到class字节码文件中并被JVM读取到
@Documented: 加上后, 当前注解会被抽取到api文档中
@Inherited: 加上后, 当前注解会被子类继承



自定义注解

属性:
接口中的"抽象方法"
属性的要求:
1. 属性的"返回值类型"可以是以下类型:
基本数据类型(8种)
String
枚举
注解
以上类型的数组
2. 定义了属性,在使用注解时, 需要"给属性赋值" (其实是抽象方法的返回值)
1. 属性使用 default 关键字指定默认值, 则可以不赋值
2. 如果只有一个名为"value"的属性需要赋值, 则 value 可以省略, 直接写值即可
3. 给数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略

注解类型 注解变量名 = 被注解的类.class.getAnnotation(注解名.class);
数据类型 变量名 = 注解变量名.抽象方法();

ProAnno proAnno = Test.class.getAnnotation(ProAnno.class);
String className = proAnno.className();
String methodName = proAnno.methodName();















欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2