栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java注解,反射和泛型

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java注解,反射和泛型

注解 作用和意义
  • 注解又称标注,是Java1.5引入的,注解本身没有任务意义,单独的注解就是一种注释,它需要结合反射,插桩技术才能体验其用处
  • 元注解: 注解上的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface ARouter {
    String path();
    String group() default "";
}
  • @Target 标识的是注解在什么上,比如class,方法,成员变量等
  • @Retention 保留级别,有RUNTIME,CLASS,SOURCE 他们是包含关系,即CLASS包含SOURCE RUNTIME包含SOURCE和CLASS
  • SOURCE: 1:APT保留级别是最好用(生成class之前) .2:IDE语法检查
  • RUNTIME: 反射用(运行时)
反射

一般情况下,我们使用某个类时必定知道它是什么类,用来做什么的,并且能够获得这个类的引用,我们就可以对这个类进行实例化,然后使用它
反射则是一开始并不知道我要初始化的对象是什么,无法使用new来实例化对象,这个时候我们就可以使用jdk提供的反射调用. 就是在运行时,对于任意一个类,都能够知道这个类的属性和方法.对于任一对象,都能够调用它的任一方法,修改其属性.

下面示例(古老方法 自动findViewById)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
    @IdRes int value();
}
Activity activity;
反射获取成员变量Filed
Class clazz = Class.forName("android.app.Activity");
//获取自己和父类的所有的成员变量(不包括private)
Field[] declaredFields = clazz.getDeclaredFields();

//获取自己的所有的成员变量,不包括父类
Field[] fields = clazz.getFields();

//获取成员变量名为xxx的成员变量
Field xxxField = clazz.getField("xxx")
//判断xxxField上是否包含了InjectView注解
boolean isInjectView = xxxField.isAnnotationPresent(InjectView.class)
//如果存在这个注解则可以获取
if (isInjectView) {
		//获取InjectView注解
    InjectView injectView = declaredField.getAnnotation(InjectView.class);
    //获取注解上的值
    int id = injectView.value();
    View view = activity.findViewById(id);
    //开始设置值
    xxxField.setAccessible(true);
    xxxField.set(activity,view);
}

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

  • Class
  • TypeVariable: 泛型类型变量
  • GenericArrayType: 当描述的泛型是泛型类数组时 比如:List[], Map[]
  • ParameterizedType: 具体泛型类型
  • WildcardType:通配符泛型
示例(获取泛型里的具体对象)
class Response{
    Type mType;
    public Response(){
        ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
        mType = type.getActualTypeArguments()[0];  
    }
    public Type getType(){
        return mType;
    }
}
void test(){
//获取type类型:
//方法1:调用此方法会抛错异常,
Type type = new Response().getType();

//方法2:可以获取到type为String.
Type type = new Response(){}.getType();//new Response(){}相当于创建了一个class文件.

//原因: 方法1是直接创建了一个对象,在编译成class之后不会保留泛型类型,全部为Object,而方法2是创建了一个匿名内部类,生成class时会保留原有的泛型签名
class Response2 extends Response{}
//方法2等于是创建了下面Response2类式对象 也就是方法2 也可以写成下面这种写法
Type type = new Response2().getType();
}
泛型

泛型是JDK5引入了,JVM本身是不支持泛型,但是为了向下兼容,Java是一种伪泛型,所以在编译期的时候会对泛型进行擦除,Java在运行时是不存在泛型信息的.

JAVA中的泛型使用分为以下三种情况
//情况一 泛型接口
public interface ILogin{}

//情况二 泛型类
public class Login{}

//情况三 泛型方法
public  T getLoginBean(){
	return new Login();
}
泛型怎么擦除
  • 检查泛型的类型,获取目标类型
  • 擦除类型变量,并替换为限定的类型,这里又分三种情况
    • 如果泛型类型的类型变量没有限定也就是只有一个,则最终这个T会变成Object
    • 如果有限定比如 ,则会用XXXBean作为原始的类型
    • 如果有多个限定的话比如 ,则以第一个作为原始类型
  • 生成桥接方法以在扩展保持多态(在有实现接口的时候会出现桥接方法,因为接口泛型里的泛型会转为Object,实现接口就得实现接口里的方法,所以会出现一个桥方法 )
  • 泛型擦除后会将泛型信息保留在类的常量池中
泛型好处
  • 代码更健壮,只要编译期没有报错,运行时就不会出现ClassCastException
  • 代码更简洁,很多都不需要强转
  • 代理更灵活,复用性高
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/322420.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号