인터페이스 , Enum

DeadWhale·2023년 2월 18일
0

JAVA

목록 보기
3/10

인터페이스는 메소드의 시그니처만 정의한다

  • 인터페이스를 상속하면 인터페이스에 명시된 모든 메소드를 반드시 구현해야 한다.
    (8버전부터 default 기능이 추가되었다.)
  • 추상 클래스와 다르게 다중의 상속이 가능하다.
  • 인터페이스는 변수를 가질 수도 있지만 해당 변수들은 final static 변수이다
  • 적지 않을 경우에는 묵시적으로 생성된다.

인터페이스의 장점

추상화

  • 클래스의 세부 구현 정보를 공개 인터페이스에서 분리할 수 있다.

다형성

  • 공통 인터페이스를 공유하는 다른 클래스의 개체와 함께 작동할 수 있는 코드를 작성할 수 있다.

다중상속

  • 추상 클래스와 다르게 여러 인터페이스를 상속 받을 수 있다.

코드의 재사용성

  • 여러 클래스에서 공통적으로 활용되는 메소드의 속성을 정의할 수 있어 효율적으로 구현할 수 있다.

계약

  • 인터페이스와 클래스간의 계약을 정의하는 방법을 제공한다.
  • 인터페이스를 구현하여 클래스는 호출할 때. 특정한 규칙이 요구되어 안정성과 유지 관리가 편해진다.

테스트

  • 실체 구현할 객체와 동일한 모의 개체같이 활용해 테스트 하고싶은 케이스를 분리해
    연관된 다른 클래스와 종속성을 피할 수 있다.

자바 8 부터는 default method를 지원한다. 활용할 경우
인터페이스에서 메소드 시그니처만 정하는 것이 아닌 기본적인 구현을 할 수 있따.

interface MyInterface {
    void myMethod();

    default void myDefaultMethod() {
        System.out.println("This is a default method.");
    }
}

Enum 클래스

상수

  • enum 클래스는 상수집함을 의미한다. 가장 핵심적인 멤버

유일성

  • 핵심적인 멤버인 각각의 상수는 중복없이 유일해야 한다.

메소드

  • 메소드를 가질 수 있고 상수 집합을 처리하는데 사용된다.
  • 스위치 같이 어느 상수 범위에 속하는지 검증 할 수 있다.

타입 안정성

  • 컴파일 시 타입 안정성을 보장 할 수 있다.
  • 클래스 내부에 정의된 상수 외에 다른값이 사용될 여지가 없어서 그렇다

  • 컴파일 시 값의 유효성을 검증할 수 있다.
  • switch를 활용해 가독성을 높일 수 있다.
  • 상수에 대한 추가적인 정보도 보관해 유연하게 사용할 수 있다.

예시 코드


@Getter
public enum Week {
    MONDAY(1, "Monday", "Mon"),
    TUESDAY(2, "Tuesday", "Tue"),
    WEDNESDAY(3, "Wednesday", "Wed"),
    THURSDAY(4, "Thursday", "Thu"),
    FRIDAY(5, "Friday", "Fri"),
    SATURDAY(6, "Saturday", "Sat"),
    SUNDAY(7, "Sunday", "Sun");

    private final int dayNumber;
    private final String fullName;
    private final String shortName;

    private Week(int dayNumber, String fullName, String shortName) {
        this.dayNumber = dayNumber;
        this.fullName = fullName;
        this.shortName = shortName;
    }
}
// 실행 환경
public class WeekRun {
    public static void main(String[] args) {
        Week sunday = Week.SUNDAY;
        System.out.println(sunday.getDayNumber());
        System.out.println(sunday.getFullName());
        System.out.println(sunday.toString());
    }
}
//결과 
7
Sunday
Week{dayNumber=7, fullName='Sunday', shortName='Sun'}
  • 일주일이라는 상수를 표현한 코드
  • enum클래스.상수명으로 선언한다.
  • 이렇게 생성하는 순간 생성자로 구현되고 그 후 getter등으로 값을 가져오는등의 역할을 한다.
public boolean isWeekend() {
        return this == SATURDAY || this == SUNDAY;
}

만약 이런 코드를 사용하면 이 값이 주말인지 아닌지 확인할 수 있다.

이런식으로 코드의 유연성과 가독성을 향상 할 수 있다

외에도 대표적으로 활용할만한 곳이 많다.

  • 주문의 상태
    • 주문 , 취소 , 배송
  • 유저의 형태
    • 관리자 , 고객, 차단고객등
  • 요일 , 계절 , 지역등을 표현
  • 💡싱글톤 패턴을 구현할 때 적합하다.
    • 프로그램 내에서 오직 하나의 객체만 생성할 수 있도록 보장할 수 있다.
    • 중요한 부분이라 생각해 아래에서 이 부분을 다시 다뤄봐야겟다.
  • enum을 통해 프로그램의 유효성 검증에 활용할 수 있다.
    • 입력 값에 대한 검증을 수행할 수 있다.

      public class DayOfWeekValidator {
          public static boolean isValidDayOfWeek(String input) {
              try {
                  DayOfWeek.valueOf(input.toUpperCase());
                  return true;
              } catch (IllegalArgumentException e) {
                  return false;
              }
          }}
      public class Main {
          public static void main(String[] args) {
              String input = "Monday";
              boolean isValid = DayOfWeekValidator.isValidDayOfWeek(input);
              if (isValid) {
                  System.out.println("Valid day of week!");
              } else {
                  System.out.println("Invalid day of week!");
      }}}
    • 입력된 값이 enum으로 바로 들어가 검증된다.

  • 컬렉션에 리스트나 맵에 키 값으로 활용할 수 있다.
    public class MessageMapExample {
        public static void main(String[] args) {
            Map<DayOfWeek, String> messageMap = new HashMap<>();
            messageMap.put(DayOfWeek.MONDAY, "Happy Monday!");
            messageMap.put(DayOfWeek.FRIDAY, "Thank God It's Friday!");
            messageMap.put(DayOfWeek.SUNDAY, "Lazy Sunday!");
    
            System.out.println( messageMap.get(DayOfWeek.MONDAY) ); 
        }
    }
  • API의 반환값으로 활용할 수 있다

싱글톤에서 활용하는 Enum

싱글톤은 프로그램 내에서 객체가 유일 하도록 보장하는 디자인 패턴이다.

멀티 쓰레드 환경에서 안전하게 동작한다.

  • JVM에서 하나의 객체만 생성하도록 보장한다 그래서 별도의 동기화 처리가 없어도 멀티 쓰레드 환경에서 안정하게 동작한다.

    멀티스레드 환경에서는 인스턴스가 동시에 여러개 생성되서 문제가 발생할 수 있지만
    enum 객체들은 컴파일이 정의되어 있어 메모리에 로드될때 인스턴스가 생겨 문제가 발생하니 않는다.

    또한 enum은 일관성에 대한 문제는 없지만 싱글톤 패턴에서 다중 스레드환경에서 여러개의 인스턴스가 생기는 걸 막기 위해 동기화 처리가 필요하다 하지만 enum은 jvm이 인스턴스 생성을 보장하기 때문에 이러한 문제가 발생하지 않는다.

직렬화가 자동으로 이루어진다.

  • enum은 직렬화가 자동으로 이루어지기 때문에 직렬화에 대한 별도의 구현이 필요가 없다

    직렬화는 객체가 이진 데이터로 변환하는 과정을 의미한다.
    객체를 파일, 네트워크 전송 등에서 사용하기 쉽도록 변환할 수 있다.
    반대의 경우에는 역직렬화로 복원된다 ( 하지만 성능을 노려해야한다 )

Enum

public enum SingletonExample {
    INSTANCE;

    private SingletonExample() {
        // 초기화 코드
    }

    public void doSomething() {
        // 기능 구현
    }
}
public class Main {
    public static void main(String[] args) {
        SingletonExample instance1 = SingletonExample.INSTANCE;
        SingletonExample instance2 = SingletonExample.INSTANCE;

        if (instance1 == instance2) {
            System.out.println("Same instance!");
        } else {
            System.out.println("Different instances!");
        }

        instance1.doSomething();
    }
}

이게 어떻게 되느냐

  • Enum에서 정의된 상수는 프로그램이 실행되는 동안 하나의 인스턴스만 생성된다
  • Enum은 클래스처럼 처리 되지만 내부적으로 final으로 선언된 static 상수들을 참조하는 구조로 표현되어 있다.
  • JVM에서 관리하는 상수 풀 (Constant pool)에 저장된다.

상수 풀 (Constant pool)

  • 상수풀은 JVM에서 관리하는 특별한 메모리 영역으로 상수값들만 저장하는 공간이다.

  • String의 리터럴, final 변수 , enum 상수의 상수 값들이 저장되는 영역이다.

  • 상수풀의 값들은 GC의 대상이 아니다

  • 그 말은 메모리에서 해제되지 않는다.

  • 다만 너무 많은 양의 상수값이 저장되면 메모리 사용량이 늘어나는 문제가 발생한다.

    • 불필요한 값을 저장하는걸 주의해야한다.
    • 일반적으로 몇천개 이상 정도는 고려 가능하다.
    • 많아질 수록 클래스의 로드가 느려진다.

0개의 댓글