Wrapper
원시값을 객체로 만들기 위해 존재하는 클래스라고 이해하면 편할 것 같다.
ArrayList나 Stream 메소드같은 경우도 (intStream을 이용하면 원시값의 stream이니까) 원시값이 들어갈 수 없기 때문에 boxed같은 함수를 통해서 boxing을 한번 해주고 넣어야 한다.
package _06_wrapper;
import java.util.stream.IntStream;
// Wrapper 객체: 기본 타입 값을 갖는 객체를 생성 가능
// - 포장 객체를 생성하기 위한 클래스는 'java.lang' 패키지에 포함되어 있음
// - 포장 객체는 포장하고 있는 기본 타입의 값을 변경할 수 없고, 단지 객체로 생성하는 데 목적이 있음
// - 컬렉션 객체 때문, ,기본 타입의 값은 저장할 수 없고, 객체만 저장 가능하기 때문
public class BoxingUnboxing {
public static void main(String[] args) {
// Boxing
// - 기본 타입의 값을 Wrapper 객체로 만들어줌
// - 포장 클래스 변수에 값이 대입될 때 발생
Integer obj1 = 100;
Double obj2 = 1.14;
Character obj3 = 'A';
System.out.println(obj1.intValue()); // intValue() : Integer 객체 내부의 int 값 리턴
System.out.println(obj2.doubleValue());
System.out.println(obj3.charValue());
// Unboxing
// - Wrapper 객체에서 원시 데이터를 얻는 과정
// - 원시 타입 변수에 포장 객체가 대입될 때 생성
int value1 = obj1;
double value2 = obj2;
char value3 = obj3;
System.out.println(value1 + " , " + value2 + " , " + value3 );
// 연산 시 boxing
// - obj는 연산 시 unboxing 되어 연산됨
int result1 = obj1 + 100;
double result2 = obj2 + 1.5;
char result3 = (char) (obj3 + 1);
System.out.println(result1 + " , " + result2 + " , " + result3 );
}
}
포장 클래스는 문자열을 기본 타입 값으로 변환할 때도 사용함
대부분의 포장 클래스에는 "parse + 기본타입" 명으로 된 static method가 존재 (오버로딩 없이 String만 인자에 들어갈 수 있다.)
ex) parseInt, parseDouble 등
:해당 메소드는 해당 기본타입 값으로 변환해줌
포장 값 비교
- 포장 객체는 내부 값을 비교하기 위해 ==, != 연산자 사용 불가능. equals 이용해야함
- why? 내부 값을 비교 하는 게 아니라 포장 객체의 주소값을 비교하기 때문
- byte, short, int: -128 ~ 127
- boolean: true, false
- char: \u0000 ~ ~\u007f
위 범위에 포함되는 값은 이미 default로 만들어져 있음.
그래서 여러개 만들어도 포장 객체 공유 (같은 참조). 주소지가 같음.
이외의 값을 갖는다면 새로운 객체를 생성하고 그 주소값을 넣는다. (그렇게 된다면 new 연산자 대신 valueOf가 나을 것 같다.)
package _06_wrapper;
public class ValueCompare {
public static void main(String[] args) {
// -128 ~ 127
Integer obj1 = 10;
Integer obj2 = 11;
Integer obj3 = 10;
System.out.println("obj2 == obj1: " + (obj2 == obj1)); // false
System.out.println("obj1 == obj3: " + (obj1 == obj3)); // true
System.out.println("obj1 equals obj3: " + obj1.equals(obj3)); // true
// 초과
System.out.println();
Integer obj4 = 1000;
Integer obj5 = 1100;
Integer obj6 = 1000;
System.out.println("obj4 == obj5: " + (obj4 == obj5)); // false
System.out.println("obj4 == obj6: " + (obj4 == obj6)); // false
System.out.println("obj6 equals obj6: " + obj6.equals(obj6)); // true
}
}
Generic
결정되지 않은 타입을 파라미터로 가진다고 가지는 클래스와 인터페이스
타입을 하나로 제약하지 않고 인스턴스를 만들 때 정의함으로써 타입이 여러가지가 들어올 수 있게 하는 것이라고 생각하면 될듯
Generic을 제한하려면
<T extends Number> 처럼 넣어주면 된다. 그러면 T는 Number를 extends한 것만 가능하기 때문에 byte, integer, double같은 class들만 들어가는 것이 가능해진다.
package _07_generic;
// 참고. Number class
// - Java에서 모든 숫자 형식의 부모 클래스
// - 정수형, 실수형 데이터타입 포함
// - Byte, Short, Integer 등등
// 제네릭 제한 Case1
// - Box 클래스는 제네릭 타입 T를 받지만 제한을 두어 Number를 상속한 클래스만 허용
class Box<T extends Number> {
private T item;
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
// movable interface
interface Movable {
void move();
}
class Car implements Movable {
@Override
public void move() {
System.out.println("자동차 출발");
}
}
// 제네릭 제한 타입 2
// Container 클래스는 제네릭 타입 T를 받지만 제한을 두어서 Movable interface를 구현한 클래스만 허용
// - makeItMove 메서드는 해당 객체의 move 메서드를 호출할 수 있음.
class Container<T extends Movable> {
private T item;
public Container(T item) {
this.item = item;
}
public void makeItMove() {
item.move();
}
}
public class GenericRunner2 {
public static void main(String[] args) {
Box<Double> doubleBox = new Box<>();
doubleBox.setItem(3.456);
System.out.println(doubleBox.getItem());
Container<Car> carContainer = new Container<>(new Car());
carContainer.makeItMove();
}
}
와일드카드
제네릭 타입을 매개값 or 리턴 타입으로 사용할 때 타입 파라미터로 ? 사용 가능하다.
제네릭에서 와일드카드(?)는 "알 수 없는 타입"을 의미함
? (Unbounded Wildcard): 어떠한 타입도 될 수 있다.
? extends T (Upper Bounded Wildcard): T 타입 또는 T의 서브타입을 의미
=> ?는 T를 extends한 객체이므로 T 타입 본인이거나 T를 extends한 것만 들어갈 수 있다.
? super T (Lower Bounded Wildcard): T 타입 또는 T의 슈퍼타입을 의미
=> ?는 T의 super 객체이기 때문에 T 타입 본인이거나 T의 super만 들어갈 수 있다.
public static void registerCourseA(Applicant<?> applicant) {
System.out.println("kind: " + applicant.kind);
System.out.println("kind.getClass(): " + applicant.kind.getClass());
System.out.println(applicant.kind.getClass().getSimpleName() + "이 Course A를 등록함");
}
// Student 혹은 자식만 가능
public static void registerCourseB(Applicant<? extends Student> applicant) {
System.out.println("kind: " + applicant.kind);
System.out.println("kind.getClass(): " + applicant.kind.getClass());
System.out.println(applicant.kind.getClass().getSimpleName() + "이 Course B를 등록함");
}
static void registerCourseC(Applicant<? super Teacher> applicant) {
System.out.println("kind: " + applicant.kind);
System.out.println("kind.getClass(): " + applicant.kind.getClass());
System.out.println(applicant.kind.getClass().getSimpleName() + "이 Course C를 등록함");
}
'포스코x코딩온' 카테고리의 다른 글
[포스코x코딩온] 풀스택 부트캠프 18주차 정리 Java(API(Get, Post), SQL Mapper(MyBatis)) (1) | 2024.02.24 |
---|---|
[포스코x코딩온] 풀스택 부트캠프 18주차 정리 Collection, Spring boot (0) | 2024.02.22 |
[포스코x코딩온] 풀스택 부트캠프 18주차 정리 Java(Class) (1) | 2024.02.19 |
[포스코x코딩온] 풀스택 부트캠프 17주차 정리 Java(Array, Collection, Exeption) (0) | 2024.02.15 |
[포스코x코딩온] 풀스택 부트캠프 17주차 정리 Java (1) | 2024.02.13 |