일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- appspec
- 커밋메세지수정
- querydsl
- AuthenticationEntryPoint
- 서브쿼리
- ㅔㄴ션
- appspec.yml
- 테스트
- 추후정리
- 테스트메소드
- 외부키
- application.yml
- 적용우선순위
- WeNews
- Query
- docker명령어
- 2 > /dev/null
- 포트
- 참조키
- 컨테이너실행
- EC2
- subquery
- 메세지수정
- 메소드명
- 예약
- foreignkey
- 네이티브쿼리
- 검색
- MySQL
- ubuntu
- Today
- Total
제뉴어리의 모든것
[Section1][Java] 컬렉션 - Generic 본문
제네릭이란
클래스 정의시 클래스 내부에서 사용하는 데이터타입을 특정 타입으로 지정하지 않고 객체 생성시에 지정하는 기술.
- 제네릭의 사용 예
import java.util.ArrayList;
import java.util.List;
class Ball{}
class SoccerBall extends Ball{}
class GolfBall extends Ball{}
class Basket <E> { // 타입매개변수 E를 선언
List<E> list = new ArrayList<>();
void add (E item) {
list.add(item);
}
E get(int index) {
return list.get(index);
}
List<E> getList() {
return list;
}
}
public class GenericPractice {
public static void main(String[] args) {
Basket<Ball> basket = new Basket<>(); // 타입매개변수 E를 Ball로 지정
basket.add(new SoccerBall()); //다형성으로 인해 하위 클래스 대입 가능. Ball item = new SoccerBall(); 과 같은 의미이다.
basket.add(new GolfBall());
for (Ball ball : basket.list) {
System.out.println(ball.getClass().getName());
}
}
}
제네릭의 필요성
클래스에서 사용하는 데이터의 타입이 특정 타입으로 지정되어 있을 경우, 다루는 데이터의 타입만 다를뿐 메소드의 동작들은 같은데도 데이터의 타입별로 클래스를 생성해주어야 한다.
일종의 코드의 반복이다.
이럴 경우 데이터 타입만 별도로 지정해 줄 수 있다면 코드의 반복을 줄일 수 있다.
이런 배경으로 인해 제네릭이란 기술이 생겨나게 되었다.
제네릭 클래스
제네릭이 사용된(선언된) 클래스
타입매개변수
제네릭 선언시 사용되는 임의의 문자 (T,K....)
제네릭 사용시 주의사항
- 클래스(static) 변수에 사용 불가
클래스 변수는 클래스의 객체마다 공유하는 변수인데 제네릭 사용이 가능하다면, 모든 객체들마다 다른 타입을 가질수 있다.
규칙에 위반. - 타입 매개변수로 기본타입 지정 불가
Box<int> box = new Box<int>(); //에러, int 사용 불가. Integer로 대체필요
Box<boolean> box = new Box<boolean>(); //에러, boolean 사용 불가. Boolean으로 대체필요
위에 코드 내용과 같이 타입매개변수로는 기본타입 지정이 불가능하다.
이럴 경우에 사용 되는것이 래퍼클래스(Wrapper Class)이다.
래퍼 클래스에 대한 내용은 아래를 살펴보자.
- 생성자부분에 제네릭지정 생략 가능
Box<Integer> box = new Box<>(); //허용, 생성자 부분에 <>안에 안 적어도 참조변수로 유추 가능하기때문.
- 다형성 허용
객체 생성시에 지정한 타입매개변수가 상위클래스 타입일 경우
해당 제네릭이 적용된 메소드의 인자, 변수에 하위 클래스 타입 객체 대입 가능.
Basket<Ball> basket = new Basket<>(); //Ball은 SoccerBall과 GolfBall의 상위클래스
basket.add(new SoccerBall()); //하위클래스를 요소로써 대입 가능
basket.add(new GolfBall()); //하위클래스를 요소로써 대입 가능
래퍼클래스
(객체가 아닌) 기본타입형의 데이터를 객체로 포장한 클래스.
즉, 객체가 아닌 타입을 객체화 해준것이다.
java.lang 패키지에 포함되어 있다.
래퍼 클래스의 필요성
어떠한 메소드가 매개변수로 객체타입만을 요구하는 경우가 있다.
이럴 경우에 기본타입의 데이터를 객체로 만들어 넘겨주어야 하므로 래퍼클래스란 개념이 생겨나게 되었다
박싱, 언박싱
박싱 : 기본타입 데이터를 래퍼클래스로 만들기
언박싱 : 래퍼클래스를 기본타입 데이터로 만들기
오토박싱, 오토언박싱
JDK 1.5부터 박싱, 언박싱이 필요한 시점에 컴파일러가 자동으로 처리 해주는 기능
오토박싱 : 명시적으로 박싱 명령을 하지 않아도 자동으로 박싱 되는 경우
오토언박싱 : 명시적으로 언박싱 명령을 하지 않아도 자동으로 언박싱 되는 경우
박싱, 언박싱, 오토박싱, 오토언박싱 사용 예
public class WrapperClassPractice {
public static void main(String[] args) {
/** 박싱, 언바싱 예 **/
Integer boxing = new Integer(11); //박싱
int unBoxing = boxing.intValue(); //언박싱
/** ~박싱, 언바싱 예 **/
/** 오토박싱, 오토언바싱 예 **/
Integer autoBoxing = 12; //오토박싱
int autoUnBoxing = autoBoxing; //오토언박싱
/** ~오토박싱, 오토언바싱 예 **/
}
}
래퍼 클래스의 연산
Integer와 같은 타입의 변수는
+, -, <, >, 와 같은 연산자들로 일반 기본타입과 같이 처리가 가능하다.
그러나 == 연산자는 다른 객체들과 같이, 두 참조변수의 주소값을 비교하기 때문에 예상하는 결과가 나오지 않는다.
그러므로 .equals() 메소드를 사용하여야 한다.
참조 : http://www.tcpschool.com/java/java_api_wrapper
제네릭 클래스
제네릭이 사용된(정의된) 클래스
위에서 보았던 제네릭의 예(제네릭이란 - "제네릭의 사용 예" 부분) 가 바로 제네릭 클래스이다!
이 처럼 클랙스옆에 <>를 사용하여 선언해 주는것이 제네릭 클래스인데,
이 제네릭의 사용범위는 클래스 내부 전체에서 사용가능하다.
제한된 제네릭 클래스
단순히 T란 제네릭만 사용할 경우,
객체 생성시에 어떠한 타입이든 설정할 수 있다.
그러나 이 무한의 자유성을 조금 제한하여 최소한 개발자가 원하는 정도의 타입매개변수를 받고 싶을때 사용한다.
쉽게 말해, 제네릭 선언시에 <T> 는 "다 들어와도되!" 이지만,
제한된 제네릭인 <T extends Box> 는 "최소한 Box이거나 Box를 상속(확장)한 클래스타입으로 들어와줘~" 이다
class Academy<T extends Marine> { //최소한 Marine 이거나 Marine을 상속한 타입으로 들어와줘~
List<T> list = new ArrayList<>();
void add (T unit) { list.add(unit);}
T add (int index) { return list.get(index);}
}
- 제한된 제네릭 종류
Box는 클래스이고, Putable은 인터페이스 임을 가정한다
- <T extends Box> : Box 클래스이거나 Box클래스를 상속한 하위 클래스만 들어와줘~
- <T extend Box, Putable> : Box 클래스이거나 Box클래스를 상속한 하위 클래스 이면서! Putable 인터페이스를 구현한 타입만 들어와줘~
제네릭 메소드
위에서 사용되었던 클래스 전체에서 사용되는 범용적 제네릭이 아닌 특정 메소드내에서만 사용할 제네릭이 선언된 메소드.
- 주의사항
제네릭 클래스에 선언된 타입매개변수의 문자와 제네릭 메소드에 선언된 타입매개변수의 문자가 같더라도 서로 전혀 관련이 없는 타입매개변수이다. - static 메소드에도 사용할 수 있다!
위에서 보았던 제네릭 클래스에 선언된 타입변수는 static 멤버변수와 static 멤버메소드에서 사용 할 수가 없었다.
그러나 메소드내에서 선언된 제네릭은 즉, 제네릭 메소드는 static으로 선언이 가능하다!
제네릭 관련 코드
- 1번 코드
import java.util.ArrayList;
import java.util.List;
interface Unit{
void Attack();
void defense();
}
class Marine implements Unit{
@Override
public void Attack() {
System.out.println("마린이 공격을 합니다.");
}
@Override
public void defense() {
System.out.println("마린이 방어를 합니다.");
}
}
class SuperMarine extends Marine{
}
class Academy<T extends Marine & Unit> {
List<T> list = new ArrayList<>();
void add (T unit) { list.add(unit);}
T add (int index) { return list.get(index);}
}
public class GenericPractice2 {
public static void main(String[] args) {
Academy<SuperMarine> academy = new Academy();
// academy.add(new Marine()); // 에러, 제네릭 선언을 <T extends Marine & Unit> 으로 했어도 객체생성시 SuperMarine이라고 지정했기에 안됨.
// SuperMarine 참조변수의 기능의 수가 Marine보다 많기에 불가능. (다형성의 규칙)
academy.add(new SuperMarine());
Academy<Marine> academy2 = new Academy();
academy2.add(new SuperMarine()); //다형성으로 인해 허용
}
}
- 2번 코드
import java.util.ArrayList;
import java.util.List;
class Army{
String attack(){
return "공격!!";
}
}
class SpecialArmy extends Army{ //Army를 상속(확장) 함.
String name;
public SpecialArmy(String name) {
this.name = name;
}
}
class Bunker{
public static <T extends Army> void totalAttack(List<T> armyList){ //제네릭 메소드, static에 가능
for (Army a : armyList) {
SpecialArmy sa = (SpecialArmy) a; //totalAttack 클래스의 객체는 main에서 SpecialArmy로 지정을 했기에 SpecialArmy보다 상위 클래스 객체는 들어올 수 없음.
System.out.println(sa.name + sa.attack()); //extends Army로 최소한 Army이거나 Army의 하위 클래스가 들어올것을 유추할 수 있으므로
//Army의 멤버 메소드 사용 가능!!
}
}
}
public class GenericPractice3 {
public static void main(String[] args) {
List<SpecialArmy> specialArmies = new ArrayList<>();
specialArmies.add(new SpecialArmy("제뉴어리맨")); //제네릭의 제한이 <T extends Army> 이므로 SpecialArmy 가능.
specialArmies.add(new SpecialArmy("줄라이맨"));
specialArmies.add(new SpecialArmy("준맨"));
Bunker.totalAttack(specialArmies);
}
}
위에 코드에서 totalAttack 메소드를 보면 static이고,
타입매개변수 T를 extends Army로 제한하였기 때문에 Army의 멤버메소드를 사용 가능하다!! (이런 점들을 사용하기 위해서라도 extedns는 자주 사용될 듯 하다!!)
'코드스테이츠 > 정리 블로깅' 카테고리의 다른 글
[Section1][Java] 컬렉션 - 컬렉션프레임웍 - 2 (Set) (0) | 2022.07.14 |
---|---|
[Section1][Java] 컬렉션 - 컬렉션프레임웍 - 2 (List) (0) | 2022.07.14 |
[Section1][Java] 객체지향 프로그래밍 심화 - 추상화에 대하여 (0) | 2022.07.13 |
[Section1][Java] 객체지향 프로그래밍 심화 - 다형성에 대하여 (0) | 2022.07.13 |
[Section1][Java] 객체지향 프로그래밍 심화 - 캡슐화에 대하여 (0) | 2022.07.13 |