TIL 2021.02.23

kyukim·2021년 2월 23일
0

TIL

목록 보기
44/322

🧐 TIL (Today I Learned)

1. Try with Resources

Try with Resources는 try block에 리소스들을 선언할때 block이 실행된 이후에 자원이 종료되도록 보증해주는 자바7의 support이다. try 괄호 내에 선언한 객체가 AutoClosable를 구현했다면 try 구문이 끝날때 객체의 close() 메소드를 호출해준다

사용법

// 코드 1

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
    writer.println("Hello World");
}

간단히 말해서, try 괄호안에 선언과 초기화를 동시에하면 끝이다.

Try with Resources 생기기 이전에는?

// 코드 2

Scanner scanner = null;
try {
    scanner = new Scanner(new File("test.txt"));
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}

이런식으로 try-catch-finally 구문을 사용해서 마지막에 항상 스캐너가 닫히도록 했다.

어디서 들은건지 모르겠는데 이 과정에서 리소스에대한 문제?가 있다고 들었는데 공부가 더 필요.

Try with Resources 가 생긴 이후

// 코드 3

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

코드 2와 달리 finally 없이 catch만 해주면 된다.

동시에 선언가능

try (
    Scanner scanner = new Scanner(new File("testRead.txt"));
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
    ) {
    while (scanner.hasNext()) {
	writer.print(scanner.nextLine());
    }
}

try 괄호 내에 ; 세미콜론으로 구분만 해주면 된다.

참고
Java – Try with Resources
Java - Try-with-resources로 자원 쉽게 해제하기

2. 미션 PR 잘읽히는거 VS 잘안읽히는거

오늘 아침엔 히로,우디,트리의 PR을 살펴봤다. 미션 그대로 하라는대로 작성한 코드는 나도 그렇게 작성해서인지 그냥 술술 읽혔다. 우디껀 자기만의 방식으로 많이 한거같아서 읽는데 많은 시간을 소요했다. 근데 코드 많이 읽어봐라는 뜻 속에는 처음보는 구조같은걸 많이 읽어봐라는 거겟지? 그러면 파이로의 코드도 아 모르겠다하고 뒤로 넘길게아니라 이해해보려고 노력해보면서 읽어보는게 좋은거겠지?

익숙한 코드들보다 모르고 우디,파이로 같이 생소한 코드를 많이 보려고 노력해보자(?)

3. 람다식 작성하는 법을 알기전에

람다가 필요한 이유

람다식은 실행을 위해 전달 될수 있는 하나의 코드블럭이다.

원래는 어떤 원하는 하나의 코드블럭이 있다고치면, 먼저 객체를 하나 생성해야한다. 즉 클래스를 하나 만들어서 메소드에 그 코드블락을 담아야한다.

근데 자바8부터는 람다식이 생기면서 이런 함수를 메소드의 인자로 가질수 있게 됐다.

자바8 이전 Sorting

// 코드 1

public class Dog {
	String name;
	int height;
	int weight;
 
	public Dog(String n, int s, int w) {
		this.name = n;
		this.height = s;
		this.weight = w;
	}
 
	public String toString() {
		return getName() + ": size=" + getHeight() + " weight=" + getWeight()
				+ " \n";
	}
 
	//setters and getters ... 
}

코드 1과 같은 Dog 클래스가 있다.

// 코드 2

public class ArraysSort {
 
	public static void main(String[] args) {
		Dog d1 = new Dog("Max", 2, 50);
		Dog d2 = new Dog("Rocky", 1, 30);
		Dog d3 = new Dog("Bear", 3, 40);
 
		Dog[] dogArray = { d1, d2, d3 };
		printDogs(dogArray);
 
		Arrays.sort(dogArray, new Comparator<Dog>() {
			@Override
			public int compare(Dog o1, Dog o2) {
				return o1.getWeight() - o2.getWeight();
			}
		});
		printDogs(dogArray);
	}
 
	public static void printDogs(Dog[] dogs) {
		System.out.println("--Dog List--");
		for (Dog d : dogs)
			System.out.print(d);
		System.out.println();
	}
}

그리고 코드 2에서 dogArray를 sort 하려면 Arrays.sort()를 사용할 수 있다. 두번째 파라미터는 comparator 이므로 comparator를 정의해줘야한다.

자바 8 람다식으로 Sorting 하기

// 코드 3

Arrays.sort(dogArray, (Dog m, Dog n) -> m.getWeight() - n.getWeight());
printDogs(dogArray);

람다식으로 바꾸면 코드 3처럼 굉장히 간결하게 코드를 만들 수 있다.

참고
Why do we need Lambda in Java?

4. Optional 을 배우기전에

the dangers of null

null 참조는 값이 없다는 것을 표시하는 데에 자주 쓰이기 때문에, 많은 문제의 근원이다.
Tony Hoare 라는 컴퓨터 과학자가 null 참조를 개발햇다고 하는데, 심지어 그가 그에 대해서 다음과 같이 사과한 적도 있다고 한다.

"I call it my billion-dollar mistake. It was the invention of the null reference in 1965. I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement."

이런 문제를 덜어줄수 있은 것이 자바 8에서 나온 java.util.Optional이다.

예를 들어 Computer에 대한 객체구조가 다음과 같다고 생각해보자.

String version = computer.getSoundcard().getUSB().getVersion();
위 코드서 발생할 수 있는 문제가 뭘까? 언뜻봐서는 문제가 없어보인다.

근데 어떤 컴퓨터는 사운드카드를 가지고 있지 않을 수도 있다.
그럼 getSoundcar()의 결과는 어떻게 될까?

일반적으로는 사운드카드가 없다는 것을 가리키는 null 참조를 리턴하는 것이다.
다시 말해서, 이 말은 getUSB()가 null 참조의 USB를 반환하려고 시도한다는 것을 의미한다.
따라서, 런타임 중에 NullPointerException가 뜰 것이고 이 의미는 프로그램이 실행 중에 작동을 멈추게 할 것이다.

지금 상황에서 의도하지않은 이 NullPointerException 가 안나오게 예방하려면 어떻게 해야할까?

String version = "UNKNOWN";
if(computer != null){
  Soundcard soundcard = computer.getSoundcard();
  if(soundcard != null){
    USB usb = soundcard.getUSB();
    if(usb != null){
      version = usb.getVersion();
    }
  }
}

위 코드의 문제점은 중첩된 조건문 때문에 코드가 지저분하다. 전체적으로 프로그램의 코드의 가독성을 떨어뜨린다.
그리고 오류가 발생하기 쉬운 프로세스이다. 만약에 저렇게 처리를 했으면 그나마 다행이지만, 어떤 한 속성이 null 일 수 있다는 것을 잊어버렸다면 어떨까?

그래서 null 자체를 사용하는 것은 위험하고 바람직하지 못하다.

여기서 필요한 것은 값이 있는지 없는지를 모델링하는 더 나은 방법이다.

참고
Tired of Null Pointer Exceptions? Consider Using Java SE 8's "Optional"!

느낀점

오늘 쿠퍼 pr 읽으면서 Character.toUpperCase 를 활용해서 representation 관리하시길래 오 이렇게하면 제 코드를 간결하게 바꿀수있을거같아요 했더니 미션5에 딱나온다 와우

2개의 댓글

comment-user-thumbnail
2021년 2월 23일

Kyu는 나만의언어로 정리를 잘하시네요 저도 노력해야겠어요👏👏

1개의 답글