Java 10 에서 var 재대로 사용하기 2탄

Composite·2020년 7월 27일
1

내가 예전 포스트 에서 var 문을 재대로 다루는 방법을 공유했었다.

만약에 이게 다라고 생각했으면, 굳이 var 문을 쓸 필요가 없을 것이다.
자, 내가 또 제시할 것이 생겼다. 이정도면 var 문 쓸 때 매력이 생길 것이다.

제네릭

자바 7에서부터 제네릭 선언 시 간결하게 선언하는 다이아몬드 연산자가 생겼다.

List<String> strList = new ArrayList<>();

그렇다면 이걸 var 로 줄이면?

var strList = new ArrayList<String>();

그렇다. 안타깝게도 var 는 제네릭 타입을 추론할 수 없기 때문에 다이아몬드를 못 쓰고 명시적으로 제네릭을 선언해 줘야 한다.
물론 글자 수는 좀 작아지지만, 그래도 딱히 매력이 없다.
하지만, 제네릭 타입이 명확한 메소드를 제공한다면 이야기는 달라진다.
스프링을 많이 썼다면 JSON을 다루는 Jackson도 다루어 봤을 것이다.
여기서 var에 진가가 드러난다.

var mapper = new ObjectMapper();
var myData = mapper.readValue(jsonString, mapper.getTypeFactory().collectionType(List.class, String.class));

이렇게 하면 myData의 타입 추론 결과는 바로 List<String> 이 되시겠다.
사실 제네릭 속 제네릭은 자바의 개같은 객체 소멸(Type Erasure) 때문에 정의와 선언이 엄청나게 까다롭다. 특히 Collection 계열이나 Map 을 많이 쓸 때 제네릭 때문에 의도한 코드가 이상하게 동작하지 않거나 컴파일 오류를 뱉거나 하는 등의 막히는 일도 일상다반사.
그래서 몇몇 라이브러리는 이런 불편함을 해소시켜줄 제네릭 헬퍼를 제공하는데, 그나마 가장 많이 쓰는 Jackson 을 예로 든 것이다.

하지만 안타깝게도 이런 식은 안 된다.

var emptyList = Collections.emptyList();

제네릭 타입이 모호하기 때문이다. 물론 런타임에서는 이게 무슨 의미냐 싶겠지만 컴파일러는 안타깝게도 받아주지 않는다. 그래서 아래처럼 해야 한다.

var emptyList = Collections.<String>emptyList();
// 아래와 같다
List<String> emptyList = Collections.emptyList();

return 변수

물론 intString 같은 간단한 타입이라면 기존 방식이 오히려 명확하겠지만, 복잡한 클래스나 제네릭이 들어갈 때 return 값이 확실하다면, var를 쓰는 게 유리하다. 예를 들면,

public ConcurrentMap<String, Person> getPersonMap() {
  var result = new ConcurrentHashMap<String, Person>();
  // ... 이것저것 처리
  return result;
}

타이핑이 간결하면서도 사람이 그나마 타입 추론이 쉽기 때문이다. return 만 알 수 있으면 되기 때문이다. 간단하다.

이래도 매력이 없는가? 사실 취향이다. 기존 방식 써도 상관 없다.
나는 강요하지 않았고, 강요할 생각도 없다.
하지만 var 문에 대해 접근할 생각이 조금이라도 있다면,
그걸 내가 도움을 주기 위해 이렇게 하는 것 뿐이다.

그럼 즐거운 모던 자바를 즐기기 바란다.
끗.

profile
지옥에서 온 개발자

0개의 댓글