35.2K
Java 7에는 개발자들이 좋아할만한 많은 특징들이 있다. switch구문에서 사용하는 String, 다중 exception처리multi-catch exception), try-with-resource 구문, 새로운 파일시스템 API, JVM의 확장, 동적 타입의 언어에 대한 지원, 유사한 작업을 위한 fork와 join 프레임워크 등 분명히 많은 곳에서 수용되어질 것이다.
Map이런 선언에 대한 안 좋은 점은 오른쪽에 있는 선언이 불필요하게 보일지라도 우리는 양쪽에 타입을 선언해야만 한다는 것이다. 왼쪽에만 선언한 것으로 컴파일러가 타입을 추측할수 있을까? Java 7을 사용하지 않으면 불가능하다. Java 7에서는 아래와 같이 작성한다.> trades = new TreeMap > ();
Map얼마나 멋진가? 당신은 인스턴스를 생성하기 위해서 전체 타입을 입력할 필요가 없다. 대신 다이아몬드 지시자라고 불리는 <> 기호를 사용한다. trades = new TreeMap() 과 같이 다이아몬드 지시자를 선언하지 않는 것은 허용되지만 컴파일러가 Type safety warning을 발생시킨다.> trades = new TreeMap <> ();
private void processTrade(Trade t) {
String status = t.getStatus();
if (status.equalsIgnoreCase(NEW)) {
newTrade(t);
} else if (status.equalsIgnoreCase(EXECUTE)) {
executeTrade(t);
} else if (status.equalsIgnoreCase(PENDING)) {
pendingTrade(t);
}
}
String으로 동작하는 이 메서드는 대충 만들었다. Java서에서 우리는 String 타입을 변수로 받는 향상된 Switch문을 활용하여 이 메서드를 향상시킬수 있다.
public void processTrade(Trade t) {
String status = t.getStatus();
switch (status) {
case NEW:
newTrade(t);
break;
case EXECUTE:
executeTrade(t);
break;
case PENDING:
pendingTrade(t);
break;
default:
break;
}
}
위에 프로그램에서는, 상태 필드를 계속 String.equals() 메서드를 사용한 case label과 비교하였다.
public void oldTry() {
try {
fos = new FileOutputStream("movies.txt");
dos = new DataOutputStream(fos);
dos.writeUTF("Java 7 Block Buster");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
dos.close();
} catch (IOException e) {
// log the exception
}
}
}
그러나, Java 7은 자동으로 리소스를 관리하는 훌륭한 기능을 소개하고 있다. 동작 또한 간단하다. 우리가 해줄 것은 try문 안에 아래와 같이 자원을 선언하는것 뿐이다.
try(resources_to_be_cleant){
// your code
}
예전 try문을 사용한 위의 메소드는 아래 보여지는 것처럼 이 새로은 기능을 사용하여 다시 작성될 수 있다.
public void newTry() {
try (FileOutputStream fos = new FileOutputStream("movies.txt");
DataOutputStream dos = new DataOutputStream(fos)) {
dos.writeUTF("Java 7 Block Buster");
} catch (IOException e) {
// log the exception
}
}
위의 코드는 또한 이 특징의 다른 측면도 보여주고 있다 : 여러개 자원들에 대해서도 동작을 한다. FileOutputStream과 DataOutputStream 은 각각 세미콜론(;)으로 나눠서 차례로 try 문 안에 쌓여있다.
int thousand = 1_000;1000000은 아래와 같다.
int million = 1_000_000이번 릴리즈에는 2진수에 대한 것도 소개 되었다. 예를 들어 "0b1"과 같이 2진수도 표현할 수 있어서 개발자들이 더 이상 16진수로 이것을 변환하지 않아도 된다.
public void oldMultiCatch() {
try {
methodThatThrowsThreeExceptions();
} catch (ExceptionOne e) {
// log and deal with ExceptionOne
} catch (ExceptionTwo e) {
// log and deal with ExceptionTwo
} catch (ExceptionThree e) {
// log and deal with ExceptionThree
}
}
catch 블록 안에 여러개의 예외를 차례로 처리하는 모습은 어수선해 보인다. 나는 12개의 예외를 잡는 코드를 본적도 있다. 이것은 믿을 수 없을 정도로 비효율적이고 오류를 범하기 쉽다. Java 7은 이 미운 오리새끼를 다루기 위해 언어에 새로운 변화를 가져왔다. 아래에 oldMultiCatch 메서드의 향상된 버전을 보자.
public void newMultiCatch() {
try {
methodThatThrowsThreeExceptions();
} catch (ExceptionOne | ExceptionTwo | ExceptionThree e) {
// log and deal with all Exceptions
}
}
여러개의 예외들은 "|" 연산자를 사용해서 1개의 catch블록 안에서 처리된다. 이 방법으로 더이상 12개의 catch문을 작성할 필요가 없다. 그러나 다른 타입에 속하는 여러 개의 예외가 있다면 "multi multi-catch" 블록을 이용하면 된다. 아래 예제에는 이 내용을 보여주고 있다.
public void newMultiMultiCatch() {
try {
methodThatThrowsThreeExceptions();
} catch (ExceptionOne e) {
// log and deal with ExceptionOn
} catch (ExceptionTwo | ExceptionThree e) {
// log and deal with ExceptionTwo and ExceptionThree
}
}
다른 분류에 속하는 ExceptionTwo와 ExceptionThree는 다르게 분리되었지만, 하나의 catch블록에서 처리되어있다.
public void pathInfo() {
Path path = Paths.get("c:\Temp\temp");
System.out.println("Number of Nodes:" + path.getNameCount());
System.out.println("File Name:" + path.getFileName());
System.out.println("File Root:" + path.getRoot());
System.out.println("File Parent:" + path.getParent());
}
실행 결과는 다음과 같다.
Number of Nodes:2 File Name:temp.txt File Root:c: File Parent:c:Temp파일이나 디렉토리를 삭제하는 것은 Files 클래스에 있는 delete 메서드를 호출하는 것만큼 간단하다. Files 클래스는 NoSuchFileException을 처리하는 것과 처리하지 않는 2개의 delete 메서드를 가지고 있다.
Files.delete(path);만약 file 또는 디렉토리가 존재하지 않는다면 예외를 던지길 기대하더라도 Files.deleteIfExists(path)은 예외를 던지지 않는다.
WatchService watchService = FileSystems.getDefault().newWatchService();2. 볼수있는 디렉토리의 참조경로를 가져온다. 나는 파일명을 하드코딩하지말고 파라메터로 전달하기를 추천한다.
path = Paths.get("C:\Temp\temp\");
3. 다음 단계는 모든 종류의 이벤트를 WatchService 에 등록한다.
dirToWatch.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);이 타입들은 java.nio.file.StandardWatchEventKinds 에 정의된 이벤트 타입들이다.
while(true)
{
WatchKey key = watchService.take(); // this would return you keys
}
5. 키 이벤트들을 통해 실행된다.
for (WatchEvent> event : key.pollEvents()) {
Kind> kind = event.kind();
System.out.println("Event on " + event.context().toString() + " is " + kind);
}
예를들어, temp 디렉토리를 수정하거나 삭제하면 콘솔창에 각각 아래와 같은 문장을 보게 될것이다.
Event on temp is ENTRY_MODIFY Event on temp is ENTRY_DELETEDirPolice 소스와 과련된 메서드는 아래에 게시되어있다. (전체 소스코드 다운로드)
/**
* This initiates the police
*/
private void init() {
path = Paths.get("C:\Temp\temp\");
try {
watchService = FileSystems.getDefault().newWatchService();
path.register(watchService, ENTRY_CREATE, ENTRY_DELETE,
ENTRY_MODIFY);
} catch (IOException e) {
System.out.println("IOException"+ e.getMessage());
}
}
/**
* The police will start making rounds
*/
private void doRounds() {
WatchKey key = null;
while(true) {
try {
key = watchService.take();
for (WatchEvent> event : key.pollEvents()) {
Kind> kind = event.kind();
System.out.println("Event on " + event.context().toString() + " is " + kind);
}
} catch (InterruptedException e) {
System.out.println("InterruptedException: "+e.getMessage());
}
boolean reset = key.reset();
if(!reset)
break;
}
}
ForkJoinPool pool = new ForkJoinPool(numberOfProcessors)여기서 numberOfProcessors = Runtime.getRunTime().availableProcessors();
public class MyBigProblemTask extends RecursiveAction {
@Override
protected void compute() {
. . . // your problem invocation goes here
}
}
당신은 computing 기능을 필요하는 곳에 compute 메서드를 오버라이드 해야한다. 그리고 ForkJoinPool 안에 있는 호출 메서드 부름으로써 ForkJoinTask를 Executor에 전달한다.
pool.invoke(task);
댓글