反射、注解、与依赖注入

反射(Reflection)

概念

为获取反射类和对象的信息,提供了类和接口。

作用

反射允许编程访问字段、方法以及构造函数的信息,并且使用反射得到的字段、方法和构造函数去操作对象潜在的副本(Class对象)

类和方法

一、获取对象的三种方式

  1. 第一种 知道类的名称,直接获取class对象
Class<?> class1 = LoginActivity.class
  1. 第二种 如果已经得到某个对象,可以通过该对象获取Class对象
LoginActivity activity = new LoginActivity();
Class<?> cls2 = activity.getClass();
  1. 第三种 如果你在编译期获取不到目标类型,但是你知道它的完整类路径,那么你可以通过如下的形式来获取 Class 对象,这样获取可能会抛出异常 ClassNotFoundException。
try {
    Class<?> cls3 = Class.forName("com.sun.study.ui.activity.LoginActivity");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

二、反射的相关方法示例

  • 方法
getName():获得类的完整名字。  
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

getFields():获得类的public类型的属性。  
getDeclaredFields():获得类的所有属性。

getMethods():获得类的public类型的方法。  
getDeclaredMethods():获得类的所有方法。  
getMethod(String name, Class[] parameterTypes):获得类的特定方法。

getModifiers()和Modifier.toString():获得属修饰符,例如private,public,static等  
getReturnType():获得方法的返回类型  
getParameterTypes():获得方法的参数类型

getConstructors():获得类的public类型的构造方法。  
getConstructor(Class[] parameterTypes):获得类的特定构造方法。

getSuperclass():获取某类的父类  
getInterfaces():获取某类实现关示例
  • 示例1:获得类的所有方法(Method)信息
private void getMethodsInfo() {
    Class<ReflectionActivity> cls = ReflectionActivity.class;
    Method[] methods = cls.getDeclaredMethods();
    if (methods == null) return;
    
    StringBuilder sb = new StringBuilder();
    for (Method method:methods) {
        sb.append(Modifier.toString(method.getModifiers())).append(" ");
        sb.append(method.getReturnType()).append(" ");
        sb.append(method.getName()).append("(");
        Class[] parameters = method.getParameterTypes();
        if (parameters != null) {
            for (int i=0; i<parameters.length; i++) {
                Class paramCls = parameters[i];
                sb.append(paramCls.getSimpleName());
                if (i < parameters.length - 1) sb.append(", ");
            }
        }
        sb.append(")\n\n");
    }

    tvInfo.setText(sb.toString());
}
  • 示例2:获得类的所有属性(Field)信息,并修改类型Int属性i的值
private void modifyFieldValue() {
   Class<ReflectionActivity> cls = ReflectionActivity.class;
   Field[] fields = cls.getDeclaredFields();
   if (fields == null) return;

   StringBuilder sb = new StringBuilder();
   sb.append("获得类的所有属性信息:\n\n");
   for (Field field:fields) {
       sb.append(Modifier.toString(field.getModifiers())).append(" ");
       sb.append(field.getType().getSimpleName()).append(" ");
       sb.append(field.getName()).append(";");
       sb.append("\n\n");
   }

   try {
       sb.append("属性i的默认值:i = ");
       Field f = cls.getDeclaredField("i");
       sb.append(f.getInt("i")).append("\n\n");
       f.set("i", 100);
       sb.append("属性i修改后的值:i = ");
       sb.append(f.getInt("i")).append("\n\n");
   } catch (Exception e) {
       e.printStackTrace();
   }

   tvInfo.setText(sb.toString());
   toolbar.setSubtitle("修改类型Int属性i的值");
}

注解(Annotations)

概念

也叫原数据,一种代码级别的说明。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

作用

  1. 标记作用,用于告诉编译器一些信息,让编译器能够实现基本的编译检查,如@Override、Deprecated
  2. 编译时动态处理,动态生成代码,如Butter Knife、Dagger 2
  3. 运行时动态处理,获得注解信息,如Retrofit

注解的分类

第一种分法

  1. 基本内置注解,是指Java自带的几个Annotation,如@Override、Deprecated、@SuppressWarnings等
  2. 元注解(meta-annotation),是指负责注解其他注解的注解,JDK 1.5及以后版本定义了4个标准的元注解类型,如下:
1、@Target
2、@Retention
3、@Documented
4、@Inherited
  1. 自定义注解,根据需要可以自定义注解,自定义注解需要用到上面的meta-annotation

第二种分法,根据作用域分类

  1. 源码时注解(RetentionPolicy.SOURCE)
  2. 编译时注解(RetentionPolicy.CLASS)
  3. 运行时注解(RetentionPolicy.RUNTIME)

注解相关知识点

元注解相关信息

  • @Target:指Annotation所修饰的对象范围,通过ElementType取值有8种,如下
TYPE:类、接口(包括注解类型)或枚举
FIELD:属性
METHOD:方法
PARAMETER:参数
CONSTRUCTOR:构造函数
LOCAL_VARIABLE:局部变量
ANNOTATION_TYPE:注解类型
PACKAGE:包
  • @Retention:指Annotation被保留的时间长短,通过RetentionPolicy取值有3种,如下:
SOURCE:在源文件中有效(即源文件保留)  
CLASS:在class文件中有效(即class保留)  
RUNTIME:在运行时有效(即运行时保留)
@Documented:是一个标记注解,用于描述其它类型的注解应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。
  • @Inherited:也是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的

注解定义格式

public @interface 注解名 { 定义体 }

注解参数可支持的数据类型:

8种基本数据类型 int、float、boolean、byte、double、char、long、short  
String、Class、enum、Annotation  
以上所有类型的数组

注意:自定义注解如果只有一个参数成员,最好把定义体参数名称设为"value",如@Target

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

依赖注入(Dependency Injection)

posted @ 2016-07-26 11:48  Live and Learn  阅读(294)  评论(0)    收藏  举报