Java注解和JDK新特性

news2024/12/23 22:45:56

1. 注解

1.1. 认识注解

Annotation:JDK1.5新提供的技术

  1. 编译检查:比如@SuppressWarnings, @Deprecated和@Override都具有编译检查的作用
  2. 替代配置文件:使用反射来读取注解的信息

注解就是代码里的特殊标记,用于替代配置文件,开发人员可以通过注解告诉类如何运行
注解的应用:通过反射得到类中的注解,以决定类的运行。注解可以标记在包、类、属性、方法,方法参数以及局部变量上,且同一个地方可以同时标记多个注解。
注解可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或部署。

1.2. 内置注解

  • @Override:检查该方法是否是重载方法,如发现其父类,或者引用的接口中并没有该方法,会报编译错误
  • @Deprecated:编辑过时的方法,使用该方法,会报编译警告
  • @SuppressWarnings:指示编译器忽略注解中注明的警告
    在这里插入图片描述
    从Java7开始,新增了3个注解:
  • @SafeVarags:忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告
  • @FunctionalInterface:标识一个匿名函数或函数式接口
  • @Repeatable:标识某注解可以在同一个声明上使用多次
@SuppressWarnings(value = {"all"})
public class Student implements Comparable<Student>, Serializable {
    @Override
    public int compareTo(Student o) {
        return 0;
    }
    @Override
    public String toString() {
        return super.toString();
    }
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date.toLocaleString());
        Student stu = new Student();
        stu.method1();
        List list = new ArrayList();
    }
    @Deprecated
    public void method1() {
        System.out.println("========");
    }
    public void method2() {
        Date date = new Date();
        System.out.println(date.toLocaleString());
    }
}
public class TestStudent {
    @SuppressWarnings(value = "deprecation")
    public static void main(String[] args) {
        Student stu = new Student();
        stu.method1();
    }
}

1.3. 元注解

元注解是指注解的注解

  1. @Retention:约束注解的生命周期:源码级别(SOURCE)、类文件级别(CLASS)或运行时级别(RUNTIME),若没有@Retention,则默认是RetentionPolicy.CLASS,含义如下:
    • SOURCE:注解将被编译器丢弃(就是不会保留在class文件中)
    • CLASS:注解在class文件中可用,但会被VM丢弃(不会加载到虚拟机中)
    • RUNTIME:注解在运行期间(JVM)也保留,因此可以通过反射机制读取注解的信息,如SpringMVC中的@Controller、@ Autowired、@RequestMappling等
  2. @Target:用来约束注解可以应用的地方(如方法、类或字段),其中ElementType是枚举类型。若没有@Target,则该Annotation可以用于任何地方
public enum ElementType {
    // 标明该注解可以用于类、接口(包括注解类型)或enum声明
    TYPE,
    // 标明该注解可以用于字段(域)声明,包括enum实例
    FIELD,
    // 标明该注解可以用于方法声明
    METHOD,
    // 标明该注解可以用于参数声明
    PARAMETER,
    // 标明注解可以用于构造函数声明
    CONSTRUCTOR,
    // 标明注解可以用于局部变量声明
    LOCAL_VARIABLE,
    // 标明注解可以用于注解声明(应用于另一个注解上)
    ANNOTATION_TYPE,
    // 标明注解可以用于包声明上
    PACKAGE,
    // 标明注解可以用于类型参数声明(1.8+)
    TYPE_PARAMETER,
    // 类型使用声明(1.8+)
    TYPE_USE
}
  1. @Documented:标记这些注解是否包含在用户文档中
  2. @Inherited:指示注解类型被自动继承。如果在注解类型声明中存在Inherited元注解,并且用户在某一类声明中查询该注解类型,同时该类声明中没有此类型的注解,则将在该类的超类中自动查询该注解类型

2. 注解

2.1. 自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnoation {
    int id() default 0;
    String name() default "";
    double[] scoreArr() default {};
}
public @interface  MyAnnoation2 {
    // 如果有只有一个配置参数,一般命名为value
    String value();
}
@MyAnnoation2("wyb")
@MyAnnoation
public class TestAnnotation {
    @MyAnnoation(id=5, name="wyb", scoreArr = {78,89,34})
    public static void main(String[] args) {
    }
    @MyAnnoation2(value="wyb")
    public void method1() {
    }
}

总结:

  • 定义注解的关键字是@interface
  • 自定义注解中可以定义多个配置参数,不是成员方法或成员变量;说明参数的名称,以及参数值的类型
  • 如果只有一个配置参数,一般命名为value
  • 如果配置参数是value,并且只有一个配置参数,value可省略
    注意:
  • 定义注解时,意味着他实现了java.lang.annotation.Anntotation接口,即该注解就是一个Anntotation
  • 和implements实现接口的方法不同。Anntotation接口的实现细节都由编译器来完成。通过@interface定义注解后,该注解不能继承其他注解或接口
  • 注解常见的API及其关系如下:
    在这里插入图片描述

2.2. 使用反射读取注解

在这里插入图片描述
模拟实现MyBatis的注解并使用反射读取

@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface Table {
    String value();
}
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.FIELD)
public @interface Column {
    String columnName();
    String columnType();
    int length();
    int precision() default 0;
}
@Table(value = "t_student")
public class Student1 {
    @Column(columnName = "id", columnType = "int", length = 6)
    private int id;
    @Column(columnName = "sname", columnType = "varchar", length = 10)
    private String name;
    @Column(columnName = "score", columnType = "double", length = 4, precision = 1)
    private double score;
}
public class TestORM {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        String className = "com.wyb.annotation.Student";
        Class clazz = Class.forName(className);
        // 获取类的所有注解
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        // 获取类的指定注解
        Table annotation = (Table) clazz.getAnnotation(Table.class);
        System.out.println(annotation);
        System.out.println(annotation.value());
        // 获取id属性的注解
        Field idField = clazz.getDeclaredField("id");
        Column idColumn = idField.getAnnotation(Column.class);
        System.out.println(idColumn.columnName());
        System.out.println(idColumn.columnType());
        System.out.println(idColumn.length());
        System.out.println(idColumn.precision());
    }
}

3. JDK新特性

3.1. JDK8新特性

3.1.1. Lamda表达式

Lamda表达式是JDK8的一个新特性,可以取代大部分的匿名内部类,写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以极大的优化代码结构

public class TestLamda {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程任务");
            }
        }).start();
        // Lamda使用1
        new Thread(() -> System.out.println("线程任务")).start();
        TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return -(o1.intValue() - o2.intValue());
            }
        });
        TreeSet<Integer> set2 = new TreeSet<>((o1, o2) -> (o1.intValue() - o2.intValue()));
        TreeSet<Integer> set3 = new TreeSet<>((o1, o2) -> {
            int v1 = o1.intValue();
            int v2 = o2.intValue();
            return -(v1 - v2);
        });
        Collections.addAll(set, 34,55,77,99,22);
        System.out.println(set);
    }
}

Lambda表达式是一种匿名函数(不是匿名内部类),他是没有声明的方法,也没有访问修饰符、返回值声明和名字。实质是属于函数式编程的概念。
Lambda表达式只能引用标记了final的外层局部变量。Lambda表达式的局部变量可以不用声明为final,但是必须不可被后面的代码修改
虽然Lambda表达式可以对某些接口进行简单的实现,但并不是所有接口都可以使用Lambda表达式来实现。Lambda规定接口中只能有一个需要被实现的抽象方法,不是规定接口中只能有一个方法,称为函数式接口。

3.1.2. 函数式接口

函数式接口:只能有一个抽象方法,其他的可以有default、static、Object里public方法等
JDK8专门提供了@FunctionalInterface注解,用来进行编译检查
作用:在Java中主要用在Lambda表达式和方法引用上

@FunctionalInterface
public interface FunInterface {
    // 只能有一个抽象方法
    void method1();
    default void method2() {}
    static void method3() {}
    // 从Object类继承的public方法不会计数
    public int hashCode();
    public boolean equals(Object obj);
}

JDK也提供了大量的函数式接口,使得Lambda表达式的运用更加方便、高效。这些内置的函数式接口可以解决开发中的大部分问题,只有小部分特殊情况需要自己去定义函数式接口

  • Consumer<T>:消费型接口(void accept(T t))。有参数,无返回值
  • Supplier<T>:供给型接口(T get())。只有返回值,没有入参
  • Function<T, R>:函数型接口(R apply(T t))。一个输入参数,一个输出参数
  • Predicate<T>:断言型接口(boolean test(T t))。输入一个参数,输出一个boolean类型的返回值
public class TestFunctionInterface {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "Java", "JS", "MySQL", "Oracle");
        /*Consumer consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        list.forEach(consumer);*/
        list.forEach((o) -> System.out.println(o));
        /*Predicate predicate = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length() == 4;
            }
        };
        list.removeIf(predicate);*/
        list.removeIf((o) -> o.length() == 4);
        System.out.println(list);
    }
}

3.1.3. Stream API

Stream API与java.io包里的InputStream和OutputStream是完全不同的概念。他是对容器对象功能的增强,专注于对容器对象进行各种便利、高效的聚合操作或大批量数据操作
Stream API提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。
Stream有三个操作步骤:

  1. 创建Stream:从一个数据源,如集合、数组中获取流
  2. 中间操作:一个操作的中间链,对数据源的数据进行操作
  3. 终止操作:一个终止操作,执行中间操作链,并产生结果

在这里插入图片描述
在这里插入图片描述
当数据源的数据上了流水线之后,这个过程对数据进行的所有操作都称为中间操作
中间操作会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线,比如map、filter、distinct、sorted、peek、limit等
当所有的中间操作完成后,若要执行终止操作。终止操作将返回一个执行结果,这就是最终的数据。
多个中间操作可以连接成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何处理,而在终止操作全部处理,称为惰性求值

public class TestStream {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Collections.addAll(list, 99,22,334,66,77);
        // list.stream().forEach((x) -> System.out.println(x));
        list.stream().sorted((o1, o2) -> o2 - o1).forEach(System.out::println);
        System.out.println("---------");
        list.stream().limit(2).forEach(System.out::println);
        System.out.println("---------");
        list.stream().filter((o) -> o >= 60).sorted((o1, o2) -> o2 - o1).forEach(System.out::println);
    }
}

3.1.4. 新的日期类

在这里插入图片描述

3.2. 其他版本新特性

3.2.1. JDK9新特性

模块化系统:允许开发者模块化开发的应用程序,同时也对JDK本身进行了模块化,因此一个应用程序就可以只包含他所需要的类库
模块化就是在package外面包裹一层,成员的作用范围在当前包和当前项目之间又增加了一个层次:模块
String类的底层由char数组变为byte数组,节省空间。
接口中可以定义private的非抽象方法,便于将多个方法中的冗余代码进行提取且不对外公开。

public interface interface9 {
    void method1();
    // JDK 8
    default void method2() {
        method5();
    };
    // JDK 8
    default void method3() {
        method5();
    }
    // JDK 8
    static void method4() {}
    // JDK 9
    private void method5() {}
}

3.2.2. JDK10新特性

局部变量类型推断:将前端思想var关键字引入,自动检测所属类型

/*
* JDK 10 之前的局部变量定义
* */
public class Test1 {
    public static void main(String[] args) {
        int num = 10;
        Scanner sc = new Scanner(System.in);
        List<String> list = new ArrayList<>();
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "wyb");
        map.put(2, "xz");
        map.put(3, "bjy");
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        for (Map.Entry<Integer, String> e : entries) {
            System.out.println(e.getKey() + "\t" + e.getValue());
        }
        int[] arr = {1, 2, 3};
        for (int a : arr) {
            System.out.println(a);
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

其实:=左侧的类型,不用显示编写出来,完全可以由右侧推断出左侧的类型

/*
* JDK 10的局部变量类型推断
* */
public class Test2 {
    public static void main(String[] args) {
        var num = 10;
        var sc = new Scanner(System.in);
        var list = new ArrayList<String>();
        var map = new HashMap<>();
        map.put(1, "wyb");
        map.put(2, "xz");
        map.put(3, "bjy");
        var entries = map.entrySet();
        for (var e : entries) {
            System.out.println(e.getKey() + "\t" + e.getValue());
        }
        var arr = new int[]{1,2,3};
        for (var a : arr) {
            System.out.println(a);
        }
        for (var i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

局部变量的类型推断必须具类型推断的基础才行。并不是任何地方都可以进行类型推断,比如:方法的返回值、行参,构造方法的行参等
注意:类型推断只能发生在编译阶段,在编译后的class文件会转为推断后的具体类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2095087.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四大集合之Set

一、Set基础知识 1. Set集合 1.1 HashSet Set集合区别于其他三大集合的重要特性就是元素具有唯一性&#xff0c;南友们记不住这个特性的话&#xff0c;有个易记的方法。Set集合为什么要叫Set呢&#xff1f;因为Set集合的命名取自于我们小学数学里的集合论&#xff08;Set Th…

SPI(硬件协议)

1 SPI硬件外设协议 2 SPI框图 3 硬件SPI数据收发流程 1 发送数据&#xff0c;同时接收数据&#xff0c;相互配合&#xff0c;可以实现数据流不间断 2 全双工SPI&#xff0c;发送和接收数据寄存器分开&#xff0c;可以同时进行 4 spi传输框图 1 速度快 2 速度慢&#xff0c;容…

软考中项拿证利器:系统集成项目管理工程师(第3版)一站通关

指尖疯编著的《系统集成项目管理工程师&#xff08;适用第3版大纲&#xff09;一站通关》目前现货已经上线各大电商平台&#xff0c;您可以在任一电商搜索《系统集成项目管理工程师&#xff08;适用第3版大纲&#xff09;一站通关》即刻找到。 出版中项一站通关完全是机缘巧合&…

Nginx: 性能优化之提升CPU效率以及TCP的三次握手和四次挥手

提升利用CPU的效率 1 &#xff09;CPU的调度机制 现在来看下 linux中 CPU的一个调度机制 假设现在系统上有只有一颗CPU&#xff0c;而linux系统是一个多任务的一个操作系统 它允许我们各个不同的用户允许在同一个操作系统上执行很多个进程 单核CPU肯定不可能同时去执行这样一…

5.图论.题目2

5.图论.题目2 题目8.字符串接龙9.有向图的完全可达性10.岛屿的周长11.寻找存在的路径12.冗余连接113.冗余连接214.寻宝 题目 8.字符串接龙 题目链接 本题的直观思路如下图所示&#xff1b;但该题有两个问题&#xff1a;1.图中的线是如何连接起来的 2.如何确定起点到终点的最…

《JavaEE进阶》----4.<SpringMVC①简介、基本操作(各种postman请求)>

本篇博客讲解 MVC思想、及Spring MVC&#xff08;是对MVC思想的一种实现&#xff09;。 Spring MVC的基本操作、学习了六个注解 RestController注解 RequestMappering注解 RequestParam注解 RequestBody注解 PathVariable注解 RequestPart注解 MVC View(视图) 指在应⽤程序中…

数据同步的艺术:探索PostgreSQL和Redis的一致性策略

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 1. 前言 在当今高度数字化的世界中,应用程…

ACL学习笔记

1.ACL快速配置 需求&#xff1a;拒绝PC 1访问PC 3 &#xff08;1&#xff09;配置PC PC 1: PC 2: PC 3: &#xff08;2&#xff09;配置R1的接口IP信息 sys sysname R1 undo info-center enable interface GigabitEthernet0/0/0 ip address 192.168.1.1 255.255.255.0 qui…

超声波智能水表多少钱一个?

超声波智能水表的价格因品牌、功能、规格等因素而异&#xff0c;就拿深圳合众致达科技有限公司智能水电表厂家的超声波智能水表DN15口径产品举例&#xff0c;价格为399元起。具体价格需根据实际需求来确定。 一、影响价格的主要因素 -技术含量&#xff1a;具备远程数据传输、…

DSOJ-id12

1.保留几位小数 #include <iostream>#include <iomanip> //必须包含这个头文件using namespace std;void main( ){ double a 3.141596;cout<<fixed<<setprecision(3)<<a<<endl; //输出小数点后3位 2. 使用了未初始化的局部变量 Point* …

如何使用小乌龟清除认证缓存、还原版本、定位及常用开发工具集成

&#x1f600;前言 本篇博文是关于如何使用小乌龟清除认证缓存、还原版本、定位及常用开发工具集成&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大…

openGuass之CTE Reuse

一. 前言 ​ CTE 是指with的公共表达式&#xff0c;如下所示是个CTE样例&#xff1a; ​ CTE表达式往往在同一条sql中多次被重复引用&#xff0c;如上图所示的cte被引用了两次&#xff08;c1 和 c2&#xff09;&#xff0c;我们称为2个CTE实例。 ​ 本文只要…

Windows系统Nginx下载安装配置 运行错误处理

Nginx是一款轻量级的web 服务器/反向代理 服务器。本篇文章主要是nginx的下载安装&#xff0c;处理运行中遇到的问题&#xff0c;配置反向代理。主要分为两部分&#xff1a;下载安装和配置。 目录 1.下载安装 2.nginx配置反向代理 1.下载安装 nginx官网&#xff1a;nginx: …

新160个crackme -044-tsrh-crackme

运行分析 提示去除NAG 不去除NAG也能进入主窗口&#xff0c;需要破解Name和Serial PE分析 ASM程序&#xff0c;32位&#xff0c;壳未知 去除NAG ida搜索字符串&#xff0c;发现NAG弹窗标题字符串&#xff0c;双击进入函数 找到了messagebox&#xff0c;即NAG位置00401079 打开x…

网络压缩之动态计算(dynamic computation)

动态计算希望网络可以自由 地调整它需要的计算量。为什么期待网络可以自由地调整它需要的计算量呢? 因为有时候我 们可能同样的模型会想要跑在不同的设备上面&#xff0c;而不同的设备上面的计算资源是不太一样的。所以期待训练好一个网络以后&#xff0c;放到新的设备上面&am…

Python编程基础知识,让编程基础更加扎实(输出个人简介)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

考研--数学(相关公式)

解析几何 知识点1 A(x1,y1) B(x2,y2) 则AB长度 |AB| A、B中点的坐标 &#xff08;&#xff0c;) 知识点2 方程求解 ①点斜式&#xff1a; y-y0k(x0-x) ②斜率式&#xff1a; ykxb ③两点式&#xff1a; …

【笔记篇】Davinci Configurator CanNm模块

目录 1 简介1.1 架构概览2 功能描述2.1 特性2.2 初始化2.3 状态机2.3.1 网络模式2.3.1.1 重复报文状态2.3.1.2 正常状态2.3.1.3 准备休眠状态2.3.2 预休眠模式2.3.3 总线休眠模式2.4 被动模式(对于被动节点)2.5 NM报文格式2.6 NM报文发送2.6.1 重试第一次报文请求2.7 降低总线…

集成电路学习:什么是I2C内部集成电路总线

I2C&#xff1a;内部集成电路总线 I2C&#xff0c;全称Inter-Integrated Circuit&#xff0c;即内部集成电路总线&#xff0c;是由飞利浦公司&#xff08;现为恩智浦半导体&#xff09;在上世纪八十年代初开发的一种同步的串行通信总线。它以其接线简单、硬件实现容易、可扩展性…

Mysql8利用binlog实现数据恢复

文章目录 1binlog基本概念2 binlog相关常用命令3 binlog工具mysqlbinlog4 测试数据准备&导入数据5 模拟误删表6 数据恢复方式说明7 数据恢复分析(偏移量方式恢复)8 数据恢复9 验证10 数据恢复的局限性11 总结 1binlog基本概念 binlog即binary log&#xff0c;二进制日志文件…