자바에서는 내부적으로 자식 클래스의 인스턴스가 생성되기 전에 부모 클래스의 인스턴스가 먼저 생성된다.
하지만 생성자는 상속을 받지 않기 때문에 자식 클래스의 생성자에서 자동으로 부모 클래스의 기본 생성자를 호출한다.
그런데 부모 클래스의 생성자가 매개변수를 갖고 있다면 자동으로 불러오지 않으며
자식 클래스의 인스턴스를 생성할 때 부모 클래스의 인스턴스가 생성되지 못해서 컴파일 에러가 발생한다.
이러한 이유로 부모 클래스에서 기본 생성자가 없다면 직접 자식 클래스의 생성자에서 super()를 통해 부모 클래스의 생성자를 선언해 줘야한다.
여기서 부모 클래스의 인스턴스가 먼저 생성되기 때문에 생성자의 첫번째 줄에 super()를 넣어줘야 한다.
new 자식클래스() -> 부모클래스 인스턴스 생성 -> 자식클래스 인스턴스 생성
자식클래스() {
super() //생략
}
inner class는 프로젝트의 복잡도가 늘어날 수 있기 때문에
중요하지 않고 한 클래스에서만 사용하는 클래스를 inner class로 정의하면 좋다고 생각이 들었다.
inner class의 종류는 크게 inner class와 inner static class로 나누어 진다.
검색을 통해 이펙티브 자바와 여러 블로그에서 inner class를 inner static class로 정의해야 된다는 것을 알게 되었다.
inner static class로 정의해야 하는 이유
추상 클래스는 추상 메서드가 없어도 추상 클래스로 선언할 수 있다.
다음은 추상 클래스가 인스턴스를 생성하지 못하는 것을 이용한 예제이다.
@Entity
@Getter
@Setter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Item {
@Id
@GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
private int stockQuantity;
//생략
Item 추상 클래스를 통해 상속받는 자식 클래스들의 공통 부분을 제거하고
다형성을 통해서 데이터베이스에서 조회할 때 사용할 예정이다. (JPA에서는 다형성을 통한 조회가 가능하다.)
여기서 Item의 자식 클래스만 객체를 생성해서 사용할 것 이라면 부모 클래스의 인스턴스를 생성하지 않을 것이다.
만약 부모 클래스의 인스턴스를 생성하고 싶지 않다면 다음과 같이 추상 클래스로 만들자.
static import를 사용하면 불러오는 클래스의 static멤버(변수와 메서드)를 클래스명 없이 접근할 수 있게 해준다.
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class importTests {
@Test
void default_import() {
Assertions.assertThat("기본 import").isEqualTo("기본 import");
Assertions.assertThat(true).isTrue();
Assertions.assertThat(false).isFalse();
}
@Test
void static_import() {
assertThat("static import").isEqualTo("static import");
assertThat(true).isTrue();
assertThat(false).isFalse();
}
}
첫 번째 메소드는 평소처럼 import를 해서 작성한 코드이고
두 번째 메소드는 static import를 사용해서 작성한 코드이다.
테스트 코드에서는 대부분 Assertions 클래스를 사용해서 검증하기 때문에
테스트 코드를 작성할 때 static import를 주로 사용한다.
자주 사용하는 클래스를 static import로 불러오면 코드를 보기 쉽게 작성할 수 있다.
static import는 Intellij에서 alt + Enter를 누르면 나오는 메뉴에서 편리하게 사용할 수 있다.
객체 생성 시 값을 입력받는 필드는 모두 setter를 정의해줘야 하기 때문에 지양한다.
대신 생성자를 통해 필드에 값을 넣어주거나 빌더 패턴을 사용하는게 좋을 것 같다.
한번만 사용하는것을 객체로 만든다면 클래스 파일의 개수가 증가하게 되면서 프로젝트의 복잡도만 늘어나게 된다.