Java7 中有一些令开发者很高兴的新特性,如switch语句中的使用字符串作为表达式,多catch异常处理,try-with-resources (自动资源管理),新的文件系统API, jvm扩展,支持动态类型语言,支持并行任务的fork/join框架,以及其他一些肯定会被社区支持的特性。
下面就概述以上功能,并提供适当的例子。 这里可以下载一个zip文件,其中包含在这篇文章中的代码片段。
语言增强
Java7 通过Project Coin 提供了一些新的语言特性,这些功能对开发者来说非常方便。
Diamond Operator
你可能已经注意到在使用泛型的时候,IDE经常会出现警告提示。例如,如果我们要声明一个使用trades类作为泛型的Map类时,我们会写出像下面的代码:
Map<String, List<Trade>> trades = new TreeMap<String, List<Trade>> ();
我们必须在等号两边都声明同样的类型,这并不是一件很方便的事情,显然右边的声明看上去有些多余。编译器能根据左边的声明推断右边的类型吗?之前是不行的,在Java7中的代码可以写成下面的样子:
Map<String, List<Trade>> trades = new TreeMap <> ();
是不是很酷?你不需要输入实例类型的完整列表。相反,你使用<>符号,这就是所谓的钻石操作符,请注意,虽然没有声明的钻石操作符是合法的, trades = new TreeMap () ),但它会使编译器生成几个类型安全警告。
在switch语句中使用的字符串
之前的switch语句只能使用原始数据类型或枚举类型。Java 7中引入另一种类型,我们可以在switch语句中使用字符串String类型。
假设我们需要根据状态处理一个交易, 到现在为止,我们使用if - else语句。
private void processTrade(Trade t) {
String status = t.getStatus();
if (status.equalsIgnoreCase(NEW)) {
newTrade(t);
} else if (status.equalsIgnoreCase(EXECUTE)) {
executeTrade(t);
} else if (status.equalsIgnoreCase(PENDING)) {
pendingTrade(t);
}
}
这是一种很粗糙的处理方法,在Java 7中,我们可以利用增强的switch语句,使用String作为参数
public void processTrade(Trade t) {
String status = t.getStatus();
switch (status) {
case NEW:
newTrade(t);
break;
case EXECUTE:
executeTrade(t);
break;
case PENDING:
pendingTrade(t);
break;
default:
break;
}
}
在上面的程序中,状态字段总是使用String.equals() 方法和case标签进行比较。
Automatic resource management
像连接、文件、I/O流一些的资源都需要开发者编写代码手动的关闭,通常我们使用try-finally块负责关闭各自的资源。目前常用的实现如下:
public void oldTry() {
try {
fos = new FileOutputStream("movies.txt");
dos = new DataOutputStream(fos);
dos.writeUTF("Java 7 Block Buster");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
dos.close();
} catch (IOException e) {
// log the exception
}
}
}
然而,Java 7中引入了另一个很酷的功能,自动管理资源。 它操作非常简单。 我们要做的是在try中声明资源,如下:
try(resources_to_be_cleant){
// your code
}
前面的方法oldtry可以使用新功能改写成如下:
public void newTry() {
try (FileOutputStream fos = new FileOutputStream("movies.txt");
DataOutputStream dos = new DataOutputStream(fos)){
dos.writeUTF("Java 7 Block Buster");
}catch (IOException e) {
// log the exception
}
}
上面的代码,也代表此功能的另一个方面:与多个资源的工作。 FileOutputStream和DataOutputStream资源都包含在try语句中一前一后,每一个资源分别由分号分隔(;)。我们不需要去手动的废除或关闭资源,它们会在控制推出try语言块后自动的在后台关闭。需要被自动关闭的资源必须实现java.lang.AutoCloseable接口。
任何实现AutoCloseable接口的资源都会被作为自动资源管理的对象, AutoCloseable是java.io.Closeable 接口的父类,只有close()一个方法,当程序控制推出try语言块时,该方法会被jvm调用。
数字文字用下划线
数值文字是眼睛过滤器。如果给你一个带有十个零的数,我相信你一定会像我一样的开始计算零的个数。识别一个百万甚至千万的数是很容易出错,而且繁琐的。在Java7中可以再确定的地方引入强调符号,例如你可以像下面的方式声明一千:
int thousand = 1_000;
或者一百万
int million = 1_000_000
注意:此版本也引入了binary 二进制文字,开发人员再也不必将它们转换为十六进制了,例如“0B1”。
改进的异常处理
在异常处理方面也有一些改进。Java7引入了多重捕获功能(multi-catch),可以再一个catch块中捕获多种不同类型的异常。
例如,你有一个方法会抛出三个异常,按之前的处理,你需要像下面这样分别处理各个异常:
public void oldMultiCatch() {
try {
methodThatThrowsThreeExceptions();
} catch (ExceptionOne e) {
// log and deal with ExceptionOne
} catch (ExceptionTwo e) {
// log and deal with ExceptionTwo
} catch (ExceptionThree e) {
// log and deal with ExceptionThree
}
}
在catch块中捕获一个又一个的异常,看起来非常杂乱。如代码所示捕获一堆异常,效率非常低下,而且容易出错。 Java 7中带来了一种新的语言变化,来解决这个丑小鸭。 来看看方法的改进版本oldMultiCatch方法如下:
public void newMultiCatch() {
try {
methodThatThrowsThreeExceptions();
} catch (ExceptionOne | ExceptionTwo | ExceptionThree e) {
/ log and deal with all Exceptions
}
}
多个异常在一个catch块中捕获,不同的异常之间用(|)操作符分隔开。使用这种方法你就不需要写许多的捕获异常块。而且,如果你有许多属于不同类型的异常,你可以使用多个multi-catch块, 下面的代码片段说明了这一点:
public void newMultiMultiCatch() {
try {
methodThatThrowsThreeExceptions();
} catch (ExceptionOne e) {
// log and deal with ExceptionOne
} catch (ExceptionTwo | ExceptionThree e) {
// log and deal with ExceptionTwo and ExceptionThree
}
}
在上述案例中,ExceptionTwo和ExceptionThree属于不同层次,所以你会想用一个catch块的不同方法来处理它们。
新的文件系统 API (NIO 2.0)
使用过Java IO的人可能任然记得框架带来的麻烦。 跨操作系统或者多文件系统的无缝使用从来都不一件容易的事情。像删除文件、重命名一类的动作在很多时候都会引起不可意料的结果。 使用符号链接是另一个问题。 总地来说,API需要大修。
为了解决上述Java的IO问题,Java 7的推出了新的API。NIO 2.0带来了许多新的改进,也引入了新的类,方便开发人员处理多文件系统问题。
文件路径
新java.nio.file的包中包含Path, Paths ,FileSystem,FileSystems和其他如类和接口。
Path是一个简单的引用文件的路径。 它是等价(更多的功能) java.io.File 。 下面的代码片断演示了如何获得“Temp”文件夹的路径引用:
public void pathInfo() {
Path path = Paths.get("c:\\Temp\\temp");
System.out.println("Number of Nodes:" + path.getNameCount());
System.out.println("File Name:" + path.getFileName());
System.out.println("File Root:" + path.getRoot());
System.out.println("File Parent:" + path.getParent());
}
控制台会输出如下内容:
Number of Nodes:2
File Name:temp.txt
File Root:c:\
File Parent:c:\Temp
删除一个文件或目录只需要简单的调Files类的delete方法(注意复数)。 Files类公开了两个delete方法,其中一个会抛出NoSuchFileException 另一个则不会。
下面的删除方法调用抛出NoSuchFileException的,所以你必须处理它:
Files.delete(path);
如果文件或目录不存在,Files.deleteIfExists(path) 不会抛出异常。
您可以使用Files.copy(..)和Files.move(..)等通用方法对文件系统进行操作。 同样,使用createSymbolicLink(..)方法创建符号链接。
文件更改通知
在JDK 7,我最喜欢的改善之一,是增加了文件更改通知。 这一直是期待已久的的功能,终于雕刻成NIO 2.0。WatchService API使你会在对象(目录或文件)变化后收到事件通知。
实现API所涉及的步骤是:
· 创建一个WatchService 。 这项服务包括一个持有WatchKeys的队列
· 用这个WatchService注册要监视的目录/文件
· 注册时,指定您希望收到的事件的类型(创建,修改或删除事件)
· 开始一个无限循环监听事件
· 当事件发生时,一个WatchKey被放入队列
· 消耗WatchKey ,并调用它的查询
通过一个例子。 我们创建一个DirPolice Java程序,其责任是检测一个特定的目录。 步骤如下:
1、创建WatchService对象:
WatchService watchService = FileSystems.getDefault().newWatchService();
2、获取到你监视的目录的路径引用。 我建议你把这个目录的参数化,所以你不要硬编码文件名;
path = Paths.get("C:\\Temp\\temp\\");
3、下一步是用WatchService为该目录注册所有类型的事件:
dirToWatch.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
这是java.nio.file.StandardWatchEventKind 事件类型
4、启动无限循环,并开始接受的事件:
while(true){
WatchKey key = watchService.take(); // this would return you keys
…
}
5、通过对关键事件的运行:
for(WatchEvent<?> event : key.pollEvents()) {
Kind<?> kind = event.kind();
System.out.println("Event on " + event.context().toString() + " is " + kind);
}
例如,如果你修改或删除这个临时文件夹,你会在控制台看到入下输出:
Event on temp is ENTRY_MODIFY
Event on temp is ENTRY_DELETE
DirPolice相关方法源代码如下( 下载完整的源代码 ):
try {
watchService = FileSystems.getDefault().newWatchService();
path.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
} catch (IOException e) {
System.out.println("IOException"+ e.getMessage());
}
/**
* The police will start making rounds
*/
private void doRounds() {
WatchKey key = null;
while(true) {
try {
key = watchService.take();
for(WatchEvent<?> event : key.pollEvents()) {
Kind<?> kind = event.kind();
System.out.println("Event on " + event.context().toString() + " is " + kind);
}
} catch (InterruptedException e) {
System.out.println("InterruptedException: "+e.getMessage());
}
boolean reset = key.reset();
if(!reset)
break;
}
}
Fork and Join
在java程序中有效的使用并行内核一直是一个挑战,有一些框架将任务分派到多核上执行,然后合并返回的结果集。Java7纳入这个功能,提供一个fork/join框架。
总地来说,Fork-Join 把待处理的任务逐级分解成小任务,直到所有任务都已经足够简单不需要再分解。它就像一个分治算法。这个框架中的一个重要的概念是最好没有工作线程处于空闲状态。 它实现了工作-窃取算法,空闲线程会从繁忙的工作线程处“窃取”任务。
支持fork-join机制的核心类是ForkJoinPool和ForkJoinTask 。 ForkJoinPool基本上是一个ExecutorService的特别实现类,执行我们上面谈到的工作窃取算法。
我们创建一个ForkJoinPool的实例,提供目标并行级别——处理器的数量,如下所示:
ForkJoinPool pool = new ForkJoinPool(numberOfProcessors)
numberOfProcessors = Runtime.getRunTime().availableProcessors();
但是,默认的ForkJoinPool实例需要设置并行级别为上面获得相同数量。
需要解决的问题写在ForkJoinTask里。 但是,有两个实现类:RecursiveAction和RecursiveTask,这两个类之间的唯一区别是,前者不返回值,而后者则返回指定类型的对象。
以下是如何创建RecursiveTask或RecursiveAction处理前面提到的问题(我使用 RecursiveAction类)
public class MyBigProblemTask extends RecursiveAction {
@Override
protected void compute() {
. . . // your problem invocation goes here
}
}
你必须覆盖需要提供计算功能的方法。 现在,向Executor提供ForkJoinTask,通过调用ForkJoinPool的invoke方法:
pool.invoke(task);
支持动态语言
Java是一种静态类型的语言 ——变量,方法和返回值的类型检查是在编译时进行。 JVM在运行时执行强类型的字节码,而不必担心找到的类型信息。
还有另一种类型的语言品种 - 动态语言。 Ruby,Python和Clojure的都属于这一类。 类型信息在运行时才能确定。 这是不是可能在Java,因为它不会有任何必要的类型信息。
Java 7中,推出的一项称为invokedynamic的新功能。 这使得虚拟机的变化,纳入非Java语言的要求。已经创建了一个新的软件包, java.lang.invoke , MethodHandle , CallSite和其他人组成的,如类,扩展动态语言的支持。
原文地址
分享到:
相关推荐
4. **垃圾收集**:Java SE 7中的垃圾收集算法有分代收集、标记-清除、复制、标记-整理等,通过这些算法优化内存使用,减少停顿时间。 5. **JIT编译器**:JIT(Just-In-Time)编译器在运行时将热点代码编译成机器码...
在Java编程中,调用Google翻译API可以帮助我们实现自动化翻译的功能,这在处理多语言文本或者构建跨语言应用时非常有用。本篇文章将详细介绍如何在Java中使用Google翻译API,并提供一个可直接运行的工具类示例。 ...
【JAVA 翻译文献 中英文全 翻译过来汉字超4000】这份文档集合涵盖了JAVA编程语言的中英文对照翻译,总计含有4674个汉字,如果包含空格则为5701个字符。这样的资源对于学习和理解JAVA技术的中文读者来说,是非常宝贵...
在IT行业中,调用外部服务来增强应用功能是一种常见的做法,比如使用有道翻译API来实现文本翻译。本文将详细讲解如何在Java环境下调用有道翻译API,以实现高效、便捷的多语言翻译功能。 首先,有道翻译API提供了一...
Java API 1.8中文谷歌翻译是针对Java开发者的重要参考资料,它将官方的Java SE 8(Java Standard Edition 8)API文档通过谷歌翻译工具进行了汉化,方便中国开发者理解和使用Java 1.8版本的新特性和接口。这份文档...
2. Nashorn JavaScript 引擎:Java 1.8 中包含了内建的 JavaScript 引擎,允许 Java 程序与 JavaScript 代码交互,为开发人员提供了一种新的动态编程方式。 3. Optional 类:Optional 是一个容器类,代表一个值存在...
在Java开发环境中,为了方便地集成和利用Google的翻译服务,`google-api-translate-java`是一个非常实用的类库。这个库提供了对Google翻译API的封装,使得开发者可以用Java语言轻松地实现多语言之间的文本翻译。下面...
在Java环境中实现微软翻译API,可以帮助我们构建跨语言的应用程序或集成翻译功能到现有的系统中。以下是对这个主题的详细阐述: 一、微软翻译API简介 微软翻译API是Azure认知服务的一部分,提供了丰富的语言支持,...
这个版本在Java发展历程中占据了重要地位,引入了许多新特性,提高了开发效率和性能。中文谷歌翻译版则是针对英文原版的API文档进行了翻译,使得中国开发者能够更方便地理解和使用。 首先,我们来详细了解一下Java ...
在本文中,我们将深入探讨如何使用Java来实现Google翻译API,从而实现在TXT文件中的文本翻译功能。Google翻译API提供了一种便捷的方式,允许开发者在应用程序中集成多语言翻译的能力。下面,我们将详细讲解实现这一...
### JAVA毕业设计外文翻译知识点概述 #### 一、Servlet与JSP技术概览 - **Servlet的作用**:Servlet是一种Java程序,运行在Web或应用服务器上,作为Web浏览器或其他HTTP客户端请求与服务器上的数据库或应用程序...
3. **默认方法**:在接口中,Java 8引入了默认方法(default methods),它们有实现的接口方法,可以在不破坏旧代码的情况下增加新功能。这使得接口能够添加新行为,而无需强制已实现该接口的类进行修改。 4. **...
1. **概述**:谷歌翻译版Java API是一种基于Java编程语言开发的应用程序接口,它允许开发者轻松地集成谷歌翻译的功能到自己的应用程序中。通过这个API,用户可以实现文本翻译、语音识别等多种功能。 2. **特点**: ...
5. **默认方法**:在接口中,Java 8引入了默认方法(default methods),这些方法有具体的实现,可以在不破坏现有实现的情况下为接口添加新功能。例如,`java.util.Comparator`接口就添加了`thenComparing()`等默认...
Java JDK 8是Java开发工具集的一个重要版本,包含了用于编写、编译、调试和运行Java应用程序所需的全部工具和库。这个中文英文帮助文档是...在实际工作中,结合官方英文文档和社区资源,可以更全面地掌握Java 8的精髓。
### JAVA毕业设计外文翻译:JSP技术发展史 #### 一、概述 Java Server Pages (JSP) 是由 Sun Microsystems 公司发起并主导的一种动态网页技术标准,该技术在构建动态网页方面功能强大且不依赖于特定的平台或服务器...
尽管这里的翻译可能不完整,但它仍能为开发者提供大部分关键功能的解释,帮助他们理解和使用Java 1.7中的各种类和方法。 在Java 1.7(也被称为Java 7)中,引入了一些重要的新特性,例如: 1. **类型推断(Type ...
这个中文文档是为初学者和有经验的开发者提供的一份实用参考资料,它详细介绍了 Java 8 的各种功能和使用方法。下面我们将深入探讨一些 Java 8 的核心知识点。 1. **函数式编程**: - **Lambda 表达式**:Java 8 ...
3. **默认方法**:在接口中添加默认方法,使得接口可以在不破坏向后兼容性的情况下增加新的功能。这些方法有一个实现,并且可以在实现接口的类中被重写。 4. **Stream API**:Stream API提供了一种新的数据处理方式...
周志明是远光软件的平台架构师,著有《深入理解Java虚拟机:JVM高级特性与最佳实践》,并且在翻译工作中负责全文统稿以及前言和部分章节的翻译校审。吴璞渊就职于西门子,专注于程序和工作流设计,并在翻译工作中...