`

Java 反射机制及Annotation

    博客分类:
  • Java
阅读更多

    Java 反射是 Java 语言的一个很重要的特征。 它允许运行中的 Java 程序对自身进行检查,并能直接操作程序的内部属性。例如,使用 它能获得 Java 类中各成员的名称并显示出来。

       Java 反射机制主要提供了以下功能:

a .在运行时判断任意一个对象所属的类。

b .在运行时构造任意一个类的对象。

c .在运行时判断任意一个类所具有的成员变量和方法。

d .在运行时调用任意一个对象的方法。

JDK 中,主要由以下类来实现 Java 反射机制,这些类在 java.lang.reflect 包中:

Class 类:代表一个类。

Field 类:代表类的成员变量(成员变量也 称为类的属性)。

Method 类:代表类的方法。

Constructor 类:代表类的构造方法。

Array 类:提供了动态创建数组,以及访问数组的元素的静态方法。

   下面写了一个程序:设计了一个 POJO 类。所谓 POJO 类,本人粗浅的理解即和 JavaBean 类似,只有字段和 setter/getter 方法。然后在主函数通过反射,在控制台打印该 POJO 类的所有字段和方法。
    
本人设计的 POJO 类为 WorkerPOJO.java ,然后另一个测试类为 POJOReflection.java ,在 main 函数中负责打印该类的所有字段和方法。程序见下:

WorkerPOJO.java

package com.xpec.landon.trainjava.annotation;
/**
 * POJO类,和JavaBean相似
 * @author lvwenyong
 *
 */
public class WorkerPOJO{
 private String name;
 private int age;
 
 /**
  * 用Annotation修饰
  * @return 姓名
  */
 @WorkerPOJOAnnotation(name = "landon",age = 22)
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }

}

POJOReflection.java

package com.xpec.landon.trainjava.annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Method;


/**
 * 运用Java的反射机制,输出POJO类的字段和方法(新增了Annotation的修饰)
 * @author lvwenyong
 *
 */
public class POJOReflectionTest {
 public static void main(String[] args)
 {
  try
  {
   //加载WorkPOJO,注意这里一定要写全类名,包括包名,因为包名是类名的一部分
   Class pojo = Class.forName("com.xpec.landon.trainjava.annotation.WorkerPOJO");
   //获取域的数组
   Field []fieldList = pojo.getDeclaredFields();
   //获取方法的数组
   Method []methodList = pojo.getDeclaredMethods();
   
   System.out.println("WorkerPOJO类的所有字段:");
   System.out.println("修饰符" + "    " + "类型" + "                   " + "字段名");
   
   for(int i = 0;i < fieldList.length;i++)
   {
    Field field = fieldList[i];
    //用下面的形式获取具体的修饰符
    System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getType() + " " + field.getName());
   }
   
   System.out.println();
   System.out.println("WorkerPOJO类的所有方法(不包括annotation修饰的方法):");
   
   for(int j = 0;j < methodList.length;j++)
   {
    Method method = methodList[j];
    //判断方法是否被Annotation修饰
    boolean methodAnnotation = method.isAnnotationPresent(WorkerPOJOAnnotation.class);
    
    //如果被annotation修饰,则过滤掉该方法,即不输出
    if(methodAnnotation)
    {
     continue;
    }
    //获取方法参数列表
    Class parameters[] = method.getParameterTypes();
    
    System.out.print(Modifier.toString(method.getModifiers()) + " " + method.getReturnType() + " " + method.getName() + " (");
    
    for(int k = 0;k < parameters.length;k++)
    {
     System.out.print(parameters[k].toString());
    }
    
    System.out.println(")");
   }
  }
  catch(ClassNotFoundException exception1)
  {
   exception1.printStackTrace();
  }
  
 }

}
    下面是程序的一个运行截图:



    可以看到,在WorkerPOJO类中引入了Annotation 。 下面,我们详细介绍一下Annotation:
    在使用 JUnit4 中,我们可以看到在每个测试方法前面都有一个 @Test 标记,这就是传说中的 Annotation
    
Annotation 提供了一条与程序元素关联任何信息或者任何元数据( metadata )的途径。从某些方面看, annotation 就像修饰符一样被使用,并应用于包、类型、构造方法、方法、成 员变量、参数、本地变量的声明中。这些信息被存储在 annotation “name=value” 结构对中。 annotation 类型是一种接 口,能够通过 java 反射 API 的方式提供对其信息的访问。
    
annotation 能被用来为某个程序元素(类、方法、成员变量等)关联任何的信 息。需要注意的是,这里存在着一个基本的潜规则: annotaion 不能影响程序代码的执行,无论增加、删除 annotation ,代码都始终如一的执行。另外,尽管一些 annotation 通 过 java 的反射 api 方法在运行时被访问,而 java 语言解释器在工作时忽略了这些 annotation 。正是由于 java 虚拟机忽略了 annotation ,导致了 annotation 类型在代码中是 不起作用 的;只有通过某种配套的工具才会对 annotation 类型中的信息进行访问和处理。
    
 annotation 是与一个程序元素相关联信息或者元数据的标注。它从不影响
ava 程序的执行,但是对例如编译器警告或者像文档生成器等辅助工具产 生影响。
    
我的理解是: Annotation 是继承自 java.lang.annotation.Annotation 的类,用于向程序分析工具或虚拟机提供 package class field methed 等方面的信息,它和其他类没什么区别 , 除了使用方式。
    下面写了一个简单的Annotation:WorkerPOJOAnnotation.java

package com.xpec.landon.trainjava.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 修饰WorkerPOJO类方法的一个Annotation
 * @author lvwenyong
 *
 */

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WorkerPOJOAnnotation {
 String name();
 int age();

}

    其 中 @Target 里面的 ElementType 是用来指定 Annotation 类型可以用在哪一些元素上的,包括 TYPE (类型), METHOD (方法), FIELD (字段), PARAMETER (参数)等。其中 TYPE 是指可以用在 Class,Interface 等类型上。下面给出用 jad 反编译 出的 ElementType 中的静态变量的截图:

    另外 @Retention 中的 RetentionPolicy 是指 Annotation 中的信息保留方式, 分别是 SOURCE,CLASS RUNTIME. SOURCE 代表的是这个 Annotation 类型的信息只会保留在程序源码里,源码如果经过了编译之后, Annotation 的数据就会消失 , 并不会保留在编译好的 .class 文件里面。 ClASS 的意思是这个 Annotation 类型的信息保留在程序源码里 , 同时也会保留在编译好的 .class 文件里面 , 在执行的时候,并不会把这一些信息加载到虚拟机 (JVM) 中去 . 注意一下,当你没有设定一个 Annotation 类型的 Retention 值时,系统默认值是 CLASS. 第三个 , RUNTIME, 表示在源码、编译好的 .class 文件中保留信息,在执行的时候会把这一些信息加载到 JVM 中去的.
    下面给出用 jad 反编译出的 RetentionPolicy 中的静态变量的截图
    
    最后的一个 Annotation@Documented 是指目的就是让这一个 Annotation 类型的信息能够显示在 Java API 说明文档上。

    下面将上面自己设计的 WorkerPOJOAnnotation 应用在了 WorkerPOJO 类的一个方法前面:
    然后在控制台输出了没有被 Annotation 注释的字段和方法,运行后可以看到不包括 getName 方法。
    最后我们可以用Junit4 书写一个测试用例: POJOReflectionJunit4Test .java

package com.xpec.landon.trainjava.annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import javax.activation.FileDataSource;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * 关于Java反射以及Annotation的一个TestCase
 * @author lvwenyong
 *
 */

public class POJOReflectionJunit4Test {
 private Class pojo;
 private Field []fieldList;
 private Method[] methodList;

 @Before
 public void setUp() throws Exception {
  //加载类WorkPOJO
  pojo = Class.forName("com.xpec.landon.trainjava.annotation.WorkerPOJO");
  //获取域的数组
  fieldList = pojo.getDeclaredFields();
  //获取方法的数组
  methodList = pojo.getDeclaredMethods();
 }
 
 //测试字段和方法的个数
 @Test
 public void testSize()
 {
  Assert.assertEquals(2, fieldList.length);
  Assert.assertEquals(4, methodList.length);
 }

 //测试字段是否带有annotations
 @Test
 public void isFieldAnnotation()
 {
  for(int i = 0;i < fieldList.length;i++)
  {
   Assert.assertEquals(false, fieldList[i].isAnnotationPresent(WorkerPOJOAnnotation.class));
  }
 }
 
 //测试方法是否带有annotations
 @Test
 public void isMethodAnnotation()
 {
  for(int i = 0;i < methodList.length;i++)
  {
   Assert.assertEquals(false, methodList[i].isAnnotationPresent(WorkerPOJOAnnotation.class));
  }
 }
 
 @After
 public void tearDown() throws Exception {
 }

}

分享到:
评论
2 楼 zxk7516 2015-02-11  
sdFASFDSADFSADFASDFA
[color=brown][/color]
1 楼 zxk7516 2015-02-11  
[color=yellow][/color]zxvcxvzxcvXVxzVCXzx

相关推荐

    通过Java annotation以及反射机制实现不同类型通用的数据库访问接口

    NULL 博文链接:https://mypyg.iteye.com/blog/849176

    Java反射机制重点总结

    文章目录Java ReflectionJava反射机制提供的功能Java反射相关的主要APIjava.lang.Class类Class类的核心要点Class类的重要API实例实例化Class类对象(四种方法)创建类对象并获取类的完整结构获取Class对象后创建类的...

    java开发实战经典(名师讲坛)-李兴华-扫描版

    这本书从初学者的角度,以丰富的实例、案例,通俗易懂的语言,简单的...需要理解或掌握的多线程、泛型、枚举、Java反射机制、Annotation、Eclipse开发工具;需要了解或掌握的图形界面、Java网络编程、Java新IO等内容。

    J2SE笔记讲解个人修订(1.1).docx

    5 JAVA反射机制 6 JAVA注解(ANNOTATION) 7 JAVA中的异常类 8 JAVA-SWING 9 观察者模式 10 内部类讲解 11 JAVA I/O流讲解 12 JAVA多线程 13 JAVA网络通信 14 JAVA类加载器CLASSLOADER 15 JAVA简单工厂...

    java高手真经 光盘源码

    java高手真经 全光盘源代码 打包rar ...javareflection.zip 26.Java反射机制与动态代理 javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性

    Java高手真经(编程基础卷)光盘全部源码 免积分

    看到那些要积分的很不酸,发布免费版本。...javareflection.zip 26.Java反射机制与动态代理 javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性

    java高级特性,涵盖了多种java常用的一些例子

    反射机制 在运行状态中,对于任意一个类能够获取类中的所有属性和方法,对于任意一个对象能够调用对象中的属性和方法,这种动态获取属性和方法的机制:反射。 设计模式1(单例,工厂) 设计模式2(观察者,适配器)...

    Java高手真经(编程基础卷)光盘全部源码

    看到很多人都分卷打包的,下载很是不方便,还浪费积分...javareflection.zip 26.Java反射机制与动态代理 javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性

    Java开发详解.zip

    031504_【第15章:Java反射机制】_Java反射机制的深入研究笔记.pdf 031505_【第15章:Java反射机制】_动态代理笔记.pdf 031506_【第15章:Java反射机制】_工厂设计模式笔记.pdf 031601_【第16章:Annotation】_系统...

    java进阶技术:泛型、反射、注解

    JAVA反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对以后学习框架有很大的帮助。注解(Annotation)是JDK1.5及以后引入的新特性,与类、接口、枚举是在同一个层次。可声明在包、类、字段、方法、局部...

    java或Java框架中常用的注解及其作用详解_资料.docx

    java或Java框架中常用的注解及其作用详解:Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过...

    JAVA_API1.6文档(中文)

    java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java....

    Java 1.6 API 中文 New

    java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java.nio ...

    想自己写框架?不了解Java注解(Annotation)机制可不行,来跟我一起通过源码深入Java注解机制

    注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行...

    AnnotationDemo

    该demo 主要通过java注解功能和反射机制 来仿xtuils 的数据库功能 和findViewByID 功能

    JavaAPI1.6中文chm文档 part1

    java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java....

    java api最新7.0

    java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java.nio ...

    MLDN魔乐所有javaSE的pdf文档

    MLDN魔乐所有javaSE的pdf文档,文档编号是从5开始的,因为前面讲的是Oracle的东西...16.1.Java反射机制.pdf 16.2.枚举.pdf 17.1.Annotation.pdf 17.2.Java数据库编程.pdf 17.3.Java网络编程.pdf 18.JAVA项目案例.pdf

Global site tag (gtag.js) - Google Analytics