java反射和注解

原创 2015年11月20日 18:50:43

ReflectionAndAnnotation

本文讲解java的 Reflect、Annotation 反射 和 注解的使用
文中的测试代码请前往 ReflectAndAnnotation

反射


java的反射机制运行程序在运行时通过反射的APIs取得class的内部信息。
关于反射的文字的说明可以看另一篇博文http://blog.csdn.net/renyuanchunby/article/details/7052895

本文主要从应用的角度讲解反射。

先写一个Bean类,定义int型的age, String name, List beans。

package com.example.dj.reflectandannotation;

import java.util.List;

/**
 * @author DragonJiang
 * @date 2015/11/16
 * @Description:
 */
public class Bean {
    private int age;

    public String name;

    List<Bean> beans;

    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;
    }

    public List<Bean> getBeans() {
        return beans;
    }

    public void setBeans(List<Bean> beans) {
        this.beans = beans;
    }

    @Override
    public String toString() {
        return "name = " + name + ", age = " + age;
    }
}

然后在BeanTest类进行测试:

package com.example.dj.reflectandannotation;

import android.util.Log;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author DragonJiang
 * @date 2015/11/16
 * @Description:
 */
public class BeanTest {

    private static final String TAG = "BeanTest";

    public static void testBean(){
        //定义一个bean的实体,然后初始化
        Bean bean = new Bean();
        List<Bean> beans = new ArrayList<>();
        beans.add(bean);
        bean.setAge(12);
        bean.setName("dragon");
        bean.setBeans(beans);

        Class clazz = bean.getClass();//取得类的对象

        Field[]  fields = clazz.getDeclaredFields();//取得类中所有属性的集合

        try {
            for (Field field : fields) {
                if (!field.isAccessible()) {//如果这些属性是不可访问的,设为可访问
                    field.setAccessible(true);
                }

                Class fieldType = field.getType();//取得该属性的类型
                String strType = fieldType.toString();

                if(int.class.isAssignableFrom(fieldType)){//判断该属性是否int类型,取得属性值
                    int i = (int) field.get(bean);
                    Log.d(TAG, strType + ", " + field.getName() + " = "+ i);

                } else if(String.class.isAssignableFrom(fieldType)){//判断该属性是否String类型,取得属性值
                    String s = (String) field.get(bean);
                    Log.d(TAG, strType + ", " + field.getName() + " = "+ s);

                } else if(List.class.isAssignableFrom(fieldType)){//判断该属性是否List类型,如果是,取得List的参数类型
                    Type type = field.getGenericType();//取得该属性的参数类型

                    if(type instanceof ParameterizedType){
                        Class itemClazz = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];//取得list的实际参数类型

                        if(Bean.class.isAssignableFrom(itemClazz)){//判断类型是否Bean类型
                            List list = (List) field.get(bean);//取得List
                            Iterator it = list.iterator();
                            while (it.hasNext()){
                                Bean b = (Bean) it.next();//取得Bean
                                Log.d(TAG, strType + ", " + field.getName() + "; itemType = "
                                        + itemClazz.getSimpleName() + ", value : " + b.toString());
                            }
                        }
                    }

                }
            }

        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

运行BeanTest.testBean();
打印出来的log如下:

11-20 11:23:34.750 7652-7652/? D/BeanTest: class java.lang.String, name = dragon
11-20 11:23:34.750 7652-7652/? D/BeanTest: interface java.util.List, beans; itemType = Bean, value : name = dragon, age = 12
11-20 11:23:34.750 7652-7652/? D/BeanTest: int, age = 12

通过反射分别取到了Bean定义的三个属性值。举一反三可以同样的用反射调用类内部的方法。

注解


注解在安卓的开发中可以提供很大的便利。

注解有元注解、自定义注解。元注解是的作用就是注解其他注解。
关于注解的说明可以看另一篇博文:http://blog.csdn.net/longlongxy/article/details/44414237

定义三个注解类,分别是类注解、方法注解、属性注解

类注解:

package com.example.dj.reflectandannotation.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author DragonJiang
 * @date 2015/11/16
 * @Description:
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAnnotation {
}

方法注解:

package com.example.dj.reflectandannotation.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author DragonJiang
 * @date 2015/11/16
 * @Description:
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodAnnotation {
}

属性注解:(注解可以带有参数,相比前两个注解,属性注解增加了一个参数,用于测试带参数的注解)

package com.example.dj.reflectandannotation.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author DragonJiang
 * @date 2015/11/16
 * @Description:
 */

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnnotation {
    /**
     * 注解的参数privacyType的值。
     */
    int PRIVACY = 0;      //隐私的属性
    int PUBLIC = 1;       //公开的属性

    int privacyType() default PRIVACY;
}

然后对Bean类进行修改,增加注解:

package com.example.dj.reflectandannotation;

import com.example.dj.reflectandannotation.annotation.ClassAnnotation;
import com.example.dj.reflectandannotation.annotation.FieldAnnotation;
import com.example.dj.reflectandannotation.annotation.MethodAnnotation;

import java.util.List;

/**
 * @author DragonJiang
 * @date 2015/11/16
 * @Description:
 */
@ClassAnnotation
public class Bean {
    @FieldAnnotation(privacyType = FieldAnnotation.PRIVACY)
    private int age;

    @FieldAnnotation(privacyType = FieldAnnotation.PUBLIC)
    public String name;

    @FieldAnnotation(privacyType = FieldAnnotation.PRIVACY)
    List<Bean> beans;

    public int getAge() {
        return age;
    }

    @MethodAnnotation
    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Bean> getBeans() {
        return beans;
    }

    public void setBeans(List<Bean> beans) {
        this.beans = beans;
    }

    @Override
    public String toString() {
        return "name = " + name + ", age = " + age;
    }
}

在AnnotationTest类解析注解:

package com.example.dj.reflectandannotation;

import android.util.Log;

import com.example.dj.reflectandannotation.annotation.ClassAnnotation;
import com.example.dj.reflectandannotation.annotation.FieldAnnotation;
import com.example.dj.reflectandannotation.annotation.MethodAnnotation;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author DragonJiang
 * @date 2015/11/16
 * @Description:
 */
public class AnnotationTest {
    private static final String TAG = "AnnotationTest";

    public static void testAnnotation(){
        Bean bean = new Bean();
        List<Bean> beans = new ArrayList<>();
        beans.add(bean);
        bean.setAge(12);
        bean.setName("dragon");
        bean.setBeans(beans);

        //类注解
        Class clazz = bean.getClass();//取得类的对象
        ClassAnnotation ca = (ClassAnnotation) clazz.getAnnotation(ClassAnnotation.class);//取类的注解
        if(ca != null) {
            Log.d(TAG, "the class "+ clazz.getSimpleName() + " has ClassAnnotation : " + ca.toString());//打印注解
        }

        //方法注解
        Method[] methods = clazz.getDeclaredMethods();
        for(Method method : methods){
            MethodAnnotation ma = method.getAnnotation(MethodAnnotation.class);
            if(ma != null){
                Log.d(TAG, "the method " + method.getName() + " has MethodAnnotation : " + ma.toString());//打印注解
            }
        }

        //属性注解
        Field[]  fields = clazz.getDeclaredFields();//取得类中所有属性的集合
        for (Field field : fields) {
            FieldAnnotation fa = field.getAnnotation(FieldAnnotation.class);
            if(fa == null){
                continue;
            }

            int privacyType = fa.privacyType();
            if(privacyType == FieldAnnotation.PRIVACY){
                Log.d(TAG, field.getName() + " has FieldAnnotation : " + "privacyType == FieldAnnotation.PRIVACY");
            } else {
                Log.d(TAG, field.getName() + " has FieldAnnotation : " + "privacyType == FieldAnnotation.PUBLIC");
            }
        }
    }
}

运行AnnotationTest.testAnnotation();打印log:

11-20 11:23:34.750 7652-7652/? D/AnnotationTest: the class Bean has ClassAnnotation : @com.example.dj.reflectandannotation.annotation.ClassAnnotation()
11-20 11:23:34.750 7652-7652/? D/AnnotationTest: the method setAge has MethodAnnotation : @com.example.dj.reflectandannotation.annotation.MethodAnnotation()
11-20 11:23:34.754 7652-7652/? D/AnnotationTest: name has FieldAnnotation : privacyType == FieldAnnotation.PUBLIC
11-20 11:23:34.754 7652-7652/? D/AnnotationTest: beans has FieldAnnotation : privacyType == FieldAnnotation.PRIVACY
11-20 11:23:34.754 7652-7652/? D/AnnotationTest: age has FieldAnnotation : privacyType == FieldAnnotation.PRIVACY

java 通过反射获取注解

有的时候我们想使用反射获取某个类的注释、方法上的注释、属性上的注释。 package com.mine.practice.reflectfield; import java.lang.an...
  • Mrzhang0419
  • Mrzhang0419
  • 2016年07月14日 10:12
  • 2677

java自定义注解和运行时靠反射机制获取注解

java自定义注解:java注解是附加在代码上的一些元信息,用于一些工具在编译,运行时进行解析和使用,起到说明配置的功能。注解不会也不能影响代码的实际逻辑,只起到辅助的作用,包含在java.lang....
  • LoveStudy_girl
  • LoveStudy_girl
  • 2016年06月22日 14:03
  • 1089

java机制学习——反射,注解,代理,泛型

java机制——反射,注解,代理,泛型
  • hdkjdhdj
  • hdkjdhdj
  • 2016年11月08日 15:17
  • 627

Java自定义注解和运行时靠反射获取注解

java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。 注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在 jav...
  • bao19901210
  • bao19901210
  • 2013年12月08日 16:05
  • 122080

利用反射获取类或者方法或者字段上的注解的值

从JDK1.5之后,注解在各大框架上得到了广泛的应用。下面这个例子中,你可以判断一个类或者方法或者字段上有没有注解,以及怎么获取上面的注解值。话不多说,代码如下: AnnotationTest01.j...
  • zknxx
  • zknxx
  • 2016年05月26日 23:34
  • 8051

Java之反射、枚举、内省、注解

一:反射技术:          1.概述:其实就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,                        并将字节码文件中的内容...
  • AlanHand
  • AlanHand
  • 2014年09月02日 00:49
  • 1852

Java注解详解,自定义注解,利用反射解析注解

概要这篇文章将会带领你了解Java注解,注解的使用,注解的解析,利用反射解析运行时注解,相信有一定Java基础的小伙伴一定会接触大量的注解,Spring , Hibernate , MyBatis等著...
  • yangjizhao
  • yangjizhao
  • 2016年05月13日 23:04
  • 4503

Java使用反射和注解实现参数校验

使用场景: 保存对象之前都要进行参数校验,例如非空校验,长度校验等,一个个字段来校验的话非常繁琐,使用注解可以灵活的进行参数校验。 直接上代码了 /** * 用于校验前端传输的...
  • hzx_abge
  • hzx_abge
  • 2017年05月09日 17:00
  • 885

Java序列化,反射,注解(一)

序列化: 什么是序列化,为什么要做序列化,考虑一种场景,考虑这种应用发生在要对一个对象做永久性保存的时候, 可以把它保存到电脑磁盘,也可以保存到数据库。而在你需要用到这个对象的时候可以从磁盘或数据库...
  • chaogu94
  • chaogu94
  • 2016年09月02日 17:43
  • 1188

Android框架常用java基础知识:反射,注解,动态代理

Android框架常用java基础知识:反射,注解,动态代理 在学习Android的框架的源码的时候,发现大部分框架中都是有对java机制的灵活应用。常见的反射,代理,动态代理,注解...
  • qyl10241024
  • qyl10241024
  • 2015年10月30日 21:40
  • 784
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java反射和注解
举报原因:
原因补充:

(最多只允许输入30个字)