자바 정복 일기 - Generic과 Enum

Bex·2023년 8월 13일
0
post-thumbnail

1. Generic

제네릭(Generic)이란?

  • 자바에서 Generic이란 클래스 내부에서 정하는 것이 아닌 사용자 호출에 의해 타입이 지정되는 것을 의미
  • 즉, 특정 타입의 변수형에 지정되는 것이 아닌 필요에 의해 여러 가지 타입을 사용하고 싶을 경우 사용
ArrayList<Integer> list1 = new ArrayList<integer>();
ArrayList<String> list2 = new ArrayList<String>();

제네릭(Generic) 타입이란?

  • 제네릭 타입은 타입 파라미터를 가지는 클래스와 인터페이스를 지칭
  • 제네릭 타입은 클래스 및 인터페이스 이름 뒤에 "<>"를 쓰고 타입 파라미터(T)를 명시해야 함
public class 클래스명<T> { }
public interface 인터페이스명<T> { }
타입 파라미터란?
• 타입 파라미터는 제네릭 클래스/인터페이스에 사용되며 타입이 정해지지 않은 파라미터이다.
• 대부분 참조 타입의 경우 T, 원소의 경우 E, 키를 나타낼 경우 K, 값을 나타낼 경우 V 등을 사용
타입 분류 타입 인자
Type <T>
Element <E>
Key <K>
Value <V>

1) Generic의 장점

  1. 재사용성 증가

    • 제네릭 타입을 여러 타입의 파라미터를 삽입해 객체를 생성할 수 있기 때문에 코드를 간결하게 하고 재사용성을 높임
  2. 컴파일 시 타입 에러 발견 가능

    • 제네릭 타입의 경우 컴파일 시 잘못 사용되는 타입 문제점을 제거하기 위해 강하게 타입 체크를 수행
  3. 컴파일러가 타입 변환 수행

    • 컴파일 단계에서 컴파일러가 타입 캐스팅을 수행해주기 때문에 불필요하게 코드에서 타입 캐스팅을 할 필요가 없음

2) Generic 사용

(1) 제네릭을 사용한 클래스 및 인터페이스 선언

아래 코드처럼 선언할 수 있고 T타입은 해당 블럭 { } 안에서까지 유효하다.

  public class 클래스명 <T> { }
  public interface 인터페이스명 <T> { }

또한 제네릭 타입을 두 개로 둘 수도 있다.

  public class 클래스명 <T, K> { }
  public class 인터페이스명 <T, K> { }

이렇게 선언한 클래스와 인터페이스는 다음과 같이 사용할 수 있다

클래스명<String> a = new 클래스명<String>();
인터페이스명<String, integer> b = new 인터페이스명<String, Integer>();

이 때 주의해야 할 점은 타입 파라미터로 명시할 수 있는 것은 참조 타입(Reference Type)밖에 올 수 없다. 따라서 int, double, char과 같은 primitive type은 올 수 없다.

또한 참조 타입이 올 수 있으므로 사용자가 정의한 클래스도 타입으로 올 수 있다.

public class 클래스명 <T> { }

public class Bex { }
  
// 사용
클래스명<Bex> a = new 클래스명<Bex>();

(2) 제네릭 클래스 구현

이제 제네릭을 이용하여 간단한 클래스를 구현해보자

InhaUniversity 클래스

  • 필드에는 info를 넣어보자
      public class InhaUniversity <T> {
      private T info;
      
      public void setInfo(T info) {
          this.info = info;
      }
      
      public T getInfo() {
          return info;
      }

(3) 제네릭 인터페이스 구현

이번에는 제네릭을 이용하여 간단한 인터페이스를 구현해보자

Umc 인터페이스

  • 각 객체들의 말을 추상 메서드로 가진다.
     public interface Umc <W> {
    	public W getSaying();
    }

(4) 제네릭 타입 상속

  • 제네릭 타입도 부모-자식간 상속이 가능하다.
  • 상속관계에서 자식 제네릭 타입은 부모의 제네릭 타입 파라미터를 반드시 선언해주어야 한다.

부모 클래스를 상속 받는 경우

public class 클래스명<부모 제네릭 타입, 자식 제네릭 타입> extends 부모클래스 { }

부모 인터페이스를 상속 받는 경우

  public class 인터페이스명<부모 제네릭 타입, 자식 제네릭 타입> implements 부모인터페이스 { }

부모 클래스, 인터페이스 모두 상속 받는 경우

위에서 만든 InhaUniversity클래스와 Umc인터페이스를 상속받는 Bex클래스를 만들어보자.

public class Bex <T, W, C> extends InhaUniversity<T> implements Umc<W> {

  public W saying;

  @Override
  public void setSaying(W saying) {
      this.saying = saying;
  }

  @Override
  public W getSaying() {
      return saying;
  }

  public C isState(C state) {
      return state;
  }
}

그렇다면 지금까지 만든 클래스와 인터페이스를 통해 출력해보자

  public class GenericExample {
    public static void main(String[] args) {
        Bex<Double, String, Integer> bex = new Bex<>();
        
        bex.setInfo(4.5);
        System.out.println("벡스의 인하대 학점은 : " + bex.getInfo());

        bex.setSaying("난 아무렇지 않아");
        System.out.println("벡스 : " + bex.getSaying());
        
        System.out.println("벡스의 슬픔 정도는?(0 ~ 5) : " + bex.isState(4));
    }
}

출력결과는 다음과 같다.


2. Enum

Enum(열거형)이란?

  • Enum은 서로 연관된 상수들의 집합을 의미한다.
  • 자바에서 Enum은 특수한 자바 클래스로 상수, 메서드 등이 포함될 수 있다.

1) Enum의 장점

  1. 코드가 단순해지며, 가독성이 좋음

  2. 인스턴스 생성과 상속을 방지하여 상수값의 타입 안정성이 보장

  3. 클래스를 상수처럼 사용 가능.

  4. 키워드 enum을 사용하기 때문에 구현의 의도가 열거임을 분명히 알 수 있음


2) Enum을 사용하는 이유

위에서 말한 장점 때문에 Enum을 사용한다. 그렇다면 직접 Enum을 구현해보면서 이유를 알아보자.

(1) Enum을 사용하지 않고 상수 사용

public class UmcManagement {
	public static final String CEO = "회장";
	public static final String VICE_CEO = "부회장";
	public static final String MANAGER = "총무";
	public static final String PART_LEADER = "파트장";
	public static final String MEMBER = "동아리원";

	public static void main(String[] args) {
		String bex;
		bex = UmcManagement.PARTLEADER;
		bex = UmcManagement.CEO;
		// 위의 상수들이 아닌 상수 값이 할당 될 때 에러 발생 X
		bex = "준석"
	}
}

위의 코드를 보면 bex에 원하는 상수를 할당할 수 있다. 하지만 마지막 줄처럼 상수가 아닌 bex와 같은 타입이면서 엉뚱한 값이 들어간다면 즉, "준석"이라는 값이 실수로 할당되었을 때 런타임시 다른 곳에서 문제가 발생할 수 있다. 따라서 이 잠재적인 문제는 프로그램에 치명적인 오작동을 초래할 수 있다.

(2) Enum을 사용해서 상수 사용

public enum UmcManagement {
  CEO("회장"),
  VICE_CEO("부회장"),
  MANAGER("총무"),
  PART_LEADER("파트장"),
  MEMBER("동아리원");

  private final String toKorean;

  UmcManagement(String toKorean) {
      this.toKorean = toKorean;
  }
}

public class EnumExample {
  public static void main(String[] args) {
      UmcManagement bex;
      bex = UmcManagement.PART_LEADER;
      bex = UmcManagement.CEO;
      // Enum에 포함하지 않는 상수 넣을 시 -> 컴파일 에러 발생
      bex = "준석";
  }
}

위의 코드처럼 Enum을 사용하여 상수를 사용할 시 엉뚱한 값을 넣었을 때 컴파일에러가 발생한다. 즉, 컴파일 시 우리가 기대하지 않는 상수값이 할당을 사전에 체크할 수 있다!!!


참고 자료

자바 [JAVA] - 제네릭(Generic)의 이해
[JAVA] 제네릭(Generic)이란?
[Java] enum 이란?
[JAVA] enum(열거형)이란?

profile
초보 개발자의 코딩 일기

0개의 댓글