首页 > Python资料 博客日记
Java 7新特性深度解析:提升效率与功能
2024-07-17 02:00:04Python资料围观74次
本篇文章分享Java 7新特性深度解析:提升效率与功能,对你有帮助的话记得收藏一下,看Python资料网收获更多编程知识
文章目录
Java 7新特性深度解析:提升效率与功能
一、Switch中添加对String类型的支持
Switch语句可以使用原始类型或枚举类型。
Java引入了另一种类型,可以在switch语句中使用:字符串类型。
public class switchAddString {
public static void main(String[] args) {
String s = "a";
switch (s) {
case "a":
System.out.println("a");
break;
case "b":
System.out.println("b");
break;
default:
System.out.println("default");
}
}
}
编译器在编译时的处理情形
- 仅有一个
case
和default
,则直接转换为if…else…
。 - 有多个
case
。先将String转换为hashCode
,然后相应的进行处理。
二、数字字面量的改进
- 数字中可加入分隔符:
- Java7中支持在数字量中间添加’_’作为分隔符。
- 下划线仅仅能在数字中间。
- 编译时编译器自己主动删除数字中的下划线。
- Java7添加二进制表示。
public static void main(String[] args) {
int i = 10;
System.out.println("i=" + i);
// 二进制
int j = 0b1010;
// 十六进制
int k = 0x1234;
// 1,000,000
int l = 1_000_000;
// 1,000,000
int m = 1__000_000;
System.out.println("j=" + j);
System.out.println("k=" + k);
System.out.println("l=" + l);
System.out.println("m=" + m);
}
三、异常处理(捕获多个异常)
- catch子句能够同一时候捕获多个异常:
- 使用’|'切割,多个类型,一个对象e 。
- try-with-resources语句:
- Java7之前须要在
finally
中关闭socket
、文件、数据库连接等资源。 - Java7引入
try-with-resources
,用于确保资源在使用后能够正确地关闭。 - 在使用
try-with-resources
时,你可以在 try 关键字后面的括号中声明一个或多个资源。 - 这些资源必须实现
AutoCloseable
接口(Java 7引入的接口,它具有一个close()
方法用于释放资源)。
- Java7之前须要在
public static void main(String[] args) {
// 捕获多个异常
try {
int a = 10;
int b = 0;
System.out.println("a/b=" + (a / b));
} catch (ArithmeticException | NullPointerException e) {
e.printStackTrace();
}
// try-with-resources,在 try 关键字后面的括号中声明一个或多个资源,每个资源用逗号分隔
String fileName = "example.txt";
try (
// 使用try-with-resources声明BufferedReader资源
BufferedReader reader = new BufferedReader(new FileReader(fileName));
// 需要声明多个资源,我们只需在括号中用逗号分隔
BufferedReader reader1 = new BufferedReader(new FileReader("file1.txt"));
BufferedReader reader2 = new BufferedReader(new FileReader("file2.txt"))
) {
// 读取文件内容
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 这里不需要显式调用reader.close(),因为try-with-resources会自动处理
} catch (IOException e) {
// 处理可能发生的IOException
e.printStackTrace();
}
// 在try代码块执行完毕后,reader会被自动关闭
}
四、增强泛型推断
- 菱形操作符:
- 在实例化泛型类时,可以使用菱形操作符
<>
来省略类型参数。 - 编译器会根据上下文推断类型参数。
- 简化代码,减少冗余,提高代码的可读性。
- 在实例化泛型类时,可以使用菱形操作符
- 泛型实例化类型推断:
- 当泛型类的构造函数的参数包含泛型类型时,Java 7 能够推断泛型的类型。
- 这允许你在实例化泛型类时省略类型参数,只在构造函数参数中指定类型即可。
public static void main(String[] args) {
// Java7之前
ArrayList<String> arrayList = new ArrayList<String>();
// Java7之后
ArrayList<String> arrayList2 = new ArrayList<>();
// 泛型类
class Generic<T> {
// 构造函数参数为泛型类型
public Generic(T t) {
}
}
// 使用泛型实例化类型推断
Generic<String> generic = new Generic<>("abc");
}
五、NIO2.0(AIO)新IO的支持
Java 7 引入了 NIO 2.0(New I/O),其中包含对异步 I/O(AIO)的支持,这是一个显著的新特性,特别是在处理非阻塞 I/O 操作时非常有用。具体来说,NIO 2.0 的 AIO 支持通过引入
AsynchronousFileChannel
类来实现异步文件 I/O 操作。
- AsynchronousFileChannel 类:
- 允许进行异步文件读取和写入操作。
- 相比于传统的阻塞 I/O,异步 I/O 可以在读写数据的同时执行其他操作,从而提高系统的效率和性能。
public static void main(String[] args) throws Exception {
// 异步读取文件
Path path = Paths.get("file.txt");
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
path, StandardOpenOption.READ);
// 分配缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 读取文件
long position = 0;
// 异步读取数据,用于检查读取操作的状态和获取读取的结果
Future<Integer> operation = fileChannel.read(buffer, position);
while (!operation.isDone()) {
// 等待读取完成
Thread.sleep(1000);
}
// 读取完成,将缓冲区数据翻转
buffer.flip();
// 读取数据
byte[] data = new byte[buffer.limit()];
// 将缓冲区数据复制到data中
buffer.get(data);
System.out.println(new String(data));
// 关闭文件
fileChannel.close();
}
- AsynchronousServerSocketChannel 和 AsynchronousSocketChannel:
- 用于支持异步的网络编程。
- 这些类允许你创建异步服务器端和客户端,并进行异步的网络数据读取和写入操作。
- 在高并发环境下处理 I/O 操作变得更为高效和灵活。
public static void main(String[] args) throws Exception {
// 创建异步通道
AsynchronousServerSocketChannel serverChannel =
AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8080));
// 接受连接
serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
/**
* 接受连接完成时调用此方法。
* @param clientChannel
* @param attachment
*/
@Override
public void completed(AsynchronousSocketChannel clientChannel, Void attachment) {
// 继续接受连接
serverChannel.accept(null, this);
// 读取数据
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 异步读取数据
clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
/**
* 当读取操作完成时调用此方法。
*
* @param result 读取操作的结果,通常为读取的字节数,但在此处未使用
* @param attachment 包含读取数据的ByteBuffer对象
*/
@Override
public void completed(Integer result, ByteBuffer attachment) {
// 处理读取完成
attachment.flip();
// 读取数据
byte[] data = new byte[attachment.limit()];
// 将数据复制到数组中
attachment.get(data);
System.out.println(new String(data));
}
/**
* 读取操作失败时调用此方法。
* @param exc
* @param attachment
*/
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
// 处理读取失败
}
});
}
/**
* 接受连接失败时调用此方法。
* @param exc
* @param attachment
*/
@Override
public void failed(Throwable exc, Void attachment) {
// 处理接受连接失败
}
});
// 程序继续执行其他操作
Thread.sleep(Long.MAX_VALUE);
}
六、SR292与InvokeDynamic
- SR-292(Small Ranges):
SR-292
是 Java 7 中引入的一个改进,主要针对switch
语句的性能优化。- 在早期的 Java 版本中,
switch
语句的效率问题在于它通过逐个比较每个case
条件来确定执行的分支,如果分支很多,这个过程可能会很慢。 - SR-292 引入了一种优化,即当
switch
语句的case
常量之间的距离非常小(称为 “small ranges
”),Java 编译器会使用一种更有效的查找方式,而不是简单的逐个比较。 - 这种方式可以显著提高
switch
语句的执行速度,特别是在处理密集的条件分支时。
public static void main(String[] args) {
int month = 3;
String monthName;
// Java 7 的 SR-292 特性可以在一些情况下优化这样的 switch 语句,尤其是在 case 常量的范围较小时
switch (month) {
case 1:
monthName = "January";
break;
case 2:
monthName = "February";
break;
case 3:
monthName = "March";
break;
case 4:
monthName = "April";
break;
case 5:
monthName = "May";
break;
case 6:
monthName = "June";
break;
default:
monthName = "Unknown";
break;
}
System.out.println("Month: " + monthName);
}
- InvokeDynamic(动态方法调用):
InvokeDynamic
是Java 7
引入的另一个重要特性,它是 Java 虚拟机(JVM
)层面的改进,旨在支持更灵活和高效的动态语言实现。- 允许 Java 代码中的方法调用在运行时动态解析,并且可以绑定到相应的方法实现。
- 用来优化字节码生成和方法调用的性能。
Java 8
的Lambda
表达式依赖于InvokeDynamic
来生成相应的字节码。
public static void main(String[] args) throws Throwable {
// 创建动态调用
MethodHandles.Lookup lookup = MethodHandles.lookup();
// 创建方法句柄,使用lookup对象来查找Math.class中的静态方法sqrt,该方法接受一个double参数并返回一个dou* 第一个参数是`lookup`对象。
MethodHandle mh = lookup.findStatic(Math.class, "sqrt",
MethodType.methodType(double.class, double.class));
// 创建动态调用
// 第一个参数是`lookup`对象
// 第二个参数是方法名,这里使用`"apply"`,因为它是`Function`接口中唯一的方法。
// 第三个参数是`Function`接口的签名(即`Function.class`的类型)。
// 第四个参数是`mh`的泛型类型签名。
// 第五个参数是我们要调用的方法句柄(即`mh`)。
// 第六个参数是`mh`的类型签名,表示我们要调用的方法的实际类型。
CallSite sqrt = LambdaMetafactory.metafactory(
lookup, "apply",
MethodType.methodType(Function.class),
mh.type().generic(),
mh,
mh.type()
);
// 调用动态调用
MethodHandle factory = sqrt.getTarget();
// 调用工厂方法,得到一个Function对象,使用了强制类型转换,因为factory.invoke()返回的是一个Object
Function<Double, Double> sqrtFunc = (Function<Double, Double>) factory.invoke();
double result = sqrtFunc.apply(16.0);
System.out.println("Square root of 16: " + result);
}
七、Path接口
在 Java 7 之前,通常使用
java.io.File
类来处理文件路径,Java 7 引入了java.nio.file.Path
接口,它是 Java 中操作文件和目录路径的抽象表示。Path
接口提供了更多功能和更强大的操作能力。
Path
接口的一些主要特性和用法:
-
路径表示:
Path
接口可以表示文件系统中的路径,可以是文件或目录。它不仅仅是一个字符串,而是一个真正的对象,提供了丰富的方法来操作路径。
-
创建路径:
-
可以使用Paths 类的静态方法来创建 Path 对象
Path path = Paths.get("/path/to/file.txt");
-
-
路径操作:
- Path 接口提供了多种方法来获取路径的信息
toString()
:将路径转换为字符串表示。getFileName()
:获取路径中的文件名部分。getParent()
:获取路径中的父路径。getRoot()
:获取路径的根部分。getNameCount()
:获取路径中的名称元素的数量。subpath(int beginIndex, int endIndex)
:获取指定范围内的子路径。
- Path 接口提供了多种方法来获取路径的信息
-
路径解析:
resolve()
方法可以用于解析相对路径或者连接两个路径,返回一个新的路径对象。
-
检查路径属性:
- 可以使用
Files
类的静态方法来检查文件或目录的属性,例如是否存在、是否可读、是否可写等。
- 可以使用
-
文件操作:
Files
类结合Path
接口提供了丰富的文件操作功能,包括读取文件内容、写入文件、复制、移动、删除等。
-
路径迭代:
-
Path接口支持迭代,可以方便地遍历路径的各个部分。
for (Path element : path) { System.out.println(element); }
-
-
相对路径和绝对路径:
Path
接口可以表示相对路径和绝对路径,并提供了方法来转换和处理这两种路径。
public static void main(String[] args) {
// 创建一个 Path 对象
Path path = Paths.get("/path/to/file.txt");
// 获取文件名
Path fileName = path.getFileName();
System.out.println("File Name: " + fileName);
// 获取父路径
Path parent = path.getParent();
System.out.println("Parent Path: " + parent);
// 获取路径的根部分
Path root = path.getRoot();
System.out.println("Root of the path: " + root);
// 获取路径的元素数量
int nameCount = path.getNameCount();
System.out.println("Number of elements in the path: " + nameCount);
// 遍历路径的每个元素
System.out.println("Elements in the path:");
for (int i = 0; i < nameCount; i++) {
System.out.println("Element " + i + ": " + path.getName(i));
}
// 路径解析示例
Path resolvedPath = path.resolve("subdir");
System.out.println("Resolved Path: " + resolvedPath);
// 检查文件或目录的属性
// 判断文件是否存在
boolean exists = Files.exists(path);
System.out.println("Exists: " + exists);
// 判断文件是否是目录
boolean isReadable = Files.isReadable(path);
System.out.println("Readable: " + isReadable);
// 判断文件是否是可写
boolean isWritable = Files.isWritable(path);
System.out.println("Writable: " + isWritable);
// 读取文件内容
Path filePath = Paths.get("/path/to/file.txt");
List<String> lines = null;
try {
lines = Files.readAllLines(filePath, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
for (String line : lines) {
System.out.println(line);
}
// 写入文件内容
Path newFilePath = Paths.get("/path/to/newfile.txt");
String content = "Hello, Java 7!";
try {
Files.write(newFilePath, content.getBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
// 复制文件
Path copiedFilePath = Paths.get("/path/to/copiedfile.txt");
try {
Files.copy(filePath, copiedFilePath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
// 移动文件
Path targetPath = Paths.get("/path/to/targetdir/movedfile.txt");
try {
Files.move(filePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
// 删除文件
try {
Files.delete(filePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
八、fork/join计算框架
Java 7 引入了
Fork/Join
框架,是一种并行计算框架,专门用于解决分而治之的问题。主要用于执行递归式地将问题划分为更小子问题,并行执行这些子问题的计算,然后合并结果的任务。
使用 Fork/Join 框架的基本步骤:
- 定义任务类 (
RecursiveTask
或RecursiveAction
):RecursiveTask
: 用于有返回值的任务。RecursiveAction
: 用于无返回值的任务。
- 重写
compute()
方法:- 在任务类中,需要实现
compute()
方法来定义任务的具体执行逻辑。 - 通常会判断是否需要进一步拆分任务,执行子任务的计算,最终将子任务的结果合并或处理。
- 在任务类中,需要实现
- 创建 Fork/Join 池:
- 使用
ForkJoinPool
类来管理并发执行的任务。 - 通常可以通过
ForkJoinPool.commonPool()
方法来获取默认的线程池,也可以根据需要创建自定义的线程池。
- 使用
- 提交任务:
- 将任务提交给
ForkJoinPool
来执行。
- 将任务提交给
使用 Fork/Join
框架来计算数组的总和Demo:
import java.util.concurrent.*;
// 继承 RecursiveTask 来实现有返回值的任务
class SumTask extends RecursiveTask<Long> {
// 阈值,控制任务拆分的粒度
private static final int THRESHOLD = 10;
private int[] array;
private int start;
private int end;
public SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if (end - start <= THRESHOLD) {
// 如果任务足够小,直接计算结果
long sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
// 否则,拆分任务为更小的子任务
int mid = (start + end) / 2;
SumTask leftTask = new SumTask(array, start, mid);
SumTask rightTask = new SumTask(array, mid, end);
// 异步执行左边的子任务
leftTask.fork();
// 同步执行右边的子任务
long rightResult = rightTask.compute();
// 获取左边子任务的结果
long leftResult = leftTask.join();
// 合并子任务的结果
return leftResult + rightResult;
}
}
}
public class ForkJoinDemo {
public static void main(String[] args) {
int[] array = new int[100];
for (int i = 0; i < array.length; i++) {
array[i] = i;
}
// 创建 Fork/Join 线程池
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
// 创建任务并提交给 Fork/Join 线程池
SumTask task = new SumTask(array, 0, array.length);
long result = forkJoinPool.invoke(task);
// 输出计算结果
System.out.println("Sum: " + result);
}
}
如果你累了,学会休息,而不是放弃
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Anaconda版本和Python版本对应关系(持续更新...)
- Python与PyTorch的版本对应
- Windows上安装 Python 环境并配置环境变量 (超详细教程)
- Python pyinstaller打包exe最完整教程