`

6、java反射机制与注解

    博客分类:
  • java
阅读更多
反射,reflection,听其名就像照镜子一样,可以看见自己也可以看见别人。在java语言中这是一个很重要的特性。下面是来自sun公司官网关于反射的介绍:
Html代码  收藏代码
Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect(内省)" upon itself, and manipulate(操作) internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them. 
The ability to examine and manipulate a Java class from within itself may not sound like very much, but in other programming languages this feature simply doesn't exist. For example, there is no way in a Pascal, C, or C++ program to obtain information about the functions defined within that program. 
One tangible(实际的) use of reflection is in JavaBeans, where software components can be manipulated visually via(通过) a builder tool. The tool uses reflection to obtain the properties of Java components (classes) as they are dynamically loaded. 
反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。这种能自我检查和操作内部属性的java类我们不常看到,但是在其他的比如C或者C++语言中很不就存在这个特性。像Pascal、C、C++无法获得内部方法的任何信息;一个实际运用是在JavaBean中,通过一个构造工具操作javaBean的各个组件,这个构造工具就是运用反射功能在javaBean动态加载时来获取他的属性。 

先看看Class的构造器:
Java代码  收藏代码
/*
* Constructor. Only the Java Virtual Machine creates Class
*/ 
private Class() {} 
注释很明确的告诉了我们,这个类是有JVM来创建的,所以我们就不用麻烦了。如果我们拿到一个类的类型信息,就可以利用反射获取其各种成员以及方法了。(注:Class 从JDK1.5版本后就开始更多为泛型服务了)那么我们怎么拿到一个类型的信息呢?假设我们有一个Role类:
Java代码  收藏代码
package org.Smart; 
   /*
    * a class Role has some methods and attribute
    */ 
public class Role { 
    public Role(){} 
    public Role(String s){} 
    private String s; 
    private int x; 
    public void fun1(String s){ 
    System.out.println(s); 
    } 
    public  void  fun2(){ 
        System.out.println("ok"); 
    } 

测试:
Java代码  收藏代码
public class Sample {  
    @SuppressWarnings("rawtypes") 
    public static void main(String...s)  { 
        Class c=Role.class; 
        Method[] m=c.getDeclaredMethods(); 
        for(int x=0;x<m.length;x++){ 
            System.out.println(m.toString()); 
        } 
    } 


获得Class 实例的几种方式:
Java代码  收藏代码
Class cls1 = Role.class; 
Class cls2 = Class.forName("org.Smart.Role"); 
Role r=new Role(); 
Class cls3=r.getClass(); 
Class cls4= Boolean.TYPE;  //仅适用基本数据类的包装类 
注意第二种方式中,forName中的参数一定是完整的类名(包名+类名),并且这个方法需要捕获异常。现在得到cls1就可以创建一个Role类的实例了,利用Class的newInstance方法相当于调用类的默认的构造器
Java代码  收藏代码
Class c; 
try { 
     c = Class.forName("org.Smart.Role"); 
     Role r=(Role) c.newInstance();        //等同Role r=new Role();利用newInstance()理解为Role的无参构造方法 
     r.fun2(); 
} catch (ClassNotFoundException e) { 
     e.printStackTrace(); 

获得构造器:getConstructors/getDeclaredConstructors  (不含私有/含私有)并可以设置为私有或公有的
获得属性:getFields/getDeclaredFields
获得方法:getMethods/getDeclaredMethods

调用类的方法:
Java代码  收藏代码
Class c= Role.class; 
        Object obj=c.newInstance(); 
        Method fun=c.getDeclaredMethod("fun1", String.class); //若方法fun1没有参数写null,有参数写入参数类型 
        fun.invoke(obj, "e");//没有参数写null,有参数传参数值 
设置属性值:
Java代码  收藏代码
Field f=c.getDeclaredField("x"); 
f.setInt(obj, 32); //int x;必须是public声明的,setInt与int型对应; 
讲到这里使用了java.lang.reflect包中的Method/Field/Constructor类,这些类都是接收Class.get()获得的方法/属性/构造器,还有一个最重要的运用:jvm核心之一Proxy代理,将在下章内容中讲解;
Class的其他重要方法:
Java代码  收藏代码
static Class<?>                 forName(String name, boolean initialize, ClassLoader loader) //Class内部方法 
static Class<?>                 forName(String className)//外部调用方法 
<A extends Annotation>A       getAnnotation(Class<A> annotationClass) 
Annotation[]                  getAnnotations() 
ClassLoader               getClassLoader()//获取类加载器 
Class<?>[]                  getInterfaces() //获取接口 
String                        getName()//获取类名 
Package                   getPackage()  //获取包类型 
Class<? super T>        getSuperclass()//获取父类 

下面接着讲注解:
JDK 5中引入了源代码中的注解(annotation)这一机制。注解使得Java源代码中不但可以包含功能性的实现代码,还可以添加元数据。注解的功能类似于代码中的注释,所不同的是注解不是提供代码功能的说明,而是实现程序功能的重要组成部分。Java注解已经在很多框架中得到了广泛的使用,用来简化程序中的配置。

java注解又叫java标注,java提供了一套机制,使得我们可以对方法、类、参数、包、域以及变量等添加标准(即附上某些信息)。且在以后某个时段通过反射将标注的信息提取出来以供使用。
Java从1.5版本以后默认内置三个标注:
@Override:只能用在方法之上的,用来告诉别人这一个方法是改写父类的。
@Deprecated:建议别人不要使用旧的API的时候用的,编译的时候会用产生警告信息,可以设定在程序里的所有的元素上.
@SuppressWarnings:这一个类型可以来暂时把一些警告信息消息关闭.
但是,仅仅这三个标注是不能满足我们开发时一些需求的。所以java允许我们自定义注解来使用。

从某种角度来说,可以把注解看成是一个XML元素,该元素可以有不同的预定义的属性。而属性的值是可以在声明该元素的时候自行指定的。在代码中使用注解,就相当于把一部分元数据从XML文件移到了代码本身之中,在一个地方管理和维护。

如何自己设计一个注解?
先看一下rt.jar下面的java.lang.annotation包:
Target.class
Java代码  收藏代码
@Documented 
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.ANNOTATION_TYPE) 
public @interface Target {        //@Target自己用自己来声明自己,只能用在ANNOTATION_TYPE之上 
    ElementType[] value(); 

  //Java中提供了四种元注解,专门负责注解其他的注解,分别如下 
  //@Documented将注解包含在JavaDoc中32  public @interface Documented { 
  //@Inheried允许子类继承父类中的注解      
  //@Retention元注解,表示保存在什地方。可选的RetentionPoicy参数包括:public @interface Retention{    
  //RetentionPolicy.SOURCE: 停留在java源文件,编译器被丢掉  public enum RetentionPolicy { 
  //RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认) 
  //RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解,因此可以通过反射机制读取注解的信息 
 
  //@Target元注解,表示使用在什么地方。可用的ElementType参数包括     
  //ElementType.CONSTRUCTOR: 构造器声明   public enum ElementType { 
  //ElementType.FIELD: 成员变量、对象、属性(包括enum实例) 
  //ElementType.LOCAL_VARIABLE: 局部变量声明 
  //ElementType.METHOD: 方法声明 
  //ElementType.PACKAGE: 包声明 
  //ElementType.PARAMETER: 参数声明 
  //ElementType.TYPE: 类、接口(包括注解类型)或enum声明        
   //ElementType.ANNOTATION_TYPE  Annotation type declaration 
   @interface是一个关键字,在设计注解的时候必须把一个类型定义为@interface,而不能用class或interface关键字,@Retention用来声明注解的保留策略,有CLASS、RUNTIME和SOURCE这三种属性,分别表示注解保存在字节码.class文件、JVM运行时刻和源代码.java文件中。只有当声明为RUNTIME时,才能通过反射机制获取到注解信息。@Target用来声明注解可以添加哪些元素类型;
    SOURCE代表的是这个Annotation类型的信息只会保留在程序源码里,源码如果经过了编译之后,Annotation的数据就会消失,并不会保留在编译好的.class文件里面。
    ClASS的意思是这个Annotation类型的信息保留在程序源码里,同时也会保留在编译好的.class文件里面,在执行的时候,并不会把这一些信息加载到虚拟机(JVM)中去.注意一下,当你没有设定一个Annotation类型的Retention值时,系统默认值是CLASS.
     RUNTIME,表示在源码、编译好的.class文件中保留信息,在执行的时候会把这一些信息加载到JVM中去的.
   @Documented的目的就是让这一个Annotation类型的信息能够显示在javaAPI说明文档上;没有添加的话,使用javadoc生成API文档的时候就会找不到这一个类型生成的信息.
   如果需要把Annotation的数据继承给子类,那么就会用到@Inherited这一个Annotation类型.
我们在来看下@Override注解:
Java代码  收藏代码
@Target(ElementType.METHOD)      
@Retention(RetentionPolicy.SOURCE) 
public @interface Override { 

从上面可以得出:该注解只能在方法前使用,保存在源代码中,不会把@T...@R保存在.class文件中,但是通过反编译还是会打印出这两个注解?

使用@Override的时候只需要一个声明即可,而没有传递参数,称为标记注解(marker annotation ),代表某种配置语义。
使用@SuppressWarnings("xxxtype"),里面传递了一个参数;其实里面是一个名值对语句:value="xxxtype",省略了value=这个字符串;

所有的Annotation会自动继承java.lang.annotation这一个接口,所以不能再去继承别的类或是接口. ;只能用public或默认(default)这两个访问权限声明这个注解类;方法的返回值只能是基本类型(与注解传来的参数相接)byte,short,char,int,long,float,double,boolean和String,Enum,Class,annotations等数据类型,以及这一些类型的数组;如果只有一个成员变量,最好把变量名称设为"value",后加括号 String value(),这样注解时可以省略value这个字段,形式上是一个无参方法;多个成员变量后面都要加(),像int x();

自己设计一个Description注解类:
Java代码  收藏代码
@Target(ElementType.TYPE)  //使用在类前,注意后面没有;分号 
@Retention(RetentionPolicy.RUNTIME)  //保证在jvm中 
public @interface Description { 
    String info(); 
    String str(); 

使用Description注解:
Java代码  收藏代码
@Description(info="skx",str="good name!!") 
public class UseDescription { 

查看注解:

Java代码  收藏代码
Class c=UseDescription.class; 
//获取UseDescription里面的@Description注解 
Description obj=(Description) c.getAnnotation(Description.class); 
//获取Description.info方法的返回值 
System.out.println(obj.info());  //skx 
分享到:
评论

相关推荐

    java注解、java反射机制 jdbc 封装

    接着,我们来看Java反射机制。反射允许程序在运行时检查类、接口、字段和方法的信息,甚至可以动态调用方法和访问字段。在JDBC封装中,反射非常有用,因为它允许在运行时创建和执行SQL语句,而不必在代码中硬编码...

    Java自定义注解使用反射获取字段注解

    总结一下,Java的自定义注解结合反射机制,为我们提供了强大的元数据功能,可以用来增强代码的可读性、可维护性,甚至实现一些动态的功能。在实际开发中,自定义注解常用于框架的实现、AOP切面编程、配置管理等领域...

    Java学习资料-反射机制和注解

    总结来说,Java的反射机制和注解是两种强大的工具,它们增强了代码的动态性和元数据功能。在设计和实现复杂系统时,正确地运用这些特性可以提高代码的灵活性和可维护性,但也需要注意潜在的性能和安全性问题。在实际...

    Java反射机制的实现_Reflection

    Java反射机制还涉及到注解处理,可以使用`Annotation`接口及其子类来获取和处理类、方法、字段上的注解信息。这对于实现元编程、AOP(面向切面编程)和自定义注解处理器非常有用。 总的来说,Java反射机制为程序员...

    一个例子让你了解Java反射机制

    通过8个demo,你可以逐步深入理解Java反射机制,从简单的获取类信息,到创建对象,调用方法,访问字段,再到处理注解和泛型,全方位掌握这一强大的工具。每个demo都应该设计为解决一个特定的问题,例如如何动态调用...

    java 反射机制详解

    Java 反射机制是 Java 语言中的一个重要特性,它允许程序在运行时动态地获取类的信息(如类名、属性、方法等)并调用对象的方法,甚至修改对象的状态。这一机制极大地增强了 Java 程序的灵活性和可扩展性,尤其是在...

    北大青鸟java反射机制

    此外,Java反射机制也广泛应用于注解处理。`Annotation`接口代表了类、方法、字段等上的注解。我们可以使用`isAnnotationPresent(Class&lt;? extends Annotation&gt; annotationClass)`检查是否存在特定注解,`...

    java反射机制原理和反射机制总结

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段以及方法等对象。这一机制的核心在于`java.lang.Class`类和相关的API,它们提供了对类元数据的访问,使得我们能够在运行时...

    java反射机制工具类

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息。这个特性使得Java具备了高度的灵活性,能够在运行时动态地发现和使用类的属性和方法,即使这些信息在编译时...

    java反射机制文档及代码

    Java反射机制是Java编程语言中一个强大的特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这个特性使得Java具有了高度的灵活性和动态性,尤其是在处理元数据、创建对象、调用方法以及...

    一种基于Java注解和反射机制的Excel文件读写操作方法.pdf

    2. Java反射机制的应用:Java反射机制允许在运行时动态访问和修改类的行为。通过反射,可以得到类的成员变量、方法、构造器等信息,甚至可以调用这些成员。在处理Excel文件时,反射机制可以动态地根据Excel文件中...

    实战java反射机制-让你迅速认识java强大的反射机制

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息,甚至动态地创建对象并调用其方法。通过反射,开发者可以实现高度灵活和动态的代码,这对于框架开发、元编程...

    Java反射机制源码

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部结构。通过反射,开发者可以动态地创建对象、调用方法、访问字段,甚至修改私有成员,这为实现元编程和框架设计...

    Java反射机制的学习

    Java反射机制是Java编程语言中的一项核心特性,它允许程序在运行时动态地获取类的信息并进行操作。这使得Java能够在编译后仍然能够灵活地处理类和对象,增强了代码的动态性。在Android应用开发中,反射机制尤其重要...

    利用java反射、注解及泛型模拟ORM实现

    1. 反射(Reflection):Java反射机制允许程序在运行时动态地获取类的信息(如类名、方法名、参数类型等)并调用其方法。通过`Class`类,我们可以实例化未知类型的对象,调用私有方法,访问私有字段,以及检查类的...

    Java反射机制(推荐)

    Java反射机制是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这种能力使得Java开发者能够在运行时动态地获取类的信息(如类名、方法名、参数类型等)并调用...

    通过Java反射机制获取JavaBean对象

    1.通过Java反射机制获取JavaBean对象。 2.通过JavaBean全路径字符串获取JavaBean对象。 3.获取JavaBean注解信息

    Java反射机制学习总结

    Java反射机制是Java编程语言中一个强大的工具,它允许程序在运行时动态地获取类的信息并操作类的对象。反射机制的核心在于java.lang.reflect包中的API,主要包括Class类、Constructor类、Method类和Field类。以下是...

    基于Java反射机制的POI实现Excel数据导入_导出.pdf

    该技术通过采用Java反射机制和自定义注解原理,实现了数据库与Excel文件之间的数据交互。这样不仅能保证数据导入的完整性,同时也能避免数据导出后重新编辑的复杂性,从而提高POI实现Excel数据导入和导出的灵活性、...

Global site tag (gtag.js) - Google Analytics