写这篇文章的目的:传统企业,大部分还在用JAVA-6,互联网公司,大部分在使用JAVA-7,JAVA-8还不太普及,所以JAVA-7还不过时,并且有好多人,即便上了JAVA-7或8,也不使用新的特性。so,这篇文章算是一个说明,或者参考吧。
基础语法的改变
一、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的二进制是1100110
int 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(new byte[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));//创建一个临时文件夹
* */
}
}