java反射机制和自定义注解原理分析和实例
来源:互联网 发布:腾讯足球数据库 编辑:程序博客网 时间:2024/04/28 00:51
1、概述
熟悉android开发的都会了解到Android的xUtils框架的ViewUtils模块,简化了findViewById的编写,通过完全注解方式就可以进行UI,资源和事件绑定。实现基本原理就是通过java中的注解和反射实现,本文主要介绍java中的反射机制和自定义注解的原理和实例编写。
2、反射机制
定义:反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
(1)反射机制提供的主要功能:
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;
- 生成动态代理。
3、反射机制应用案例
(1)获取某个类的属性
package com.chunsoft.testReflect;import java.lang.reflect.Field;import java.lang.reflect.Modifier;public class TestReflect{ private String testField1 = "testField1"; public int value = 2017; public static void main(String[] args) throws Exception { //获取当前类的字节码 Class<?> clazz = Class.forName("com.chunsoft.testReflect.TestReflect"); System.out.println("===============本类所有属性==============="); //获取本类的所有属性 Field[] declaredFields = clazz.getDeclaredFields(); for(int i = 0;i < declaredFields.length;i ++) { //权限修饰符 int mo = declaredFields[i].getModifiers(); String priv = Modifier.toString(mo); //属性类型 Class<?> type = declaredFields[i].getType(); String name = type.getName(); System.out.println(priv + " " + name + " " + declaredFields[i].getName() + ";"); } System.out.println("==========获取public的属性=========="); // 取得public的属性 Field[] fields = clazz.getFields(); for (int i = 0; i < fields.length; i++) { //权限修饰符 int mod = fields[i].getModifiers(); String priv = Modifier.toString(mod); //属性类型 Class<?> type = fields[i].getType(); String name = type.getName(); System.out.println(priv + " " + name + " " + fields[i].getName() + ";"); } }}
(2)获取某个类的全部方法
package com.chunsoft.testReflect;import java.lang.reflect.Method;import java.lang.reflect.Modifier;public class TestReflectMothod { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.chunsoft.testReflect.TestReflectMothod"); //获取Public类型方法和实现的接口或者父类的方法 //Method method[] = clazz.getMethods(); //获取所有方法 Method method[] = clazz.getDeclaredMethods(); for (int i = 0; i < method.length; i++) { //获取返回类型 Class<?> returnType = method[i].getReturnType(); //获取参数类型 Class<?>[] parameterTypes = method[i].getParameterTypes(); //获取权限修饰符 int temp = method[i].getModifiers(); System.out.print(Modifier.toString(temp) + " "); System.out.print(returnType.getName() + " "); System.out.print(method[i].getName() + " "); System.out.print("("); for (int j = 0; j < parameterTypes.length; ++j) { System.out.print(parameterTypes[j].getName() + " " + "arg" + j); if (j < parameterTypes.length - 1) { System.out.print(","); } } //获取异常类型 Class<?> exce[] = method[i].getExceptionTypes(); if (exce.length > 0) { System.out.print(") throws "); for (int k = 0; k < exce.length; ++k) { System.out.print(exce[k].getName() + " "); if (k < exce.length - 1) { System.out.print(","); } } } else { System.out.print(")"); } System.out.println(); } } private String testMethod(int age ,String name) { return name+":"+age; }}
(3)通过反射机制调用某个类的方法
package com.chunsoft.testReflect;import java.lang.reflect.Method;public class TestReflectUse { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.chunsoft.testReflect.TestReflectUse"); // 调用TestReflectUse类中的reflect1方法 Method method = clazz.getMethod("reflect1"); method.invoke(clazz.newInstance()); // Java 反射机制 - 调用某个类的方法1. // 调用TestReflect的reflect2方法 method = clazz.getMethod("reflect2", int.class, String.class); method.invoke(clazz.newInstance(), 20, "张三"); // Java 反射机制 - 调用某个类的方法2. // age -> 20. name -> 张三 } public void reflect1() { System.out.println("Java 反射机制 - 调用某个类的方法1."); } public void reflect2(int age, String name) { System.out.println("Java 反射机制 - 调用某个类的方法2."); System.out.println("age -> " + age + ". name -> " + name); }}
更多用法示例
4、自定义注解
Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在java.lang.annotation 包中。
(1)注解的原理
JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型。该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰的class文件和一个注解处理工具组成。
目前已被广泛应用于各种Java框架,如Hibernate,Jersey,Spring。注解相当于是一种嵌入在程序中的元数据,可以使用注解解析工具或编译器对其进行解析,也可以指定注解在编译期或运行期有效。
元注解是指注解的注解。包括 @Retention @Target @Document @Inherited四种。
(2)创建自定义注解
使用@interface自定义注解时,自动继承java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。
- 自定义注解:
public @interface MyAnnotation {}
- 自定义注解使用
public class AnnotationTest { @MyAnnotation public void execute(){ System.out.println("method"); }}
- 添加变量
public @interface MyAnnotation { String value1();}
当注解中使用的属性名为value时,对其赋值时可以不指定属性的名称而直接写上属性值接口;除了value意外的变量名都需要使用name=value的方式赋值。
- 自定义注解使用
public class AnnotationTest { @MyAnnotation(value1="abc") public void execute(){ System.out.println("method"); }}
@Retention注解可以在定义注解时为编译程序提供注解的保留策略。
CLASS
编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。
RUNTIME
编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
SOURCE
编译器要丢弃的注释。@Target – 表示支持注解的程序元素的种类,一些可能的值有TYPE, METHOD, CONSTRUCTOR, FIELD等。如果Target元注解不存在,那么该注解就可以使用在任何程序元素之上。
Java提供3种内置注解
@Override – 当我们想要覆盖父类的一个方法时,需要使用该注解告知编译器我们正在覆盖一个方法。这样的话,当父类的方法被删除或修改了,编译器会提示错误信息。大家可以学习一下为什么我们总是应该在覆盖方法时使用Java覆盖注解。
@Deprecated – 当我们想要让编译器知道一个方法已经被弃用(deprecate)时,应该使用这个注解。Java推荐在javadoc中提供信息,告知用户为什么这个方法被弃用了,以及替代方法是什么。
@SuppressWarnings – 这个注解仅仅是告知编译器,忽略它们产生了特殊警告,比如:在java泛型中使用原始类型。它的保持性策略(retention policy)是SOURCE,在编译器中将被丢弃。
5、反射和自定义注解结合
大部分java框架的实现通过反射机制和自定义的结合,本文介绍反射和自定义注解的简单结合。
(1)实现自定义注解类
新建Annotation方法,ViewInject.class:
package com.chunsoft.AnnotationTest;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;//自定义注解类@Target(ElementType.FIELD) //用于限制当前自定义注解类的作用的对象//@Retention(RetentionPolicy.SOURCE) //该注解类只会在源码中出现,当将源码编译成注解码时,注解信息就会被清除//@Retention(RetentionPolicy.CLASS) //该注解类会被编译到注解码中,但是当虚拟机加载字节码时,注解信息会被清除@Retention(RetentionPolicy.RUNTIME) //该注解类,永远保留到被加载到虚拟机中public @interface ViewInject { int age(); String name();}
(2)在实体类中使用注解
新建一个实体类并在属性上使用注解,User.class:
package com.chunsoft.AnnotationTest;public class User { @ViewInject(age=21,name="chunsoft") private String name; private int age; private String eat(String eat) { System.out.println("eat:"+eat); return eat + " 真好吃"; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; }}
(3)反射和自定义注解测试
package com.chunsoft.AnnotationTest;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class AnnotationMainTest { public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { //需求:获取User类中name字段上的自定义注解的值, //然后将该值的age通过反射设置给User对象的age属性,将name设置给User对象的name属性 User user = new User(); /** * 1.获取User类的字节码 */// user.getClass();// User.class;// Class.forName(""); Class clazz= User.class; /** * 2.将字节码中的name字段获取到 */// clazz.getField("");//只能获取声明为public的字段 Field declaredField = clazz.getDeclaredField("name"); Field declaredFieldAge = clazz.getDeclaredField("age"); /** * 3.将当前字段上的注解对象获取到 */ ViewInject viewInject = declaredField.getAnnotation(ViewInject.class); if (viewInject != null) { /** * 4.获取自定义注解对象的参数 */ int age = viewInject.age(); String name = viewInject.name(); System.out.println("name="+name+",age="+age); /** * 5.通过反射将这两个值反射给User对象 */ declaredField.setAccessible(true); //设置允许访问,其实就是允许暴力反射 declaredFieldAge.setAccessible(true); //将user对象的declaredField设置为name declaredField.set(user, name); declaredFieldAge.set(user, age); System.out.println(user.toString()); }else { System.out.println("字段上面没有自定义注解"); } //通过反射调用eat对象的方法 Method declaredMethod = clazz.getDeclaredMethod("eat", String.class); //设置允许访问 declaredMethod.setAccessible(true); //暴力反射调用该方法 Object result = declaredMethod.invoke(user, "牛肉拉面"); System.out.println(result); }}
本文简单介绍了java反射机制和自定义注解原理分析和实例,下篇文章将实现基本的ViewUtils基本功能,减少重复编码。
- java反射机制和自定义注解原理分析和实例
- 自定义注解和反射实例
- java反射和自定义注解的使用实例
- Java自定义注解和反射获取注解
- java自定义注解和运行时靠反射机制获取注解
- java注解介绍和自定义注解实例
- Java的反射机制和注解
- Java注解和反射机制(1)
- 巧用java自定义注解和反射
- Java自定义注解和运行时靠反射获取注解
- Java自定义注解和运行时靠反射获取注解
- Java自定义注解和运行时靠反射获取注解
- Java自定义注解和运行时靠反射获取注解
- Java自定义注解和运行时靠反射获取注解
- java 自定义注解annotation和通过反射获取注解
- Java自定义注解和运行时靠反射获取注解
- Java自定义注解和运行时靠反射获取注解
- Java自定义注解和运行时靠反射获取注解
- 新纪元——初识android(Intent)
- leetcode
- idea常用快捷键
- Fragment生命周期小结
- 深大云网络在H5开发中解决IE浏览器的兼容问题
- java反射机制和自定义注解原理分析和实例
- POJ2240 Arbitrage(floyd找正环)
- leetcode
- PHP面向对象:魔术方法__toString()
- 图片防盗链
- JZOJ4994. 棋盘
- java 蓝桥杯 牌型种数
- 我眼中的Linux系统和红帽RHCE认证
- Java基础复习---多态