try { // do something } catch (Exception1 | Exception2 | Exception3 ex) { ex.printStackTrace(); }
바(|)를 통해 여러가지 예외를 한번에 catch 할 수 있다.
java.lang.AutoCloseable 인터페이스를 구현한 리소스는 finally 블록에서 명시적으로 close()하지 않아도 자동으로 close()를 무조건 호출 할 수 있게 되었다.
과거에는 finally 블록에서 명시적으로 다음과 같이 close()를 호출해줘야만 리소스를 닫아줄 수 있었다.
// Java7 이전 BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("C:/Windows/system32/drivers/etc/hosts")); String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } } finally { if (reader != null) { try { reader.close(); } catch (Exception ex) { // ignored } } }
위와 같은 코드가 Try With Resource 블록을 사용하면 아래와 같이 된다. catch 블록이 없어도 된다는 사실에 주의.
// Java7 try (BufferedReader reader = new BufferedReader(new FileReader("C:/Windows/system32/drivers/etc/hosts"))) { String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } }
try () 안에서는 세미콜론으로 구분하여 여러개의 리소스를 생성해도 된다.
catch 절에서 예외를 잡아서 다시 던질 때, Java 7 이전에는 catch 절에서 잡는 타입에 따라 해당 메소드의 throws 절이 결정되었었다.
public static class FirstException extends Exception { } public static class SecondException extends Exception { } public static void rethrowException(String msg) throws Exception { try { switch (msg) { case "First": throw new FirstException(); default: throw new SecondException(); } } catch (Exception ex) { throw ex; } }
즉, rethrowException 메소드는 catch (Exception ex) 때문에 항상 throws Exception으로 선언되어야 했었다. 하지만 Java 7 부터는 try 블록에서 실제로 발생 가능한 예외를 컴파일러가 분석하여, catch 절과 무관하게 throws 할 예외 클래스를 지정할 수 있게 되었다.
다음과 같이 FirstException
과 SecondException
을 명시해 주는게 가능해 진다.
public static void rethrowException(String msg) throws FirstException, SecondException { try { switch (msg) { case "First": throw new FirstException(); default: throw new SecondException(); } } catch (Exception ex) { throw ex; } }
문자열을 switch/case 구문에 사용할 수 있게 되었다.
Console console = System.console(); String value = console.readLine("입력 : "); switch(value) { case "A": System.out.println("A"); break; case "B": System.out.println("B"); break; case "some": System.out.println("some"); break; default: System.out.println("Don't know..."); }
Generic 객체를 생성할 때 선언이 올바로 되어 있으면 객체 생성 구문에서 제너릭타입을 지정하지 않고 <>
만 사용해도 된다.
public static void main(String[] args) throws Exception { // 앞부분의 선언 때문에, 객체 생성 구문에서는 제너릭 타입 지정 불필요 List<String> strings = new ArrayList<>(); } public static Map<String,Long> getValues() { // 메소드 선언의 제너릭타입 지정 때문에, return 문에서도 Diamond Operator 사용 가능 return new HashMap<>(); }
byte,short,int,long 형을 0B숫자
를 사용해 이진수로 표현할 수 있다. Binary Literals
int binary = 0B10; System.out.println(binary); // 2 binary = 0B11111111; System.out.println(binary); // 255
숫자값에 밑줄(_)을 써도 되며 밑줄은 그냥 무시된다. 숫자의 가독성을 높이는데 사용하면 된다.
long creditCardNumber = 1234_5678_9012_3456L; long socialSecurityNumber = 999_99_9999L; float pi = 3.14_15F; long hexBytes = 0xFF_EC_DE_5E; long hexWords = 0xCAFE_BABE; long maxLong = 0x7fff_ffff_ffff_ffffL; byte nybbles = 0b0010_0101; long bytes = 0b11010010_01101001_10010100_10010010;
MethodHandle을 사용하면 메소드를 객체로 전달하는 것이 가능해진다. Vanilla Java: MethodHandle performance in Java 7를 참조하였다.
아래는 multiply 메소드를 MethodHandle 객체로 만든 뒤에 해당 메소드를 호출하는 것을 보여준다.
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; public class Java7Test { public static int multiply(int i, int j) { return i * j; } public static void main(String[] args) throws Throwable { Lookup lookup = MethodHandles.lookup(); MethodHandle multiply = lookup.findStatic(Java7Test.class, "multiply", MethodType.methodType(int.class, int.class, int.class)); System.out.println(multiply.invoke(5,6)); // multiply(5,6) 호출 // 1번 인자로 4를 미리 지정해둔다. MethodHandle quadruple = MethodHandles.insertArguments(multiply, 1, 4); System.out.println(quadruple.invoke(5)); // multiply(4,5) 호출 } }
synchronized
때문에 성능이 저하됨.// 대부분 아래와 같은 형태로 사용하면 된다. ThreadLocalRandom.current().nextX(...)
-XX:-UseSplitVerifier
옵션을 주면 일단 넘어갈 수 있다.