Java 7 (그리고 8)에 포함된 Project Coin 중 유용하지만 (상대적으로) 자주 언급되지 않은 몇 가지.
Binary Literals
Java 7 이전에는 binary 값으로 무언가 하려 하면 ‘parseX’ 메소드를 써야 했다.
예를 들어 “1100110”을 십진수 102로 변수에 지정하려면 아래와 같았다.
|
int x = Integer.parseInt("1100110", 2); |
하지만 Java 7 부터는 아래와 같다. (왠지 너무나 당연하다)
또다른 재미있는 것 하나는, 긴 숫자 사이에 ‘_’ (underscore)를 넣어 표현할 수 있다는 것이다. (Ruby에서 아이디어를 가져왔다고 한다)
이 ‘_’는 compiler가 나중에 다 지워버리기 때문에 상관없다.
아래 예를 보면 가독성이 확실히 차이남을 알 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public class LiteralsExample { public static void main(String[] args) { System.out.println("With underscores: "); long creditCardNumber = 1234_5678_9012_3456L; int bitPattern = 0b0001_1100__0011_0111__0010_1011__1010_0011; // doesn't matter to use '_' more than once System.out.println(creditCardNumber); System.out.println(bitPattern); System.out.println("Without underscores: "); creditCardNumber = 1234567890123456L; bitPattern = 0b00011100001101110010101110100011; System.out.println(creditCardNumber); System.out.println(bitPattern); } } |
TWR(Try-with-resources)
Project Coin 쪽에 본 기능에 대한 제안이 도착했을 때 밝혀진 놀라운 사실 하나는, JDK 내 close()를 사용한 code 60% 이상이 bug를 내포하고 있었다는 것이다. (사실 사용한 resource를 100% 확실하게 close 하는 것이 쉽진 않다)
아래 내용은 TWGJD(The Well-Grounded Java Developer, 2013)에서 가져온 것이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
public class Java6ResourcesExample { private void run() { File file = new File("foo"); URL url = null; try { url = new URL("http://www.google.com/"); } catch (MalformedURLException e) { } InputStream is = null; try { is = url.openStream(); OutputStream out = new FileOutputStream(file); try { byte[] buf = new byte[4096]; int len; while ((len = is.read(buf)) >= 0) out.write(buf, 0, len); } catch (IOException iox) { // Handle IOException from the read or write } finally { try { out.close(); } catch (IOException closeOutx) { // Handle a possible IOException from close() of out } } } catch (FileNotFoundException fnfx) { // Handle FileNotFoundException from openStream() } catch (IOException openx) { // Handle other IOException from openStream() } finally { try { if (is != null) is.close(); } catch (IOException closeInx) { // Handle a possible IOException from close() of is } } } /** * @param args */ public static void main(String[] args) { Java6ResourcesExample instance = new Java6ResourcesExample(); instance.run(); } } |
코드를 보면 InputStream이나 File (즉 OutputStream) 어느 쪽에서도 뭔 일이 벌어질 수 있고, 특히 이런 식으로 exception이 엉켜있게 되면 문제가 생겼을 때 처리하기 여간 성가신 것이 아니다.
그래서, 아래와 같은 문법이 등장했다.
즉 exception이 발생하게 되면 자동으로 모든 열려있는 resource를 close 해준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public class Java7ResourcesExample { private void run() throws IOException { File file = new File("foo"); URL url = null; try { url = new URL("http://www.google.com/"); } catch (MalformedURLException e) { } try (OutputStream out = new FileOutputStream(file); InputStream is = url.openStream()) { byte[] buf = new byte[4096]; int len; while ((len = is.read(buf)) > 0) { out.write(buf, 0, len); } } } public static void main(String[] args) throws IOException { Java7ResourcesExample instance = new Java7ResourcesExample(); instance.run(); } } |
한가지 주의할 점은, 아래와 같은 code는 ObjectInputStream 생성 중 에러가 발생할 경우 FileInputStream을 close 하지 못할 수 있다.
|
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("someFile.bin"))) { ... } |
해결책은, 좀 덜 멋있더라도(?) 분리해놓으면 된다.
아래와 같이.
|
try (FileInputStream fin = new FileInputStream("someFile.bin"); ObjectInputStream in = new ObjectInputStream(fin)) { ... } |