Java注解和JDK新特性

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 {@Overridepublic int compareTo(Student o) {return 0;}@Overridepublic 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();}@Deprecatedpublic 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 {// 如果有只有一个配置参数,一般命名为valueString 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() {@Overridepublic void run() {System.out.println("线程任务");}}).start();// Lamda使用1new Thread(() -> System.out.println("线程任务")).start();TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() {@Overridepublic 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>() {@Overridepublic void accept(String s) {System.out.println(s);}};list.forEach(consumer);*/list.forEach((o) -> System.out.println(o));/*Predicate predicate = new Predicate<String>() {@Overridepublic 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 8default void method2() {method5();};// JDK 8default void method3() {method5();}// JDK 8static void method4() {}// JDK 9private 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.rhkb.cn/news/413918.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内存管理篇-17解开页表的神秘面纱-下

1.页表初探遗留问题-页表的创建过程 使用MMU之前&#xff0c;页表要准备好&#xff0c;怎么准备的&#xff1f;如何把物理内存通过section映射构建页表页表的创建过程分析&#xff1a;__create_page_tables--创建临时页表&#xff0c;然后在开启MMU 页表的大小和用途页表在内存…

zdppy_cache缓存框架升级,支持用户级别的缓存隔离,支持超级管理员管理普通用户的缓存

启动服务 import zdppy_api as api import zdppy_cachekey1 "admin" key2 "admin"app api.Api(routes[*zdppy_cache.zdppy_api.cache(key1, key2, api) ])if __name__ __main__:import zdppy_uvicornzdppy_uvicorn.run(app, host"0.0.0.0",…

Mac 安装Hadoop教程

1. 引言 本教程旨在介绍在Mac 电脑上安装Hadoop&#xff0c;便于编程开发人员对大数据技术的熟悉和掌握。 2.前提条件 2.1 安装JDK 想要在你的Mac电脑上安装Hadoop&#xff0c;你必须首先安装JDK。具体安装步骤这里就不详细描述了。你可参考Mac 安装JDK8。 2.2 配置ssh环境…

代码随想录 -- 字符串 -- 重复的子字符串

459. 重复的子字符串 - 力扣&#xff08;LeetCode&#xff09; 暴力解法&#xff1a; 思路&#xff1a; 假设子串 s 长度 n 为 i&#xff0c;从1到n/2遍历&#xff1a; 1. 如果 s 能够由他的子串重复构成&#xff0c;那么 s 的长度 n 一定整除其子串 s 的长度 n&#xff0c; …

结合Wireshark抓包实战,图文详解TCP三次握手及四次挥手原理(附下载)

网络安全的基础是网络&#xff0c;若连最基础的网络协议都搞不明白&#xff0c;何谈网络安全。针对核心的TCP协议&#xff0c;本文通过Wireshark工具抓取并分析TCP三次握手和四次挥手的详细过程&#xff0c;包括数据包捕获步骤&#xff0c;每个握手阶段和挥手阶段的数据包内容解…

数据分析处理库(pandas)

目录 数据预处理 数据读取 DataFrame结构 数据索引 创建DataFrame Series操作 数据分析 统计分析 pivot数据透视表 groupby操作 常用函数操作 Merge操作 排序操作 缺失值处理 apply自定义函数 时间操作 绘图操作 大数据处理技巧 数值类型转换 属性类型转换…

MediaGo下载器:专业级功能,轻松应对各种下载需求!

前言 在科技的浪潮中有这样一句名言&#xff0c;深刻地揭示了创新的力量&#xff1a;“创新是引领发展的第一动力。”正是这股不竭的动力&#xff0c;推动了无数软硬件产品的诞生与迭代&#xff0c;为我们带来了前所未有的便捷与体验。今天&#xff0c;我们要探讨的正是这样一…

C++ | Leetcode C++题解之第384题打乱数组

题目&#xff1a; 题解&#xff1a; class Solution { public:Solution(vector<int>& nums) {this->nums nums;this->original.resize(nums.size());copy(nums.begin(), nums.end(), original.begin());}vector<int> reset() {copy(original.begin(), …

重新修改 Qt 项目的 Kit 配置

要重新修改 Qt 项目的 Kit 配置&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. 打开 Qt Creator 首先&#xff0c;启动 Qt Creator&#xff0c;确保你的项目已经打开。 2. 进入项目设置 在 Qt Creator 中&#xff0c;点击菜单栏的 “Projects” 标签&#xff08;通…

Java并发编程面试必备:如何创建线程池、线程池拒绝策略

一、线程池 1. 线程池使用 1.1 如何配置线程池大小 如何配置线程池大小要看业务系统执行的任务更多的是计算密集型任务&#xff0c;还是I/O密集型任务。大家可以从这两个方面来回答面试官。 &#xff08;1&#xff09;如果是计算密集型任务&#xff0c;通常情况下&#xff…

中仕公考怎么样?公务员考试什么时候补录?

公务员考试补录的时间和方法通常因地区和职位的不同有所区别&#xff0c;一般来说&#xff0c;这一过程会在面试、体检和考核环节完成后启动。 如果在招录过程中出现职位空缺或者并未全部招满的情况&#xff0c;就会进行补录。用人单位会通过其官方或公告形式公布相关信息&…

关于武汉芯景科技有限公司的实时时钟芯片XJ8337开发指南(兼容DS1337)

一、芯片引脚介绍 1.芯片引脚 2.引脚描述 二、系统结构图 三、功能描述 1.时钟功能 2.闹钟功能&#xff08;两个闹钟&#xff09; 3.振荡器停止控制 4.频率输出&#xff08;1HZ、1.096KHZ、8.192KHZ、32.768KHZ&#xff09; 5.振荡器停止检测 6.闹钟中断标志 四、程序代…

短时傅里叶变换(Short-Time Fourier Transform, STFT),语音识别

高能预警&#xff01;&#xff01;&#xff01; .wav文件为笔者亲自一展歌喉录制的噪声&#xff0c;在家中播放&#xff0c;可驱赶耗子&#xff0c;蟑螂 介绍 短时傅里叶变换&#xff08;Short-Time Fourier Transform, STFT&#xff09;是一种时频分析方法&#xff0c;用于…

如何在银河麒麟操作系统中为文件加锁与解锁

如何在银河麒麟操作系统中为文件加锁与解锁 1、加锁2、解锁 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、加锁 若要为文件加锁&#xff0c;防止被修改或删除&#xff0c;可以使用chattr命令并加上i选项。这需要root权限。 命令&…

华为OD机试真题 - 多段数据压缩(Java/Python/JS/C/C++ 2024 D卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Java/Python/JS/C/C++)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX…

网络基础+Socket

目录 下图为数据分用的过程 认识IP地址 认识MAC地址 认识端口号 网络字节序 sockaddr结构 Makefile新写法 下图为数据分用的过程 认识IP地址 IP协议有两个版本, IPv4和IPv6. 我们整个的课程, 凡是提到IP协议, 没有特殊说明的, 默认都是指IPv4 IP地址是在IP协议中, 用来…

js实现3d拖拽环绕旋转

js实现拖动节点围绕圆心转动 1.使用transform属性&#xff0c;将圆环放倒展示为椭圆 圆环上有不同的色彩&#xff0c;在转动的同时&#xff0c;需要让圆环也转动&#xff0c;所以圆环不能是椭圆&#xff0c;而是圆形&#xff0c;这样在转动的时候&#xff0c;改变rotate&…

开源 AI 智能名片 S2B2C 商城小程序在现代商业中的创新与启示

摘要&#xff1a;本文通过分析一种以 9.9 元裙子为代表的独特商业模式&#xff0c;探讨了其背后的现金流、产品和渠道组合策略&#xff0c;以及开源 AI 智能名片 S2B2C 商城小程序在其中可能发挥的作用和带来的启示。 一、引言 在当今竞争激烈的商业环境中&#xff0c;企业不断…

认知杂谈41

今天分享 有人说的一段争议性的话 I I 贫富根源在观念 I 你知道不&#xff1f;穷人穷啊&#xff0c;好多时候是因为他们自己还有家里好几代人呢&#xff0c;都陷在一种不对的想法里出不来&#xff0c;还觉得这样挺好&#xff0c;就一直这么过下去了。可富人的那些想法呢&am…

3127.构造相同颜色的正方形

1.题目描述 给你一个二维 3 x 3 的矩阵 grid &#xff0c;每个格子都是一个字符&#xff0c;要么是 B &#xff0c;要么是 W 。字符 W 表示白色&#xff0c;字符 B 表示黑色。 你的任务是改变 至多一个 格子的颜色&#xff0c;使得矩阵中存在一个 2 x 2 颜色完全相同的正方形。…