Java注解与反射——各类注解,反射机制简介
注解(Java.Annotation)
Annotation:不是程序本身,但可以对程序作出解释。可以被其它程序读取。
可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问。
内置注解
1.@Override:修饰方法,表示一个方法声明打算重写超类中的另一个方法声明。
2.@Deprecated:可修饰方法,属性,类,表示不鼓励使用这样的元素。
3.@SuppressWarnings:用来抑制编译时的警告信息。
元注解
负责注解其他注解,Java定义了4个标准的meta-annotation,被用来提供对其他annotation类型做说明。
1.@Target:用于描述注解的适用范围。
2.@Retention:表示需要在什么级别保存该注解信息,用于描述注解的生命周期。(SOURCE < CLASS < RUNTIME)
3.@Document:说明该注解将被包含在javadoc中。
4.@Inherited:说明子类可以继承父类中的该注解。
自定义注解
使用@interface自定义注解,自动继承java.lang.annotation.Annotation接口。
其中每一个方法实际上是声明了一个配置参数。
方法的名称就是参数的名称。返回值类型就是参数的类型(返回值类型只能是基本类型,Class,String,enum)。可以通过default来声明参数的默认值。
如果只有一个参数成员,一般参数名为value。
注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值。
反射机制(Java.Reflection)
概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
可以动态创建对象和编译,体现出很大的灵活性。但对性能有影响。
1.一个类在内存中只有一个class对象;
2.一个类被加载后,类的整个结构都会被封装在class对象中;
3.一个Class对象对应的是一个加载到JVM中的一个class文件;
4.每个实例都知道自己是由哪个class实例所生成;
5.Class类是Reflection的根源,针对任何想动态加载、运行的类,唯有先获得相应的Class对象。
只要元素类型与维度一样,就是同一个class。
类加载内存分析
类加载过程:类的加载——类的链接——类的初始化。
类的主动引用:(一定会发生类的初始化)
类的被动引用:(不会发生类的初始化)
动态创建对象执行方法实例:
package org.example.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class test9 {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("org.example.reflection.User");
//构造一个对象
User user = (User)c1.newInstance();//本质是调用类的无参构造器
System.out.println(user);
//通过构造器构建对象
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) declaredConstructor.newInstance("z", 1, 20);
System.out.println(user2);
//通过反射调用普通方法
User user3 = (User)c1.newInstance();
Method setName = c1.getMethod("setName", String.class);
//invoke:激活,参数(对象,“方法的值”)
setName.invoke(user3, "z");
System.out.println(user3.getName());
//通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,需要关闭程序的安全检测,通过属性或者方法的setAccessible(true),可提高代码效率
name.setAccessible(true); //
name.set(user4, "z");
System.out.println(user4);
}
}
反射操作泛型
Java采用泛型擦除的机制引入泛型,Java中泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除。
为了通过反射操作这些类型,Java新增了几种类型来代表不能被归一到Class类中的类型,但是又和原始类型齐名的类型。