java data type은 primitive type과 reference type 이 있으며, primitive type 에는 각각에 대응되는 reference type이 존재하는데 이를 boxing 된 primitive type이라고 한다. ( ex) int - Integer , long - Long )
primitive 타입과 boxing된 primitive type간의 차이점
기본 타입의 값은 언제나 유효하나 (기본값이 존재) , reference type은 null을 가질 수 있다.
메모리측면에서 기본타입이 더 가볍다
기본 타입에 비해 reference type은 값에 더해 식별성(identity)라는 속성을 갖는다. 즉 값이 같아도 서로 다르다고 식별될 수 있다.
publicstaticvoidmain(String[] args)throws IOException { try(InputStream in = new URL(args[0]).openStream()){ in.transferTo(System.out); //url 내용을 console에 출력 } }
특정 기능을 개발하려고 할때, 우선은 표준 라이브러리에서 제공하는지 확인하고, 제공하지 않는다면 서드파티 라이브러리를 활용하고 서드파티 라이브러리에서도 제공하지 않으면 그때 직접 구현하자.
// collection 순회 for(Iterator<Element> i = c.iterator(); i.haxNext(); ){ Element e = i.next(); } // 배열 순회 for(int i = 0; i < a.length ; i++){ //a[i]; }
for문을 사용해 collection과 배열을 순환할 경우, 불필요한 반복자와 인덱스가 사용된다. 또한 collection이냐 배열이냐에 따라 코드 형태와 위와 같이 달라진다.
반면 향상된 for문을 사용할때는 반복자와 인덱스 변수를 사용하지 않고, collection과 배열일때 모두 코드 형태가 동일하다.
1 2 3
for ( Element e : elements ){ // e }
for-each문은 collection과 배열은 물론 Iterable interface를 구현한 객체라면 무엇이든 순회할 수 있다.
method용 문서화 주석에는 해당 method 와 client 사이의 규약을 명료하게 기술해야 한다.
how가 아닌 what 을 기술해야 한다. (어떻게 동작하는지보다 무엇을 하는지를 기술해야 한다.)
client가 해당 method를 호출하기 위한 precondition을 모두 나열해야 한다.
client가 해당 method를 호출한 뒤에 postcondition을 모두 나열해야 한다.
시스템의 어떠한 변화를 가져오는 경우, 문서에 밝혀야 한다.
@param,@return,@thorws 태그
매개변수에 @param 태그 , 반환타입이 void가 아니라면 @return 태그 , 발생할 가능성이 있는 모든 예외에 @throws 태그를 달아야 한다.
관례상 @param 태그 , @return 태그의 설명은 해당 매개변수가 뜻하는 값이나 반환값을 설명하는 명사구를 쓴다.
@throws 태그의 설명은 if로 시작해서 해당 예외를 던지는 조건을 설명하는 절이 뒤따른다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*** * Returns the element at the specified position in this list. --> method가 무엇을 하는지 기술하는 요약 설명 (this:호출된 method가 가르키는 객체) * <p> This method is <i> not </i> guaranteed to run in constant time. * In some complementations it may run in time proportional to element position * * @param index idnex of element to return; must be non-negative and less than the size of this list * @return the element at the specified position in this list * @throws IndexOutOfBoundsException if the index is out of range * ( {@code index< 0 || index >= this.size() }) */
E get(int index);
javadoc utility는 문서화 주석을 HTML로 변환함으로 문서화 주석안의 HTML 요소들이 최종 HTML 문서에 반영된다. {@code} 태그는 코드용 폰트로 렌더링, 이스케이프 기능을 제공한다.
문서화 주석의 첫 번쨰 문장은 해당 요소의 요약 설명으로 간주되며, 이 요약 설명은 반드시 대상의 기능을 고유하게 기술해야 한다. 즉 한 class안에서 요약 설명이 똑같은 멤버가 둘 이상이면 안 된다. (다중정의된 method라고 하여도 허용되지 않는다.)
첫번째 문장의 마무리는 마침표여야 한다. 중간에 의도치 않는 마침표가 들어간 경우에는 @literal 태그 (아래에 설명 ) 를 활용하자
1 2 3 4
/** * A suspect , such as Colonel Mustard or {@listeral Mrs.} Peacok. */ publicclassSuspect{...}
java 10부터는 이 요약 설명부분이 @summary 태그로 분리되었으니, 중간에 마침표를 별도로 literal태그로 감쌀필요가 없다
1 2 3 4
/** * {@summary A suspect , such as Colonel Mustard or Peacok.} */ publicclassSuspect{...}
요약 설명은 method와 생성자의 경우에는 주어가 없는 동사구 여야 한다.
1
- ArrayList (int intialCapacity) : Constructs an empty list with the specified initial capacity
요약 설명은 class,interface,field의 경우에는 대상을 설명하는 명사절이여야 한다.
1
- Instant : An instantaneous point on the time-line.
jdk 8 이전에는 method가 특정 조건에서 값을 반환할 수 없을 때 취할 수 있는 선택지는 null을 반환하거나 , 예외를 던지는 방법이 있었다.
예외를 던지는 경우에는 진짜 예외적인 상황에만 사용해야 하며, null을 반환하는 경우에는 null처리로직이 client코드에 들어가야한다는 단점이 있었다.
jdk 8 이후부터는 Optional API 가 추가되었다.
Optional<T> 는 null 이 아닌 T 타입의 참조값을 하나 담거나, 혹은 아무것도 담지 않을 수 있다.
보통은 T를 반환해야 하지만 특정 조건에서는 아무것도 반환하지 않아야 할때, T 대신 Optional<T>를 반환하도록 선언하면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13
// collection에서 최댓값을 구하는 method로 collection이 비어있으면 IllegalArgumentException을 던진다. publicstatic <E extends Comparable<E>> E max(Collection<E> c){ if(c.isEmpty()){ thrownew IllegalArgumentException("빈 collection"); } E result = null; for (E e : c) { if(result == null || e.compareTo(result)>0){ result = Objects.requireNonNull(e); } } return result; }
위 method를 Optional을 반환하도록 변경하면 다음과 같다.
1 2 3 4 5 6 7 8 9 10 11 12
publicstatic <E extends Comparable<E>> Optional<E> max(Collection<E> c){ if(c.isEmpty()){ return Optional.empty(); } E result = null; for (E e : c) { if(result == null || e.compareTo(result)>0){ result = Objects.requireNonNull(e); } } return Optional.of(result); }
빈 optional은 Optional.empty()
null이 아닌 값이 들어있는 optional은 Optional.of(value)
null일 수 있는 값이 들어있는 optional은 Optional.ofNullable(value)를 사용하면 된다.
주의사항은 optional을 반환하는 method에는 당연히 null을 반환하면 안된다. 이는 API 도입 취지를 완전히 무시하는 행동이다.
추가로 Stream의 max연산을 비롯한 상당수의 종단 연산이 Optional 반환을 지원한다.
collection이나 배열같은 container가 비었을 떄 null을 반환하는 method를 사용할 때면 항상 이와 같은 방어 코드를 넣어주어야 한다.
null을 반환하는 족에서는 빈 container 를 만드는데도 비용이 드니 null을 반환하는게 낫다는 주장도 있지만 이는 잘못된 주장이다. 빈 container를 만드는데는 성능 차이가 미미하며, 굳이 빈 collection 과 배열은 새로 할당하지 않고도 반환할 수 있다.
publicstaticvoidmain(String[] args){ Collection<?>[] collections = { new HashSet<String>(), new ArrayList<BigInteger>(), new HashMap<String,String>().values() };
for (Collection<?> c : collections) { System.out.println(classify(c)); } } }
collection에 set,list,map을 넣어주면 예상결과는 set,list,others인데 실제로는 others만 세번 출력된다. 그 이유는 다중정의(overloading)된 classify증에 어느 method를 실행할지가 compile time에 정해지기 떄문이다. compile time에 for문안의 c는 항상 Collection<?> 타입이다. runtime에는 타입이 매번 달라지지만 호출할 method를 선택하는데는 영향을 주지 못한다.
overloading vs overriding
재정의한 method는 동적으로 runtime에 선택되고, 다중정의한 method는 정적으로 compile time에 선택된다. method를 재정의했다면 해당 객체의 runtime 타입이 어떤 method를 호출할지의 기준이 된다.