목록Study/Java (17)
전공공부

함수 객체를 표현하는 방식에는 익명 클래스를 이용하여 함수 객체를 표현하여 사용하였다. 하지만, 익명 클래스의 인스턴스를 함수 객체로 사용하는 것은 낡은 기법이며 코드를 길어지게 한다. Collection.sort(words, new Comparator() { public int compare(String s1, String s2){ return Integer.compare(s1.length(), s2.length()); } }); 기존의 익명 클래스를 활용하여 문자열의 길이를 기준으로 오름차순 정렬을 시도하였다. 해당 코드는 자바8에서는 간결히 표현 할 수 있다. 추상 메서드 하나짜리 인터페이스는 특별한 의미를 인정 받아서 특별한 대우를 받게 되었다. 아래와 같은 람다식으로 말이다. Collection..
결론 열거 타입 자체는 확장 할 수 없다. 하지만 인터페이스를 이용하여 인터페이스를 구현하는 기본 열거 타입을 함께 사용해 확장과 같은 효과를 낼 수 있다. 타입 안전 열거 패턴(typesafe enum pattern) public class TypesafeOperation { private final String type; private TypesafeOperation(String type) { this.type = type; } public String toString() { return type; } public static final TypesafeOperation PLUS = new TypesafeOperation("+"); public static final TypesafeOperation M..
우선 장을 시작하기 전 공변과 불공변의 개념을 집고 넘어가는 것이 좋다. 공변과 불공변의 개념 공변과 불공변은 각각 다음과 같다. 공변(covariant) : A가 B의 하위 타입일 때, T 가 T의 하위 타입이면 T는 공변 불공변(invariant) : A가 B의 하위 타입일 때, T 가 T의 하위 타입이 아니면 T는 불공변 대표적으로 배열은 공변이며, 제네릭은 불공변인데 이를 코드로 살펴보도록 하자. 예를 들어 배열의 요소들을 출력하는 메소드가 있다고 하자. 이때 우리가 변수의 선언 타입은 Integer로, 메소드의 선언 타입은 Object로 해두었다고 하자. void Test() { Integer[] integers = new Long[]{1, 2, 3};//(공변) 컴파일은 되지만 런타임에러 Ar..

1. 상속을 고려한 설계와 문서화의 이해 상속을 사용 할 때 메소드 재정의하면 무슨 일이 일어나는지를 정확히 정리하여 문서로 남겨야 한다. 덧붙여서 어떤 순서로 호출 할 지, 각각의 호출 결과가 이어지는 처리에 어떤 영향을 주는지도 담아야 한다. 더 넓게 말하면, 재정의 가능 메서드를 호출 할 수 있는 모든 상황을 문서로 남겨야 한다. 기존의 API 문서의 메서드 설명 끝에서 종종 "Implementation Requirementss"로 시작하는 절을 볼 수 있는데, 그 메서드의 내부 동작 방식을 설명하는 곳이다. 다음 예는 java.util.AbstractCollection 에서 발췌한 예이다. 내부 동작 방식을 설명하는 이유 /** * {@inheritDoc} * * @implSpec * This i..

Cloneable은 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스이지만, clone 메서드가 정의된 곳이 Object 클래스이고 그마저도 protected이다. 그래서 Cloneable을 구현 하는 것 만으로는 외부 객체에서 clone을 사용 할 수 없다. Cloneable을 이례적으로 Object 클래스의 protected 메서드인 clone의 정의를 정의한다. 일반적으로는 인터페이스에서 정의한 기능을 클래스에서 받아서 사용하는 행위를 진행하는데, Cloneable의 경우 상위 클래스에 정의된 protected 메서드의 동작 방식을 변경한다. 그래서 Object.clone() 을 만약 바로 불러서 내부적으로 구현하여 사용 하려고 하면 아래의 설명을 참고하면 throws CloneNotSup..

자바는 Managed Language로써 일반적으로 언어상에서 메모리를 관리해주는 언어이다. 그래서, 메모리를 직접 관리하지 않아도 된다고 착각 할 수 있는데 이는 사실이 아니다. 예시 코드 public class Stack{ private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack(){ elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e){ ensureCapacity(); elements[size++] = e; } public Object pop(){ if(size ..
문제점 정적 팩토리, 생성자는 선택적 매개변수가 많을 때 적절하게 대응하기 어렵다. 예시 Code 식품 포장의 영양정보를 표현하는 클래스를 생각해보자. 영양정보는 1회 내용량, 총 n회 제공량, 1회 제공량당 칼로리 같은 필수 항목 몇 개와 총 지방, 트랜스 지방, 포화지방, 콜레스테롤, 나트륨 등 총 20개가 넘는 선택 항목으로 이뤄진다. 그런ㄴ데 대부분 제품은 이 선택항목 중 대다수의 값이 그냥 0이다. 1. 점층적 생성자 패턴 각 생성자의 매개변수 개수를 다르게 만들어, 여러 개의 생성자를 만드는 방식이다. 예시 public class NutritionFacts { private final int servingSize; private final int servings; private final in..
기본 타입 int, double, boolean, ... 박싱된 기본 타입 Integer, Double, Boolean, ... 그리고, 기본 타입과 달리 박싱된 기본 타입은 식별성을 가지기 때문에 두 변수가 값이 같아도 서로 다르다고 식별되어진다. 또한, 기본 타입과 달리 박싱된 기본 타입은 null 값을 가질 수 있다. 그래서, 위 점들을 유의하지 않고 사용하게되면 정말로 문제가 발생할 수 있다. 코드 1 Comparator naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1); 위 코드를 기준으로 naturalOrder.compare(new Integer(42),new Integer(42)); 를 실행하면 두 값이 같으므로 0을 출력하는 것이 맞지만 ..