注解与反射
内置注解
@Override
表示一个方法被重写,如果加了会首先检查父类是否有这个方法如果没有则会报错
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Deprecated
用于修辞方法、属性、类表示此方法已经废弃,暂时可用,后期可能会删除,建议后来人不要调用此类方法
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
@SuppressWarnings
用于抑制编译时的警告信息
使用时需要添加参数:
@SuppressWarnings(“all”)
@SuppressWarnings(“unchekced”)
@SuppressWarnings("value={“unchekced,“deprecation”}”)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) // 可作用范围
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value(); // 表示传参
}
元注解
负责注解其他的注解,Java 定义了 4 个标准的 meta-annotation 类型,他们被用来提供对其他 annotation 类型做说明
@Target
用于描述注解的使用范围
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Retention
表示需要在什么级别保存该注释信息,用于描述注解的生命周期(SOURCE < CLASS < RUNTIME)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Document
说明该注解将被包含在 javadoc 中
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Inheriteed
说明子类可以继承父类中的该注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
自定义注解
使用 @interface 自定义注解时,自动继承了 java.lang.annotation.Annotation 接口
public class Demo1 {
// 注解可以显示赋值,如果没有默认值,我们必须给注解赋值
@MyAnnotation2(name = "xiong")
public void test(){}
@MyAnnotation3("value可以省略不写")
public void test2(){}
}
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
// 注解的参数: 参数类型 + 参数名 ()
String name();
String value() default "xinq";
int id() default -1; // 如果默认值为 -1,代表不存在
String[] school() default {"清华大学","北京大学"};
}
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
// 只有参数名为 value 时,注解中 value 可以省略
String value();
}
反射机制
Reflection(反射)时 Java 被视为动态语言的关键,反射机制允许程序在执行期借助于 Reflection API 取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
优点
可以实现动态创建对象和编译,体现出巨大的灵活性
缺点
对性能有影响。使用反射基本上是一种解释操作,我们可以告诉 JVM,我们希望做什么并且他满足我们的要求。
public class Reflect {
public static void main(String[] args) throws ClassNotFoundException {
// 通过反射获取类的 class 对象
Class aClass = Class.forName("zhujie.User");
Class aClass1 = Class.forName("zhujie.User");
System.out.println(aClass);
// 一个类在内存中只有一个 class 对象
// 一个类加载后,类的整个结构都会被封装在 calss 对象中
System.out.println(aClass.equals(aClass1)); // 输出 true
}
}
class User{
private String name;
private String password;
private int age;
public User(){}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
public void setAge(int age) {
this.age = age;
}
}
Class 类
- Class 本身也是一个类
- Class 对象只能有系统建立对象
- 一个加载的类在 JVM 中只会有一个 Class 实例
- 一个 Class 对象对应的是一个加载到 JVM 中的一个 class 文件
- 每个类的实例都会记得自己是由哪个 Class 实例所生成
- 通过 Class 可以完整的得到一个类的所有被加载的结构
- Class 类是 反射 的根源,针对任何你想动态加载、运行的类,唯有先获得相应的 Class 对象
常用方法
static ClassforName(String name) | 返回指定类名 name 的 Class 对象 |
---|---|
Object newInstance() | 调用缺省构造函数,返回 class 对象的一个实例 |
getName() | 返回此 Class 对象所表示的实体(类,接口,数组类或 void)的名称 |
Class getSuperClass() | 返回当前 class 对象的父类 class 对象 |
Class[] getinterface() | 获取当前 class 对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Constructor[] getConstructors() | 返回一个包含某些 construct 对象的数组 |
Method getMethod(String name,Class… T) | 返回一个 Method 对象,此对象的形参类型为 ParamType |
Field[] getDeclaredField() | 返回 Field 对象的一个数组 |
获取 Class 的实例
- 若已知具体的类,通过 class 属性获取,该方法最为安全可靠,程序性能最高
Class clazz = Person.class
- 已知某个类的实例,调用该实例的 getClass() 方法获取 class 对象
Class clazz = person.getClass();
- 已知一个类的全类名,且该类在类路径下,可以通过 class 类的静态方法 forName() 获取
Class clazz = Class.forName("demo01.Student");
- 内置基本数据类可以直接用 类名.Type
- 还可以使用 ClassLoader
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
// 通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
// 通过forname 获得
Class c2 = Class.forName("zhujie.Student");
System.out.println(c2.hashCode());
// 通过 类名.class
Class c3 = Student.class;
System.out.println(c3.hashCode());
// 基本内置类的包装类型
Class c4 = Integer.TYPE;
System.out.println(c4);
// 获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
public String name;
public Person(String name) {
this.name = name;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Student extends Person{
public Student() {
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(String name) {
this.name = "老师";
}
}
所有类型的 Class
public class Test02 {
public static void main(String[] args) {
Class c1 = Object.class; // 类
Class c2 = Comparable.class; // 接口
Class c3 = String[].class; // 一维数组
Class c4 = int[][].class; // 二维数组
Class c5 = Override.class; // 注解
Class c6 = ElementType.class; // 枚举
Class c7 = Integer.class; // 包装类
Class c8 = void.class; // void
Class c9 = Class.class; // Class
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
}
}
/* 输出
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
*/
类的加载过程
占坑
获得类的信息
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class c1 = Class.forName("zhujie.User");
// 获得类的名字
System.out.println(c1.getName()); // 获得 包名 + 类名
System.out.println(c1.getSimpleName()); // 获得类名
// 获得类的属性
Field[] fields = c1.getFields(); // 只能获得 public 属性
fields = c1.getDeclaredFields(); // 获得所有属性
for (Field field : fields){
System.out.println(field);
}
// 获得类的方法
Method[] methods = c1.getMethods(); // 获得本类或者父类的 public 方法
for (Method method : methods){
System.out.println("正常:"+method);
}
methods = c1.getDeclaredMethods(); // 获得本类所有方法
for (Method method : methods){
System.out.println("getDeclaredMethods:"+method);
}
// 获得指定方法
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
// 获得指定的构造器
Constructor[] constructors = c1.getConstructors(); // 获得 public
for (Constructor constructor : constructors){
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors(); // 获得全部
for (Constructor constructor : constructors){
System.out.println(constructor);
}
// 获得指定 填入参数类型的 class
Constructor constructor = c1.getDeclaredConstructor(String.class, String.class, int.class);
System.out.println(constructor);
}
}
反射的使用
public class Test05 {
//动态创建对象
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1 = Class.forName("zhujie.User");
// 构造一个的对象
User user = (User)c1.newInstance();
System.out.println(user);
// 通过构造器创建
Constructor constructor = c1.getDeclaredConstructor(String.class, String.class, int.class);
User user1 = (User)constructor.newInstance("xiong", "mao", 12);
System.out.println(user1.getName());
// 通过反射调用普通方法
User user3 = (User)c1.newInstance();
// 通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
// invoke(对象,参数) 激活此方法
setName.invoke(user3, "xiongmao");
System.out.println(user3.getName());
// 通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
// 无法直接操作私有属性
// name.set(user4, "XiongMaoHei");
// 报错:
// Class zhujie.Test05 can not access a member of class zhujie.User with modifiers "private"
name.setAccessible(true); // 设置可访问
name.set(user4, "XiongMaoHei");
System.out.println(user4.getName());
}
}
性能测试
public class Test06 {
// 普通方法调用
public static void test01(){
User user = new User();
long startTime = System.currentTimeMillis();
for (long i = 0; i < 10_0000_0000L; i++) {
user.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法执行10亿次"+(endTime-startTime));
}
// 反射方法调用
public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName",null);
long startTime = System.currentTimeMillis();
for (long i = 0; i < 10_0000_0000L; i++) {
getName.invoke(user, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方法调用执行10亿次"+(endTime-startTime));
}
// 反射方法调用 设置可访问
public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName",null);
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for (long i = 0; i < 10_0000_0000L; i++) {
getName.invoke(user, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方法调用执行10亿次"+(endTime-startTime));
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
test01();
test02();
test03();
}
}
// 输出:
普通方法执行10亿次622
反射方法调用执行10亿次2853
反射方法调用执行10亿次1621
开启访问权限可以有效提高反射调用的效率
通过反射获取泛型
public class Test07 {
// 通过反射获取泛型
public static void main(String[] args) throws NoSuchMethodException {
Method method = Test07.class.getMethod("test01", Map.class, List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes){
System.out.println("###"+genericParameterType);
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments){
System.out.println(actualTypeArgument);
}
}
}
method = Test07.class.getMethod("test02", null);
Type genericReturnType = method.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments){
System.out.println("return: "+actualTypeArgument);
}
}
}
public void test01(Map<String, User> map, List<User> list){
System.out.println("test1");
}
public Map<String, User> test02(){
System.out.println("test2");
return null;
}
}
获取注解信息
/**
* 尝试写一个与数据库相关的映射注解
*/
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("zhujie.Student2");
// 通过反射活获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 获得注解 value 值
MyTable myTable = (MyTable) c1.getAnnotation(MyTable.class);
String value = myTable.value();
System.out.println(value);
// 获得类指定注解
Field name = c1.getDeclaredField("name");
MyField annotation = name.getAnnotation(MyField.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@MyTable("db_student")
class Student2{
@MyField(columnName = "db_id", type = "int", length = 10)
private int id;
@MyField(columnName = "db_age", type = "int", length = 10)
private int age;
@MyField(columnName = "db_name", type = "int", length = 10)
private String name;
public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public Student2() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTable{
String value();
}
// 属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyField{
String columnName();
String type();
int length();
}