java 反射 初始化array_Android架构师之路--Java进阶基础--注解与反射

Java进阶基础--注解与反射

一、注解

Java注解(Annotation)又称Java标注,是JDK5.0引入的一种注释机制。注解是元数据的一种形式,提供有关于程序但不属于程序本身的数据。注解对它们注解的代码的操作没有直接影响。

1、注解声明

Java中所有的注解,默认实现Annotation接口:

package java.lang.annotation;

public interface Annotation {

boolean equals(Object obj);

int hashCode();

String toString();

Class extends Annotation> annotationType();

}

于声明一个“Class”不同的是,注解的声明使用@interface关键字。

public @interface Lance{ }

1.1、元注解

在定义注解时,注解类也能够使用其他的注解声明。对注解类型进行注解的注解类,我们称之为meta-annotation(元注解)。一般的,我们在定义自定义注解时,需要指定的元注解有两个:

@Target

注解标记另一个注解,以限制可以应用注解的Java元素类型。目标注解指定以下元素类型之一作为其值:

①ElementType.ANNOTATION_TYPE  可以应用于注解类型。

②ElementType.CONSTRUCTOR 可以应用于构造函数。

③ElementType.FIELD 可以应用于字段或属性。

④ElementType.LOCAL_VARIABLE 可以应用于局部变量。

⑤ElementType.METHPD 可以应用于方法级注解。

⑥ElementType.PACKAGE 可以应用于包声明。

⑦ElementType.PARAMETER 可以应用于方法的参数。

⑧ElementType.TYPE 可以应用于类的任何元素。

@Retention

注解指定标记注解的存储方式:

①RetentionPolicy.SOURCE 标记的注解仅保留在源码级别中,并被编译器忽略。

②RetentionPolicy.CLASS 标记的注解在编译时由编译器保留,但Java虚拟机(JVM)会忽略。

③RetentionPolicy.RUNTIME 标记的注解由JVM保留,因此运行时环境可以使用它。

另外还有@Documented 与 @Inherited 元注解,前者用于被javadoc工具提取成文档,后者表示允许子类继承父类中定义的注解。

@Retention 三个值中 SOURCE < CLASS < RUNTIME,即CLASS包含了SOURCE,RUNTIME包含SOURCE、CLASS。

例子:

@Target({ElementType.TYPE,ElementType.FIELD}) // 允许在类与类属性上标记该注解

@Retention(RetentionPolicy.SOURCE) //注解保留在源码中

public @interface Lance {}

1.2、注解类型元素

在声明注解中,允许在使用注解时传递参数。

@Target({ElementType.TYPE,ElementType.FIELD})

@Retention(RetentionPolicy.SOURCE)

public @interface Lance {

String value(); //无默认值

int age() default 1; //有默认值

}

注意:在使用注解时,如果定义的注解中的类型元素无默认值,则必须进行传值。

1.3、注解应用场景

按照@Retention元注解定义的注解存储方式,注解可以被在三种场景中使用:

2d3d8afacae5

1.4、Android注解语法检查

在Android中我们需要设计接口以供使用者调用时,如出现需要对入参进行类型限定,如限定为资源ID,布局ID等类型参数,将参数类型直接给定int即可。然而,我们可以利用Android为我们提供的语法检查注解,来辅助进行更为直接的参数类型检查与提示。

参数限制为:图片资源ID

public Drawable getDrawable(@Drawable int id) throw是 NotFoundException

同时,我们也可以使用@intDef来定义自己的入参类型检查。

二、反射

一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的,并且能都获得此类的引用。于是我们直接对这个类进行实例化,之后使用这个类进行操作。

反射则是一开始并不知道我们初始化的类对象是什么,自然也无法使用new关键字来创建对象。这时候,我们使用JDK提供的反射API进行反射调用。

反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。是Java被视为动态语言的关键。

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

①在运行时构造任意一个类的对象

②在运行时获取或者修改任意一个类所具有的成员变量和方法

③在运行时调用任意一个对象的方法和属性

2d3d8afacae5

1、Class

反射始于Class,Class是一个类,封装了当前对象所对应的类的信息。

1.1、获得Class对象

①通过类名获取   类名.class

②通过对象获取    对象名.getClass()

③通过全类名获取     Class.forName(全类名)    classLoader.loadClass(全类名)

2、判断是否为某个类的实例

一般地,我们用 instanceof 关键字来判断是否为某个类的实例。同时我们也可以借助反射中 Class 对象的isInstance() 方法来判断是否为某个类的实例,它是一个 native 方法: public native boolean isInstance(Object obj);

判断是否为某个类的类型:  public boolean isAssignableFrom(Class> cls)

3、创建实例

①使用Class对象的newInstance()方法来创建Class对象对应类的实例

Class> c = String.class;         Object str = c.newInstance();

②先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。

//获取String所对应的Class对象             Class> c = String.class;

//获取String类带一个String参数的构造器        Constructor constructor = c.getConstructor(String.class);

//根据构造器创建实例          Object obj = constructor.newInstance("23333");

4、获取构造器信息

获取构造器的方法:

①Constructor getConstructor(Class[] params)  获得使用特殊的参数类型的public构造函数(包括父类)

②Constructor[] getConstructors()   获得类的所有公共构造函数

③Constructor getDeclaredConstructor(Class[] params)   获得使用特定参数类型的构造函数(包括私有)

④Constructor[] getDeclaredConstructors()   获得类的所有构造函数(与接入级别无关)

5、获取类的成员变量(字段)信息

获取字段信息的方法:

①Field  getField(String name)    获得命名的公共字段(public修饰)

②Field[]  getFields()   获得类的所有公共字段(public修饰)

③Field  getDeclaredField(String name)   获得类声明的命名的字段(包括private修饰)

④Field[]  getDeclaredFields   获得类声明的所有字段(包括private修饰)

当我们从类中获取了一个方法后,就可以用 invoke() 方法来调用这个方法。

public Object invoke(Object obj, Object... args);

6、利用反射创建数组

数组在Java里是比较特殊的一种类型,它可以赋值一个Object Reference其中的Array类为java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象

public static Object newInstance(Class> componentType, int length);

7、反射获取泛型真实类型

当我们对一个泛型类进行反射时,需要得到泛型中的真实数据类型,来完成如JSON反序列化的操作。此时需要通过Type体系来完成。Type接口包含了一个实现类(Class)和四个实现接口:

①TypeVariable                 泛型类型变量。可以获得泛型上下限等信息

②ParameterizedType       具体的泛型类型。可以获得元数据中泛型签名类型(泛型真实类型)

③GenericArrayType         当需要描述的类型是泛型类的数组时,比如List[],Map[],此接口会作为Type的实现

④WildcardType                通配符泛型。可以获得上下限信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值