📦 Enum

An enum type is a special data type that enables for a variable to be a set of predefined constants.
enum type은 미리 정의된 상수의 집합이 될 수 있도록 하는 특별한 데이터 타입이다.

The variable must be equal to one of the values that have been predefined for it.
변수는 미리 정의된 값 중 하나와 같아야 합니다.

Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.
일반적인 예로는 나침반 방향(NORTH, SOUTH, EAST 및 WEST 값)과 요일이 포함됩니다.

 

방향 대신 Day로 예시를 들어보면 다음과 같다.

enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY 
}
Day.SUNDAY // SUNDAY

 

 

enum은 열거체를 비교할 때 실제 값뿐만 아니라 타입까지도 체크한다.

enum의 상숫값이 재정의되더라도 다시 컴파일할 필요가 없다.

 

enum Color {
    RED(3),
    YELLOW(4),
    BLUE(5);
    
    private final int value;
    Color(int value) { this.value = value; }
    public int getValue() { return value; }
}

 

System.out.println(Color.RED.name());      // RED
System.out.println(Color.RED.value());      // 3

 

1. 자바에서 상수 정의하기:: static final 

상수를 정의하는 방법에는 enum이 나타나기 전에 static final을 사용하는 방법이 있었다.

static final을 사용하는 방법 예시는 다음과 같다.

 

예시 상황으로 사용자는 1에서 100사이의 값만 입력할 수 있는 프로그램이 있다고 하자.
여기서 1과 100을 상수로 선언할 것이다. static final을 활용한 코드는 아래와 같다.

 

public class Application {
    private static final int MIN_SIZE = 1;
    private static final int MAX_SIZE = 100;
    
     public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int userInput = parseInt(in.readLine());
        if(userInput >= MIN_SIZE
                && userInput <= MAX_SIZE) {
            System.out.println("good");
        }
    }
}

 

 

이러한 static final 이 존재하였는데 왜 enum 이라는 열거형이 나왔을까?

 

Why created the enum?

  1. final static으로 상수를 선언하는 경우 상수 이름과 상수 값 자체는 관련이 없게된다.
  2. 이름의 충돌이 발생할 수 있다.

다음 예시를 통해 배경을 더 정확히 이해해보자!

 

final static으로 상수를 선언하는 경우 상수 이름과 상수 값 자체는 관련이 없게된다.

public class Application {
    private static final String SPRING = "봄";
    private static final String SUMMER = "여름";
    private static final String AUTUMN = "가을";
    private static final String WINTER = "겨을";
    
    public static void main(String[] args) {
    	System.out.println(SPRING); // 봄
        System.out.println(SUMMER); // 여름
        System.out.println(AUTUMN); // 가을
        System.out.println(WINTER); // 겨울
        
        String season = "봄";
        
        if (season == SPRING) {
        	System.out.printf("season is %s", SPRING); // season is 봄
        }
    }
}

 

 

이름의 충돌이 발생할 수 있다.

public class Framework {
    public static final int SPRING = 1;
    public static final int VUE = 2;
    public static final int NESTJS = 3;
}

public class Season {	
    public static final int SPRING = 1;
    public static final int SUMMER = 2;
    public static final int AUTUMN = 3;
    public static final int WINTER = 4;
}

// Season.SPRING Framework.SPRING 충돌

 

 

Advantages of using Enum instead of static final

  1. 코드가 단순해지고, 가독성이 좋아진다.
  2. 인스턴스 생성과 상속을 방지한다.
  3. enum 키워드 사용을 통해서 구현 의도가 열거형임을 분명하게 나타낼 수 있다.

 

static final 사용

private static final String SPRING = "봄";
private static final String SUMMER = "여름";
private static final String AUTUMN = "가을";
private static final String WINTER = "겨을";

 

 

enum 사용

public enum Season {
    SPRING("봄"),
    SUMMER("여름"),
    AUTUMN("가을"),
    WINTER("겨울");
    
    private final String value;
    Seson(String value) { this.value = value; }
    
    public String getValue() {
    	return value;
	}
}

 

final static 을 사용하여 선언한 상수보다 enum 을 사용한 상수 선언이 가독성 면에서 더 좋다.

 

 

 

 

 

 

Enum Types (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

 

 

11주차 과제: Enum

11주차 과제: Enum · Issue #11 · whiteship/live-study 목표 자바의 열거형에 대해 학습하세요. 학습할 것 (필수) enum 정의하는 방법 enum이 제공하는 메소드 (values()와 valueOf()) java.lang.Enum EnumSet 마감일시 2021

hyeonic.tistory.com

 

 

[Java] 자바의 상수(Constant), final 변수 정리

상수(Constant) 프로그래밍 언어에서 상수는 변하지 말아야 할 데이터를 임시적으로 저장하기 위한 수단으로 사용된다. 즉, 초기화 이후 재할당이 불가능하다는 뜻이다. final 자바에서는 상수를 구

ittrue.tistory.com

 

 

Java: enum의 뿌리를 찾아서...

이번 글에서는 자바 1.5버전부터 새롭게 추가된 열거형 상수인 enum(enumeration)에 대해 알아보겠습니다. 열거형은 서로 연관된 상수들의 집합입니다. 이번 글은 enum 정의와 enum 사용방법, 그리고 enum

www.nextree.co.kr

 

 

Java Enum 활용기 | 우아한형제들 기술블로그

{{item.name}} 안녕하세요? 우아한 형제들에서 결제/정산 시스템을 개발하고 있는 이동욱입니다. 이번 사내 블로그 포스팅 주제로 저는 Java Enum 활용 경험을 선택하였습니다. 이전에 개인 블로그에 E

techblog.woowahan.com

 

728x90

'Language > JAVA' 카테고리의 다른 글

[JAVA] Vector Class  (1) 2023.11.29
[JAVA] Getter/Setter  (0) 2023.11.02
[JAVA] 생성자  (0) 2023.10.25
[JAVA] 값 복사와 주소 복사  (0) 2023.10.25
[JAVA] Java Collections / Array / ArrayList  (2) 2023.10.25

Getter/Setter ?

getter, setter는 get method와 set method를 의미한다.

Get/Set method는 각각 값을 가져오는 메소드, 값을 수정하는 메소드이다.

자바에서 Get/Set Method를 굳이 일반 메소드와 구분하여 사용하는 이유가 무엇일까?

 

Why use Getter/Setter Method in JAVA?

자바는 대표적인 객체지향프로그래밍 언어이다.

객체지향프로그래밍에서는 객체의 데이터에 객체 외부가 직접적은로 접근하는 것을 막는다. (캡슐화)

외부에서 객체의 데이터를 직접적으로 읽고 변경하게 된다면 객체 무결성이 깨질 수 있기 때문이다.

자바에서는 이렇게 "민감한 데이터를 사용자에게서 숨기도록" 캡슐화를 위하여 멤버변수를 private으로 선언하여 get/set method를 통해서 멤버변수에 접근할 수 있도록 한다.

 

즉, 캡슐화를 위해서 get/set을 사용한다.

 

캡슐화 예시

사람 객체가 있다고 가정하자.

사람은 모두 이름과 나이, 성별, 생년월일, 주민등록번호를 가진다.

간단하게 예시만 들 것이기 때문에 이름과 주민번호를 멤버변수로 갖는 객체를 선언할 것이다.

이를 객체로 표현하면 다음과 같다.

class Person {
    public String name; // 이름
    public String personId; // 주민번호
}

 

여기서 접근제어자를 모두 public으로 선언하였는데, 주민번호는 개인정보이기 때문에 private으로 선언해줘야 알맞다. 이를 수정해준다.

 

class Person {
    public String name;
    private String personId;
}

 

이제 우리가 사람의 주민번호를 알고 싶을때 Person.personId로 접근할 수 없게 되었다. 특정 사람의 주민번호를 알기 위한 get method와 주민등록을 변경할 경우를 대비해 set method를 같이 선언해준다.

class Person {
    public String name;
    private String personId;
    
    public String getPersonId() {
    	return this.personId;
    }
    
    public void setPersonId(String newPersonId) {
        Pattern id = Pattern.compile("/^\d{2}[0-1]\d{1}[0-3]\d{1}\-[1-4]\d{6}$/");
        if (id.matcher(newPersonId).matches()) {
	        this.personId = newPersonId;
        }	
    }
}

 

이렇게 get/set 메소드를 활용하면 외부로부터 값을 보호하고, set 메소드를 통해서 수정하고자 하는 값이 올바른 값이 맞는지 확인하는 과정을 거칠 수 있다.

728x90

'Language > JAVA' 카테고리의 다른 글

[JAVA] Vector Class  (1) 2023.11.29
[JAVA] Enum 열거형  (0) 2023.11.04
[JAVA] 생성자  (0) 2023.10.25
[JAVA] 값 복사와 주소 복사  (0) 2023.10.25
[JAVA] Java Collections / Array / ArrayList  (2) 2023.10.25

생성자

생성자는 클래스로부터 객체를 생성할 때 자동으로 호출되는 메소드를 말한다. 객체의 멤버 변수 초기화를 담당하는 특수한 목적의 메소드이다.

 

생성자의 개념과 특징

  • 메소드 이름이 클래스 이름과 동일하다.
  • 리턴 타입이 없으며, void조차 허용하지 않는다.
  • 객체 생성 시 자동으로 호출되며, 일반 메소드처럼 참조 변수를 통해 호출할 수 없다.
  • 생성되는 객체의 멤버 변수 초기화를 담당한다.
  • 생성자가 하나도 정의되지 않은 클래스에는 기본 생성자가 자동으로 제공된다.
  • 하나의 클래스에 여러 개의 생성자를 오버로딩 할 수 있다.
  • this() 형태의 특수한 생성자가 있다.

 

기본 생성자

기본 생성자는 매개변수가 없는 생성자를 의미한다.

생성자의 가장 중요한 기능이 멤버 변수의 초기화인데, 기본 생성자는 매개변수를 가질 수 없기 때문에 멤버 변수를 기본값으로 초기화한다.

그래서 기본 생성자라는 이름을 갖게 된 것이다.

 

기본 생성자의 또 다른 특징으로는 클래스에 생성자가 하나도 없을 때 기본으로 제공된다는 것이다. 따라서 다음 두 클래스는 동일한 코드라고 볼 수 있다.

 

public class Student {
	String name;
    int score;
}
public class Student {
	String name;
    int score;
    
    Student() {}
}

 

 

생성자를 통해서 객체의 멤버변수를 초기화 하기

// 1. 클래스 선언부
public class Student {
    public String name;
    public int score;
    public boolean isPassed;
    public String major;

    public Student() {}

    public Student(String stdName, int stdScore, boolean stdIsPassed, String stdMajor) {
        name = stdName;
        score = stdScore;
        isPassed = stdIsPassed;
        major = stdMajor;
    }

    public void printInfo() {
        System.out.println(name + "의 전공 : " + major + " 점수 : " + score + " 시험 통과 여부 : " + isPassed);
    }

}

public Student() {}  는 기본생성자이고, 그 아래에 매개변수를 가지고 있는 public Student( ... ) {} 는 멤버변수 값을 초기화 해주는 오버로딩된 생성자이다.

 

기본 생성자로 객체를 선언하게 되면 멤버변수값들이 아래와 같이 기본값으로 초기화가 된다. int type의 score 는 0, boolean 타입의 isPassed는 false, 참조 변수 타입인 name, major는 null 값을 갖게 된다.

public class Main {
    public static void main(String[] args) {
        Student millpre = new Student();
        millpre.printInfo();
    }
}

 

아래와 같이 매개변수를 넣어 선언하게 되면 매개변수에 맞게 멤버변수 값들이 초기화 되는 것을 확인할 수 있다.

public class Main {
    public static void main(String[] args) {
        Student millpre = new Student("millpre", 90, true, "cs");
        millpre.printInfo();
    }
}

 

this() 생성자

생성자의 이름은 반드시 클래스의 이름과 동일해야 한다. 그런데 생성자 중에 클래스의 이름을 사용하지 않는 this() 라는 독특한 생성자가 존재한다.

this() 생성자를 이용하면 같은 클래스에 있는 다른 생성자를 호출할 수 있다. 이를 통해 생성자 내의 코드 중복을 제거할 수 있다.

코드를 보면 바로 이해할 수 있을 것이다.

// 1. 클래스 선언부
public class Student {
    public String name;
    public int score;
    public boolean isPassed;
    public String major;

    public Student() {}
    
    public Student (String stdName, int stdScore) {
        name = stdName;
        score = stdScore;
    }

    public Student(String stdName, int stdScore, boolean stdIsPassed, String stdMajor) {
        this(stdName, stdScore);
        isPassed = stdIsPassed;
        major = stdMajor;
    }

    public void printInfo() {
        System.out.println(name + "의 전공 : " + major + " 점수 : " + score + " 시험 통과 여부 : " + isPassed);
    }

}

 

728x90

'Language > JAVA' 카테고리의 다른 글

[JAVA] Enum 열거형  (0) 2023.11.04
[JAVA] Getter/Setter  (0) 2023.11.02
[JAVA] 값 복사와 주소 복사  (0) 2023.10.25
[JAVA] Java Collections / Array / ArrayList  (2) 2023.10.25
[JAVA] 테스트코드 작성하기  (1) 2023.10.24

값 복사와 주소 복사

자바에서 기본 타입의 변수는 값 자체가 복사되고, 참조 타입의 변수는 주소가 복사된다.

이 개념은 메소드를 호출할 때도 동일하게 적용된다.

 

값 복사

메소드의 매개변수가 기본 타입인 경우는 인자로 전달된 값이 매개변수에 복사되어 전달된다.

public class Main {
    public static void main(String[] args) {
        int firstScore = 99;
        int secondScore = 33;

        System.out.println("before(firstScore) : " + firstScore);
        System.out.println("before(secondScore) : " + secondScore);

        swapScore(firstScore, secondScore);

        System.out.println("after(firstScore) : " + firstScore);
        System.out.println("after(secondScore) : " + secondScore);
    }

    private static void swapScore(int score1, int score2) {
        int temp = score1;
        score1 = score2;
        score2 = temp;

        System.out.println("swqpScore() 에서 score1 : " + score1);
        System.out.println("swqpScore() 에서 score2 : " + score2);
    }
}

 

메소드가 호출되면서 매개변수를 통해 값이 복사되면서 main() 메소드 안에서 선언된 firstScore, secondScore 값이 swapScore() 메소드가 호출되는 순간 매개변수에 해당되는 score1, score2 변수에 복사되어 전달된다.

 

swapScore() 메소드에서 temp 변수를 이용하여 score1과 score2의 값을 교환하면 swapScore() 메소드에서는 값이 당연히 바뀌지만 main() 함수에서는 firstScore와 secodScore의 값이 바뀌지 않는다.

 

주소 복사

// 1. 클래스 선언부
public class Student {

    // 2. 멤버 변수
    public String name = "MillPRE";
    public int score = 52;
    public int firstScore;
    public int secondScore;
	
    
    // ~ 생략 ~
}
public class Main {
    public static void main(String[] args) {
        Student millpre = new Student();
        millpre.firstScore = 90;
        millpre.secondScore = 33;

        System.out.println("before(firstScore) : " + millpre.firstScore);
        System.out.println("before(secondScore) : " + millpre.secondScore);

        swapScore(millpre);

        System.out.println("after(firstScore) : " + millpre.firstScore);
        System.out.println("after(secondScore) : " + millpre.secondScore);
    }

    private static void swapScore(Student std) {
        int temp = std.firstScore;
        std.firstScore = std.secondScore;
        std.secondScore = temp;

        System.out.println("swqpScore() 에서 firstScore : " + std.firstScore);
        System.out.println("swqpScore() 에서 secondScore : " + std.secondScore);
    }
}


이전에 값 복사와는 다르게 millpre.firstScore와 millpre.secondScore 의 값이 maind에서도 바뀌는 것을 확인할 수 있다.

이는 main() 함수에서 swqpScore() 메소드를 호출할 때 millpre라는 참조변수가 참조하고 있는 Student 객체의 주소가 매개변수로 선언된 std 변수에 복사되기 때문이다.

swapScore 메소드가 호출되는 시점에 Student 객체는 millpre와 std 두 개의 참조 변수에 의해 공유되고 있는 상태가 된다.

 

728x90

'Language > JAVA' 카테고리의 다른 글

[JAVA] Getter/Setter  (0) 2023.11.02
[JAVA] 생성자  (0) 2023.10.25
[JAVA] Java Collections / Array / ArrayList  (2) 2023.10.25
[JAVA] 테스트코드 작성하기  (1) 2023.10.24
[JAVA] 메소드 Method  (0) 2023.10.19

+ Recent posts