java7新特性一览表
基础语法的改变
一、switch语句中的String
在java6中,switch语句中的case中的常量只能是byte/char/short/int,或者是枚举常量。java7中新增加了String类型,这使得switch适用的场景更多了。
private static void switchString(String str){
switch(str){
case "one":
System.err.println("1");
break;
case "two":
System.out.println("2");
break;
default :
System.out.println("err");
}
}
二、二进制文本
在java7之前,如果想处理二进制,就必须借助棘手的基础转换。比如:想让int x用位模式表示十进制102,需要如下方式
//102的二进制是1100110int x = Integer.parseInt("1100110" ,2); //java7之前语法int x_new = 0b1100110; //java7语法/***加0b表示二进制*加0 表示八进制*加0x表示十六进制*/
三、数字中的下划线
java7中允许将过长的数组用“_”隔开,以便阅读。例如:
long a = 23_23_98L; //输出232398L
四、改善后的异常处理
异常处理有两处改进 —— multicatch
和final重抛
。
multicatch
try {}catch (FileNotFoundException | UnknownHostException e){//文件类异常和主机类异常}catch (IOException ex){//IO异常}
就是比如需要抛出多个异常的时候,可以讲多个异常合并到一个catch中。
final重抛
所谓final重抛
就是当我们catch异常的时候,偷懒使用Exception强制替换多个异常类型时,异常的真是类型将会被覆盖。
如果使用我们如下方式:
try {}catch (final Exception e){}
这样,不仅可以偷懒,而且还可以抛出真实的异常类型。
try-with-resources
(TWR)
TWD:是把资源的作用域限定在代码快内,当程序离开这个代码快时,资源会被自动关闭。(这个真的很重要,因为没人会在手动关闭资源时100%正确。并且,JDK中有三分之二的close()用法都有Bug。)
public void writeFile(File file){try (OutputStream out = new FileOutputStream(file)){ out.write(newbyte[4096]); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }}
在try语句块中,构建资源,使用完后,会自动关闭。但是需要注意,不可以这么写:
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("aaa.txt"))){} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}
原因在于如果“aaa.txt”文本不存在,或者出现问题,FileInputStream
是无法关闭的,只能关闭ObjectInputStream
,所以需要分开构建。
try (FileInputStream fi = new FileInputStream("aaa.txt");ObjectInputStream in = new ObjectInputStream(fi)){} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}
五、实现equals、hashCode和CompareTo方法
- 安全的比较
在进行对象比较的时候,比如要比较两个String的对象是否相等,JAVA6的实现方式:
String a = null;String b = "aa";String d = "aa";System.out.println("a==b?" + a.equals(b));System.out.println("b==a?" + b.equals(a));System.out.println("b==d?" + b.equals(d));
第一个输出语句,结果是抛出:java.lang.NullPointerException
第二个输出语句,结果是false
第三个输出语句,结果是true
so,在java6的时候,我们比较对象时,还需要判断一下对象时候为null,相当蛋疼。来看看JAVA7的改进吧
String a = null;String b = "aa";String d = "aa";System.out.println("a==b?" + Objects.equals(a,b));System.out.println("b==d?" + Objects.equals(b,d));
第一个输出语句,结果是false
第二个输出语句,结果是true
来看下Objects.equals()
的远吗,一目了然:
public static boolean equals(Object a, Object b) {return (a == b) || (a != null && a.equals(b));}
- 比较数值类型
JAVA7之前,在进行计算时会出现这样的问题,比如:
public static String compare(int x ,int y){int diff = x - y;if (diff > 0) return"x > y";return"x < y";}public static void main(String[] args) {int x = 2147000000;int y = -483650; System.out.println(Test.compare(x , y));}
按理说,返回结果应该是:”x > y”。可是,输出的结果偏偏是:”x < y”。
为什么呢?原因在于,int类型的范围是:-2147483648~2147483647,计算结果超出范围了,diff=-2147483646。解决方案是:将int diff = x-y;
改成int diff = new Integer(x).compareTo(y);
JAVA7的解决方案简化了这一操作:int diff = Integer.compare(x,y);
不只是int,Short,Long,Byte,Boolean均有该方法。
六、其他改进
- 计算HASH码
Objects.hash(a,b...);
可以传入可变参,生成hash码。
- NULL 检查
Objects.requireNonNull(null);Objects.requireNonNull(null,"this is null");
requireNonNull()
方法不仅方便检查对象是否为null,还可以输出自定义的异常语句。这样可以快速定位问题地点。
- 全局日志打印
System.out.println()
带来的问题:会严重影响服务器性能,比如我们使用Tomcat作为web容器,输出语句会频繁向log日志中频繁写入,访问量越大,写入量就越大。Log
日志的优势:可以控制日志级别,在上线的系统中打印error级别的日志,在开发环境打印全部级别等等。高级的日志系统还可以做到将日志输出到指定文件,并且控制文件大小等功能。
public static void main(String[] args) throws IOException, InterruptedException {//Level级别有 信息:INFO、警告:WARNING、严重:SEVERE、禁用:OFF Logger.getGlobal().log(Level.INFO,"打印一条INFO日志。");}
- 执行外部命了的方法
JAVA执行linux命令或者DOS命令的方式。不仅可以执行,还可以将结果定向输出。
public static void main(String[] args) throws IOException, InterruptedException {
//每个空格隔开的命令,就是一个字符串。比如linux命令:ls -al,在ProcessBuilder中就是new ProcessBuilder("ls","-al")
ProcessBuilder builder = new ProcessBuilder("grep","-o","[A-Za-z][A-Za-z_0-9]*");
//将标准输入、输出和错误流重定向到文件中
builder.redirectError(Paths.get("Error.java").toFile());
builder.redirectInput(Paths.get("Input.java").toFile());
builder.redirectOutput(Paths.get("Input.java").toFile());
//将结果输出到控制台
builder.inheritIO();
//执行
builder.start().waitFor();
}
NIO.2
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
/**
* User: R&M www.rmworking.com/blog
* Date: 17/1/3
* Time: 21:16
* Test
* org.thinkInJava
*/
public class FileOperation {
/**
* 文件读写操作
*
* @param fileName
* @throws IOException
*/
public void fileWriteAndRead(String fileName) throws IOException {
Path p = Paths.get(fileName);
System.out.println("文件夹名称: " + p.getFileName());
System.out.println("父路径名称: " + p.getParent());
System.out.println("根路径名称: " + p.getRoot());
//将字符串写入文件
String content = "测试JAVA7的文件写入功能!!!";
Files.write(p, content.getBytes(StandardCharsets.UTF_8));
//按照行来写入文件,并且追加到原文件末尾
List<String> lines = new ArrayList<>();
lines.add("苹果。。。");
lines.add("香蕉。。。");
lines.add("橙子。。。");
Files.write(p, lines, StandardOpenOption.APPEND);
//文件读取
byte[] bytes = Files.readAllBytes(p);
String result = new String(bytes, StandardCharsets.UTF_8);
System.out.println(result);
}
/**
* 文件夹操作
*
* @param filePath
* @throws IOException
*/
public void fileOperation(String filePath) throws IOException {
Path p = Paths.get(filePath);
//判断父目录是否存在,如果不存在则创建
System.out.println(Files.exists(p.getParent()));
if(Files.exists(p.getParent())){
Files.createDirectory(p);
}else{
Files.createDirectories(p);
}
}
/**
* 删除文件或文件夹
* @param fileNames
* @throws IOException
*/
public void delFies(String... fileNames) throws IOException {
for (String fileName : fileNames){
Path p = Paths.get(fileName);
// if(Files.exists(p)){
// Files.delete(p); //这个方法是需要判断是否存在目录的
// }
//这个方法是可以允许空文件或者文件夹
Files.deleteIfExists(p);
}
}
public static void main(String[] args) throws IOException {
FileOperation fo = new FileOperation();
String fileName1= "XXX/demo.txt";
String fileName2 = "XXX/demo";
fo.fileWriteAndRead(fileName1);
fo.fileOperation(fileName2);
fo.delFies(fileName1 , fileName2);
/**其他还有一些 Files
* Files.move(p); 移动文件
* Files.copy(); 复制一个文件
* Path p = Files.createTempFile(null, ".TXT");//创建一个临时文件
* System.out.println(p.getParent() + "/" + p.getFileName());
* Path p = Files.createDirectory(Paths.get(fileName1));//创建一个临时文件夹
* */
}
}