//Object 기반 스택 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 == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] ..
배열과 제네릭의 차이 1) 배열은 공변(함께 변한다)이다. → Sub가 Super의 하위타입이면 Sub[]는 Super[]의 하위타입이 된다. 제네릭은 불공변이다. → 서로 다른 Type1, Type2 가 있으면 List은 List의 하위타입도 상위타입도 아니다. //배열 : 런타임 오류 -> 문제가 있다! Object[]objectArray = new Long[1]; objectArray[0] = "타입이 달라 넣을 수 없다."; // ArrayStoreException을 던진다. //제네릭 : 컴파일 오류 List ol = new ArrayList(); // 호환되지 않는 타입이다. ol.add("타입이 달라 넣을 수 없다."); 2) 배열은 실체화된다. 배열은 런타임에도 자신이 담기로 한 원소의 타..
제네릭 사용시에 컴파일러 경고를 많이 보게 될 것이다. (비검사 경고) 대부분의 비검사 경고는 쉽게 제거할 수 있다. 할수 있는한 모든 비검사 경고를 제거하라. 그러면 타입 안전성이 보장된다. 비검사 경고 예시 Set set = new HashSet(); 위 코드는 구현체 타입을 명확히 작성하지 않고 HashSet 객체를 생성하고 있다. 이는 컴파일러가 아래와 같이 경고를 한다. Set set = new HashSet(); ^ required: Set found: HashSet 컴파일러가 알려준대로 수정하면 경고가 사라지지만, 자바7부터 다이아몬드 연산자()를 지원하기 때문에 그걸로 해결할 수 있다. 다이아몬드 연산자를 사용하면 컴파일러가 올바른 실제 타입 매개변수를 추론해준다. Set set = new..
클래스와 인터페이스 선언에 타입 매개변수가 쓰이면 제네릭 클래스나 제네릭 인터페이스라 한다. 이들을 제네릭 타입이라고 한다. 로 타입 (raw type) 제네릭 타입을 하나 정의하면 그에 딸린 로 타입(raw type) 도 함께 정의된다. 제네릭 타입에서 타입 매개변수를 사용하지 않을 때를 로 타입이라고 한다. ex) List의 로 타입은 List 로 타입을 사용하면 안되는 이유 로 타입은 사용하지 않는 것이 좋다. //Raw type private final Collection stamps = ...; // Stamp 인스턴스만 취급한다. stamps.add(new Coin(...)) // Coin 인스턴스를 add() 한다면 "unchecked call" 경고를 내뱉는다. 위 코드는 컴파일 오류 없이..
톱레벨 클래스가 소스 파일 하나에 들어있으면 심각한 위험을 감수해야한다. //A.java 파일 class A { static final String NAME = "ab"; } class B{ static final String NAME = "cd"; } //B.java 파일 class A { static final String NAME = "ef"; } class B{ static final String NAME = "gh"; } 만약 다른곳에서 A 클래스와 B 클래스를 참조할때 중복 정의이기 때문에 이와 같이 작성하면 안된다. 컴파일러에 어느 소스 파일을 먼저 건네느냐에 따라 동작이 달라지므로 이렇게 사용하면 안된다. 해결방안은 단순히 톱레벨 클래스들을 서로 다른 소스파일로 분리하는 것이다. 굳이 한 ..
중첩 클래스 (nested class) 중첩 클래스는 다른 클래스 안에 정의된 클래스를 말한다. 자신을 감싼 바깥 클래스에서만 쓰여야함 정적 멤버 클래스, (비정적) 멤버 클래스, 익명 클래스, 지역 클래스 정적 멤버 클래스 다른 클래스 내부에서 static으로 선언된 클래스 다른 정적 멤버와 똑같은 규칙 적용 흔히 바깥 클래스와 함께 쓰일때만 유용한 public 도우미 클래스로 사용 public class Calculator { public enum Operation { // 열거 타입도 암시적 static 이다. PLUS, MINUS, MULTIPLE, SUBTRACT } } 비정적 멤버 클래스 다른 클래스 내부에서 static 없이 선언된 클래스 비정적 멤버 클래스 인스턴스는 바깥 클래스 인스턴스와..
태그 달린 클래스 두 가지 이상의 의미를 표현할 수 있고 현재 표현하는 의미를 태그 값으로 알려주는 클래스 public class Figure { enum Shape {RECTANGLE, CIRCLE} // 태그 private final Shape shape; // 이 필드들은 사각형일때만 사용 private final double length; private final double width; // 이 필드는 원형일때만 사용 private final double radius; //원용 생성자 public Figure(Shape shape, double radius) { this.shape = shape; this.length = 0; this.width = 0; this.radius = radius; ..
인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 하는데, 인터페이스는 이 용도로만 사용해야 한다. 상수 인터페이스는 메서드 없이 static final 필드로만 가득찬 인터페이스로, 인터페이스를 잘못 사용한 예이다. //상수 인터페이스 안티패턴 - 사용금지 public interface PhysicalConstants { static final double AVOGADROS_NUMBER = 6.022_140_857e23; static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23; static final double ELECTRON_MASS = 9.109_383_56e-31; } 클래스 내부의 상수는 외부 인터페이스가 아니라 내부 구..