Java高级特性之注解

本博文涉及代码已上传至github,结合代码看更容易理解哟~链接:https://github.com/ZNKForSky/AnotationDemo

概念

Java注解是JDK1.5的新特性,与注释比较类似,不同的是注释是给我们开发人员看的,注解是给代码看的,它是代码层面的解释说明
注解的使用也很简单,语法规则:@注解名称,比如我们常见的“@Override”。

作用

①生成doc文档;

②使用反射对代码进行分析;

③编译检查。

JDK中预定义的一些注解:

①@Override: 检测方法是否是重写父类或父接口的;

②@Deprecated: 标识过时的内容;

③@SuppressWarnings: 压制警告,一般传入参数all,@SuppressWarnings("all")

自定义注解:

格式:

[元注解]

public @interface 注解名称{

    属性列表;

}

eg.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface ZnkAnno {
String value();
}

ps:[ ] 表示可选。

注解本质:

通过javap命令反编译class文件,可以发现注解的本质就是继承 java.lang.annotation.Annotation的接口。

注解中的属性(其实就是接口中的抽象方法):

语法:
1>属性的返回值必须是基本数据类型、String、Class、枚举、注解或者以上类型的数组;
2>定义属性后,在使用注解时要给属性赋值,如果定义属性时使用default关键字给了属性默认值,则可以不做赋值;如果只有一个名称为value的属性,则value可以省掉,直接定义值即可;数组赋值时需要{},如果数组中只有一个值,则可省略{}。 

元注解

元注解就是用来解释说明注解的注解。

①@Target:描述注解能够作用的位置。

 --ElementType常用取值:

  • TYPE:可以作用在类上;
  • FIELD:可以作用在属性上;
  • METHOD:可以作用在方法上。

PS:所有取值见下图。

②@Retention:描述注解被保留的阶段(java代码SOURCE(源码阶段)、CLASS(字节码文件)、RUNTIME(运行时阶段)三个阶段

    -- @Retention(RetentionPolicy.RUNTIME) 表示当前被描述的注解会被保留到class字节码文件中,并会被JVM读取到

③@Documented:描述注解是否被抽取到api文档中

④@Inherited:描述注解是否被子类继承

注解的使用场景

上面我们已经了解到注解的保留级别包括SOURCE、CLASS、RUNTIME三个阶段,那我们根据保留级别不同,自然能想到注解的使用也存在不同场景。

级别

技术

备注

源码

APT

1.在编译期能够获取注解与注解声明的类,包括类中所有成员信息,一般用于生成额外的辅助类。

2.也可以用作语法检查。

字节码

字节码增强

在编译出Class后,通过修改Class数据以实现修改代码逻辑目的。对于是否需要修改的区分或者修改为不同逻辑的判断可以使用注解。

运行时

反射

在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判定。

--源码级别的注解示例:

1>APT(Annotation Processor Tools)

2>语法检查:在Android开发过程中,当我们需要设计接口供使用者调用时,如果需要对入参类型做限定,比如限定为资源ID、布局ID等类型参数,就可以通过@IdRes、@LayoutRes分别限定。同时我们可以利用@IntDef、@StringDef、@LongDef 定义自己的入参类型检查。

PS:我们也可以改变自定义限定注解语法检查的提示等级:

--字节码级别的注解在热修复技术中会用到,这里暂时不做详细描述(关键我自己还没整明白{>-<})。

--运行时的注解主要是与反射结合做一些操作,比如我们常用的ButterKnife,最初就是通过注解加反射的方式实现的,我给出的git代码里面也有实现findViewById的案例,感兴趣的小伙伴可以瞄一眼。

反射获取泛型真实类型(很少用到,了解即可)

当我们对泛型类进行反射时,需要拿到泛型信息来完成像Json反序列化的操作时,需要借助Type体系来完成。Type接口包含一个实现类Class和四个实现接口:

我们开发过程中经常会有这样一种场景,我们请求后台接口,后台返回的数据类型可能是这样的:
{
    "data":{
        "name":"luffy",
        "age":18,
        "sex":"male"
    },
    "code":200,
    "message":"查询成功"
}

我们会将后台返回的数据封装成一个Bean:

static class Response<T> {
        T data;
        int code;
        String message;

        public Response(T data, int code, String message) {
            this.data = data;
            this.code = code;
            this.message = message;
        }

        @Override
        public String toString() {
            return "Response{" +
                    "data=" + data +
                    ", code=" + code +
                    ", message='" + message + '\'' +
                    '}';
        }
    }

 因为每个接口返回的data多数情况下类型是不同的,所以我们一般用泛型处理。比如现在某个接口返回的数据是

{
    "name":"luffy",
    "age":18,
    "sex":"male"
}
我们将它封装成Bean:

    static class Data {
        String name;
        int age;
        String sex;

        public Data(String name, int age, String sex) {
            this.name = name;
            this.age = age;
            this.sex = sex;
        }

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

 我们测试如上的数据是否可以进行反序列化:如下图所示,出现了ClassCastException。

解决方案:

Type type = new TypeToken<Response<Data>>() {
}.getType();
Response<Data> response = gson.fromJson(result, type);

 我们来看看TypeToken里面的具体实现:

我也按照这个思路试着实现了一下: 

package com.luffy.reflect.Type;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 作者:<a href="https://blog.csdn.net/qq_35101450">张宁科CSDN主页</a><p>
 * 创建时间:2020/10/27 15:51<p>
 * 描述:参考TypeToken 解决Json反序列化问题
 */
public class TypeRefrence<T> {
    Type type;
    T t;

    protected TypeRefrence() {
        //1.获得泛型类型
        Type genericSuperclass = getClass().getGenericSuperclass();
        System.out.println("genericSuperclass的类型是: " + genericSuperclass.getClass());
        System.out.println("genericSuperclass ====== " + (genericSuperclass instanceof Class));
        ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
        //2.因为泛型类型可以定义多个: MainActivity<T,E,K...> 所以返回是一个数组
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        type = actualTypeArguments[0];
    }

    public Type getType() {
        return type;
    }
}

关于注解先讲这么多,觉得能get到好东西的小伙伴记得关注加点赞哟, 不懂的地方也可以评论区留言与我交流~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
引用\[1\]:很简单,加个循环就可以啦: String file = "D://hello.txt"; FileReader fr = new FileReader(file); char\[\] cbuf = new char\[1024\]; int len = 0; // 每次读取的长度 StringBuilder builder = new StringBuilder(); while ((len = fr.read(cbuf)) != -1) { builder.append(cbuf,0,len); } System.out.println(builder.toString()); 。 引用\[2\]:上述代码的最佳实践为: OutputStream out = null; try { String file = "D://test.txt"; out = new FileOutputStream(file); String str = "hello educoder"; byte\[\] b = str.getBytes(); out.write(b); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { try { out.close(); // 释放该输出流 } catch (IOException e) { e.printStackTrace(); } } } 。 引用\[3\]:可能学到这,你会有很多疑问: 扩展 使用BufferedReader读取字符文件的速度要比我们之前使用的字节流和FileReader快很多,示例代码: BufferedReader bf = new BufferedReader(new FileReader("D://hello.txt")); BufferedWriter writer = new BufferedWriter(new FileWriter("D://abc.txt")); String str = ""; while( (str = bf.readLine()) != null){ writer.write(str); } bf.close(); writer.close(); 五、总结 。 问题:java高级特性是什么 回答: Java高级特性包括但不限于以下几个方面:多线程、网络编程、反射、泛型、注解、Lambda表达式、流式API、函数式编程等。其中,多线程允许程序同时执行多个任务,提高程序的并发性能;网络编程允许程序通过网络进行通信;反射允许程序在运行时动态地获取类的信息并操作对象;泛型允许在编译时指定类型参数,提高代码的安全性和可读性;注解允许程序在代码中添加元数据,用于编译时和运行时的处理;Lambda表达式和函数式编程允许以更简洁的方式处理函数式接口;流式API提供了一种更便捷的方式来处理集合和数组等数据;这些高级特性可以提高Java程序的效率和可维护性。 #### 引用[.reference_title] - *1* *2* *3* [Java高级特性-IO流](https://blog.csdn.net/m0_52423924/article/details/122801498)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值