최종 목표 : 컴프2 대비
1주차 1회 계획 : Java 지네릭스(Generics), 열거형(enum) 의 개념 공부
공부한 내용 정리
제네릭(generic)이란 무엇일까?
제네릭은 클래스나 메소드 안에서 사용할 변수들의 타입을 미리 알리는 방법이다. 제네릭을 시용하는 이유는 클래스나 메소드 안에서 자료형(data type)에 대해 크게 고민할 필요가 줄어들기 때문이라고 한다.
class MyArray<T>{
T element;
void setElement(T element){this.element = element;}
T getElement() {return element;}
}
public class Generic_study {
public static void main(String[] args){
MyArray<String> myArr = new MyArray<>();
myArr.setElement("문자열");
System.out.println(myArr.getElement());
MyArray<Integer> myArr2 = new MyArray<Integer>();
myArr2.setElement(10);
System.out.println(myArr2.getElement());
}
}
MyArray옆에 '<T>'를 보자. 여기서 T는 타입 변수(type variable)이라고 한다. 찾아보니 임의의 참조 타입이라고 한다. T 대신 어떤 문자를 사용해도 된다.
만약 제네릭을 사용하지 않으면 Object형 같은걸 이용해서 A, B 등을 표현하거나 해야 할 텐데 이러면 type에 위험성이 생긴다. 하지만 제네릭을 사용하면 이 위험성을 어느 정도 탈피할 수 있다. 앞선 코드에서 타입 변수를 T로 두었다. 그럼 클래스 안에 있는 모든 타입 변수들에 대해 자바가 컴파일할 때 T라는 타입으로 모두 치환한다. T를 설정해주기만 하면 T의 참조 타입이 사용자가 원하는 타입으로 변경된다.
하지만 주의해야할 점이 있다. T는 타입 변수이고, 참조 타입에 대응하기 때문에 원시 타입(primitive type)은 대응하지 않는다. 그렇기 때문에 int, long, boolean 등의 원시 타입들은 반드시 래퍼 클래스를 사용해야 한다.
import java.util.ArrayList;
class Animal{ public void sound(){System.out.println("동물");} }
class dog extends Animal{ public void sound() { System.out.println("멍멍"); } }
class cat extends Animal{ public void sound() {System.out.println("야옹");}}
class water{ public void sound(){System.out.println("졸졸졸");} }
class AnimalList<T>{
ArrayList<T> al = new ArrayList<T>();
void add(T animal) {al.add(animal);}
T get(int index) {return al.get(index);}
int size(){return al.size();}
}
public class Generic_study {
public static void main(String[] args){
AnimalList<Animal> animalList = new AnimalList<>();
animalList.add(new dog());
animalList.add(new cat());
animalList.add(new Animal());
// animalList.add(new water()); // Erorr!
// 'add(Animal)' in 'AnimalList' cannot be applied to '(water)'
}
}
위 코드에서 animalList는 Animal 타입만 원소로 갖기 때문에 Animal타입이 아닌 water는 animalList에 들어갈 수 없다. 그래서 Erorr가 발생한다.
타입 변수에 제한을 걸 수 있는 방법이 있다. 첫번째 방법은 바로 상위 클래스의 상속을 이용한 것이다.
class AnimalList<T extends dog>{
ArrayList<T> al = new ArrayList<T>();
void add(T animal) {al.add(animal);}
T get(int index) {return al.get(index);}
int size(){return al.size();}
}
public class Generic_study {
public static void main(String[] args){
AnimalList<Animal> animalList = new AnimalList<>();
animalList.add(new dog());
// animalList.add(new cat());
// 'add(dog)' in 'AnimalList' cannot be applied to '(cat)'
// animalList.add(new Animal());
}
}
타입변수를 dog를 상속받은 참조 변수에 한하여 입력이 가능토록 변경해보았다.
이것 말고도 인터페이스를 이용하는 방법도 있다.
interface life{}
class AnimalList<T extends life>{
ArrayList<T> al = new ArrayList<T>();
void add(T animal) {al.add(animal);}
T get(int index) {return al.get(index);}
int size(){return al.size();}
}
특이하게도 인터페이스와 상속 모두 extends를 통해 상속 받음을 지시한다.
만약 부모클래스의 상속, 인터페이스의 구현을 모두 나타내고 싶으면 엠퍼센트(&) 기호를 사용하면 된다.
class AnimalList<T extends Animal & life>
그런데 반드시 클래스가 앞, 인터페이스가 뒤로, 순서가 정해져 있다는 특징이 있다.
열거형(enum, enumeration type)이란 무엇일까?
열거형은 서로 관련된 상수끼리를 편리하게 선언하기 위한 것으로, 여러 상수를 정의할 때 사용하면 편리하다고 한다.
열거형을 사용하는 방법은 간단하다.
enum 열거형이름{ 상수명1, 상수명2, ... }
나도 한 번 만들어봤다.
enum school{ ELEMENTARY, MIDDLE, HIGH, UNIVERSITY }
위 코드에서 ELEMENTARY, MIDDLE, HIGH, UNIVERSITY 는 아직 상수값이 설정되어 있지 않다. 그렇기 때문에 상수명만 존재하고 있는 것이다.
- 상수값 설정
enum School{ ELEMENTARY(8), MIDDLE(14), HIGH(17), UNIVERSITY(20);
private final int age;
School(int age){this.age = age;}
public int getAge(){return age;}
}
상수값을 설정하기 위해서는 이처럼 초기화작업을 해줘야 한다. School 도 실은 클래스이기 때문인 것 같다.
- values() 메소드
- 해당 열거체의 모든 상수를 저장한 배열을 생성하여 반환한다.
enum school{ ELEMENTARY, MIDDLE, HIGH, UNIVERSITY }
public class Enum_study {
public static void main(String[] args){
School school[] = School.values();
}
}
- valueOf() 메소드
- 열거체에서 상수를 반환해준다.
처음에는 name() 메소드(열거체의 상수의 이름을 문자열로 반환한다.)의 존재를 몰라 상수를 반환한다는 것이 상수값을 반환한다고 생각했지만 아래 코드를 짜 보고 나서 아닌 것을 알게 되었다. 그래서 그냥 상수 이름을 가져오는 것인 줄로만 알뻔했다.
enum School{ ELEMENTARY, MIDDLE, HIGH, UNIVERSITY;}
public class Enum_study {
public static void main(String[] args){
School s = School.valueOf("ELEMENTARY");
System.out.println(s);
}
}
>> ELEMENTARY
다행히도 아래 코드를 통해서 상수를 반환한다는 것이 무슨 의미인지 알게 되었다.
enum School{ ELEMENTARY(8), MIDDLE(14), HIGH(17), UNIVERSITY(20);
private final int age;
School(int age){this.age = age;}
public int getAge(){return age;}
}
public class Enum_study {
public static void main(String[] args){
School s = School.valueOf("ELEMENTARY");
System.out.println(s);
System.out.println(s.getAge());
}
}
>> ELEMENTARY
>> 8
School에서 정의한 메소드 getAge를 통해 s의 value를 불러왔다. 처음에는 '상수명'만 문자열로 가져오는 줄 알았다. 하지만 정말 상수자체를 가져오는 것이었다.
- ordinal() 메소드
- 해당 열거체 상수가 열거체 정의에서 정의된 순서(0부터 시작)를 반환한다.
enum School{ ELEMENTARY, MIDDLE, HIGH, UNIVERSITY;}
public class Enum_study {
public static void main(String[] args){
int idx = School.MIDDLE.ordinal(); // idx = 1 과 같다.
}
}
enum School{ ELEMENTARY(8), MIDDLE(14), HIGH(17), UNIVERSITY(20);
private final int age;
School(int age){this.age = age;}
public int getAge(){return age;}
}
public class Enum_study {
public static void main(String[] args){
int idx = School.MIDDLE.ordinal(); // << idx에는 1이 들어간다.
}
}
'활동 > 2022 하계 모각코' 카테고리의 다른 글
[2022 하계 모각코] 6주차 1회 계획 및 결과 (0) | 2022.08.01 |
---|---|
[2022 하계 모각코] 5주차 1회 계획 및 결과 (0) | 2022.07.25 |
[2022 하계 모각코] 4주차 1회 계획 및 결과 (0) | 2022.07.18 |
[2022 하계 모각코] 2주차 1회 계획 및 결과 (0) | 2022.07.07 |
임시 페이지 (0) | 2022.06.15 |
댓글