欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

reflect反射 & Annotation注解,

来源: javaer 分享于  点击 9739 次 点评:187

reflect反射 & Annotation注解,


类加载器的基本概念:

         类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机
使用 Java 类的方式如下:Java 源程序(.java )在经过 Java 编译器编译之后就被转换成
Java 字节代码(.class )。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类
的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就
可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工
具动态生成的,也可能是通过网络下载的。

 

Java反射机制定义:

        Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调
用对象的方法的功能称为java语言的反射机制。

 

Java 反射机制的功能:

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

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

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

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

5.生成动态代理。

 

Java 反射机制的应用场景:

1.逆向代码 ,例如反编译

2.与注解相结合的框架 例如Retrofit

3.单纯的反射机制应用框架 例如EventBus

4.动态生成类框架 例如Gson

常见的注解:

注解的概念是在jdk5.0中提出来的,在java.lang的包中已经定义了三个注解:

Override,Deprecated,SuppressWarnings

Override相信大家非常熟悉,就是表明这个方法是改写了父类的方法,重写

Deprecated表示在新版本的 jdk中已经不建议使用这个方法或者属性,不建议使用

SuppressWarning就是屏蔽掉一些警告,压制警告

 

注解的概念:

        注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的
一部分。注解对于代码的运行效果没有直接影响。

 

注解有许多用处,主要如下:

- 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息
- 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它
        相应处理。
- 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取

 

元注解:

    元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它
的注解上面。

    如果难于理解的话,你可以这样理解。元注解也是一张标签,但是它是一张特殊的标签,它
的作用和目的就是给其他普通的标签进行解释说明的。

元标签有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5种。
                保留、            文档、                目标、        继承、        可重复的

 

@Retention注解的三种取值

- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM中,所以在      程序运行时可以获取到它们。

@Target注解的取值

ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造方法进行注解
ElementType.FIELD 可以给属性进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法内的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

@Inherited注解的用法

    注解 TestInherited 被 @Inherited 修饰,之后类 A 被 TestInherited 注解,类 B继承 A,类 B 也拥有 TestInherited 这个注解。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER,
TYPE})
public @interface Deprecated {
}

元注解:

Target注解的功能就是表明你这个注解是用在什么地方的,它的值是一个枚举型

           1.CONSTRUCTOR:用于描述构造器

    2.FIELD:用于描述域

    3.LOCAL_VARIABLE:用于描述局部变量

    4.METHOD:用于描述方法

    5.PACKAGE:用于描述包

    6.PARAMETER:用于描述参数

    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

 

Retention注解的功能差不多说明的就是你的注解的生命周期吧,就是什么时候失效,它的值如下

              1.SOURCE:在源文件中有效(即源文件保留)

    2.CLASS:在class文件中有效(即class保留)

    3.RUNTIME:在运行时有效(即运行时保留)

注解的属性:

        注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义
中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该
成员变量的类型。

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interfaceTestAnnotation{
    int id();
    String msg();
}

意思是: TestAnnotation 这个注解中拥有 id 和 msg 两个属性。在使用的时候,我们应该给它们进行赋值。

Android中通过注解FindViewByID:自定义模仿ButterKnife(通过反射、注解的方式绑定控件)

 

自定义ButterKnife注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindView {
    @IdRes int value() default View.NO_ID;
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindString {
    @StringRes int value() default View.NO_ID;
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnClick {
    @IdRes int[] value();
}
public class ButterKnife {

    public static void bind(final Activity activity) {
        // 1. 拿到类模板
        Class<Activity> clazz = (Class<Activity>) activity.getClass();
        // 2. 拿到所有的属性
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            // 判断是否被对应的注解修饰
            if (field.isAnnotationPresent(BindView.class)) {
                // 拿到修饰该属性的注解
                BindView bindView = field.getAnnotation(BindView.class);
                int id = bindView.value();
                // 根据id拿到xml中的控件对象
                View view = activity.findViewById(id);
                // 给属性赋值
                try {
                    field.set(activity, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            /**
             * 绑定字符串
             */
            if (field.isAnnotationPresent(BindString.class)) {
                BindString bindString = field.getAnnotation(BindString.class);
                int value = bindString.value();
                String string = activity.getResources().getString(value);
                try {
                    field.set(activity, string);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            // 删除线的文字
            if (field.isAnnotationPresent(Deprecated.class)) {
                Deprecated deprecatedAnnotation = field.getAnnotation(Deprecated.class);
                int value = deprecatedAnnotation.value();
                View view = activity.findViewById(value);
                if (view instanceof TextView) {
                    ((TextView) view).getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
                    try {
                        field.set(activity, view);
                    } catch (IllegalAccessException e) {
                         e.printStackTrace();
                    }
               }
           }

        }

        /**
         * 绑定点击事件
         */
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (final Method method : declaredMethods) {
            method.setAccessible(true);
            if (method.isAnnotationPresent(OnClick.class)) {
                OnClick onClickAnnotation = method.getAnnotation(OnClick.class);
                int[] ids = onClickAnnotation.value();
                for (int id : ids) {
                    View view = activity.findViewById(id);
                    view.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            try {
                                method.invoke(activity, view);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            }
        }
    }
}

 

 

相关文章

    暂无相关文章
相关栏目:

用户点评