OracleJDK 7新特性

2018-07-13  本文已影响0人  烤玉米馒头

0. 好记性不如烂笔头

工作这些年,没有很好的整理java相关知识点,从今天开始陆续整理。

1. switch支持使用字符串

jdk7之前switch语句只能使用Integer及与之兼容的类型做分支判断,比如char,short,byte,和对应的包装类Character,Short,Byte;而jdk7则支持使用字符串,如:

public class StringSwitch {

    public static Integer getCode(String name) {
        Integer code;
        switch (name) {
            case "苹果":
                code = 1;
                break;
            case "香蕉":
                code = 2;
                break;

            default:
                code = 0;
        }

        return code;
    }

    public static void main(String[] args){
        System.out.println(getCode("苹果"));
        System.out.println(getCode("香蕉"));
        System.out.println(getCode("梨子"));
    }
}

这一特性是在编译器层面实现的,我们可以通过IDEA反编译看到,其实编译器使用String的hashCode做为判断条件,再加上String的equals:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
public class StringSwitch {
    public StringSwitch() {
    }

    public static Integer getCode(String name) {
        byte var3 = -1;
        switch(name.hashCode()) {
        case 1065923:
            if (name.equals("苹果")) {
                var3 = 0;
            }
            break;
        case 1253072:
            if (name.equals("香蕉")) {
                var3 = 1;
            }
        }

        Integer code;
        switch(var3) {
        case 0:
            code = 1;
            break;
        case 1:
            code = 2;
            break;
        default:
            code = 0;
        }

        return code;
    }

    public static void main(String[] args) {
        System.out.println(getCode("苹果"));
        System.out.println(getCode("香蕉"));
        System.out.println(getCode("梨子"));
    }
}

另,代码中的魔法值,应该使用enum来维护。

2. 数值字面量增强

jdk7之前紧支持十、十六、八进制,而jdk7增加了二进制的支持,并且允许在数值之前增加下划线“_”分隔,这样便于阅读,注意:不能添加在前后,如果在前面添加下划线,那就会歧义,如:_123表示为数值还是为一变量。

public class NumericLiteral {

    public static void main(String[] args) {
        System.out.println(123_456_789);
        System.out.println(0123_456_7);
        System.out.println(0xa23_456);
        System.out.println(0b100__010_0010);
    }
}

3. 异常处理优化

3.1 一个catch子句能捕获多个异常

public class CatchMutiException {

    public static void main(String[] args) {
        try {
            System.out.println(1 / 0);

        } catch (ArithmeticException | NullPointerException | NumberFormatException ex) {
//            ex = null; // 会编译错误
            ex.printStackTrace();
        }
    }

}

捕获的异常多余1个时,ex变量就隐式为final的变量,不能再重新赋值。并且多个异常间不能有父子类关系,其实也可以理解,如若为父子类关系,那其实可以去掉子类异常的捕获了。

3.2 重新抛出异常精准检查

重新捕获异常时,会检查该异常是否能被抛出,而jdk7之前是不会检查的。
如下的代码会编译失败,因为从throwException方法的声明不会抛出CloneNotSupportedException 异常,但可能会抛出NumberFormatException,虽然没有声明,这也就是说只会对受检异常做分析,而非受检异常是无法分析出是否会抛出的。

public class MultiExceptionTypeChecking {

    public static void throwException() throws IOException, ClassNotFoundException {

    }

    public static void main(String[] args) {
        try {
            throwException();

        } catch (CloneNotSupportedException | NumberFormatException | IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}

3.3 Throwable增加addSuppressed、getSuppressed

public class ReadFile {
    public void read(String filename) throws IOException {
        FileInputStream input = null;
        IOException readException = null;
        try {
            input = new FileInputStream(filename);
        } catch (IOException ex) {
            readException = ex;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException ex) {
                    if (readException != null) {
                        readException.addSuppressed(ex);
                    }
                    else {
                        readException = ex;
                    }
                }
            }
            if (readException != null) {
                throw readException;
            }
        }
    }
}

4. try-catch-resouces

jdk7之前需要在finally语句对socket、文件、数据库连接等资源关闭,jdk7后,只有继承AutoCloseable接口就能使用try-catch-resouces语句自动关闭。

public class ResourceBasicUsage {
    public String readFile(String path) throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
            StringBuilder builder = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                builder.append(line);
                builder.append(String.format("%n"));
            }
            return builder.toString();
        }
    }
}

如果使用资源和close都抛异常时,则抛出的是使用资源的异常,并对close的异常addSuppressed;若只有close抛出异常时,则捕获到的是close的异常,这会影响整体的业务受继续执行,所以一般情况,只记录close时的异常,而不抛出,如:

public class ReadFile {
    public void read(String filename) throws BaseException {
        FileInputStream input = null;
        IOException readException = null;
        try {
            input = new FileInputStream(filename);
        } catch (IOException ex) {
            readException = ex;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException ex) {
                    if (readException == null) {
                        ex.printStackTrace(); // 打印异常
                    }else{
                        readException.addSuppressed(ex);
                    }
                }
            }
            if (readException != null) {
                throw new BaseException(readException);
            }
        }
    }
}

5. 泛型初始化语句推测

Map<String, List<String>> map = new HashMap<>();
上一篇 下一篇

猜你喜欢

热点阅读