String str = "Hello";
String str2 = str + "AAAA" + "World";
위 코드를 실행하면, Hello, str+"AAAA", str + "AAAA" + "World" 3개의 객체가 생김
(즉, 만번의 덧셈을 하게 되면 만개의 객체가 생기는 것임)
🟢 왜 이렇게 될까?
String 선언시 final이 붙어있기 때문에 (상수이기 때문에 변할 수 없는 값)
StringBuilder sb = new StringBuilder("123");
Calendar d = Calendar.getInstance()
d.get(Calendar.YEAR) : 연도
d.get(Calendar.MONTH) : 월
d.get(Calendar.DATE) : 일
d.get(Calendar.HOUR) : 시 (12시 기준)
d.get(Calendar.HOUR_OF_DAY) : 시 (24시 기준)
d.get(Calendar.MINUTE) : 분
d.get(Calendar.SECOND) : 초
d.get(Calendar.MILLISECOND) : 밀리 초
d.get(Calendar.ZONE_OFFSET) : 위치 (숫자로 표현)
d.getActualMaximum(Calendar.DATE) : 이달의 마지막 일
Integer n3 = 5; : 기본 자료형을 래퍼런스 클래스의 객체에 넣기
Integer n1 = Integer.valueOf(5);
int num = n1;
래퍼런스 클래스로 만든 객체를 기본 자료형에 넣기
일반적으로 기본 자료형을 많이 씀
🟢 언제 래퍼런스 클래스를 사용할까?
ArrayList<E> arr = null; 에서 E에 래퍼런스 클래스가 들어간다.
(제네릭(<>)을 사용할때 래퍼런스 클래스를 사용)
BigInteger : Long 타입보다 큰 수를 다룰 때 사용
BigInteger big1 = new BigInteger("1000000000000000000000");
BigInteger big2 = new BigInteger("-1000000000000000000000");
BigInteger result = big1.add(big2); // big1 + big2는 안됨
System.out.println(result);
result = big1.multiply(big2);
System.out.println(result);
🔴 평범한 연산 기호를 사용할 수 없음
big1.add(big2) : big1 + big2
big1.multiply(big2) : big1 * big2
제네릭 : 클래스 / 인터페이스 / 메소드 등의 타입을 파라미터로 사용할 수 있게 해주는 역할
(대표적으로 ArrayList<>에서 <> 부분)
class Apple {
@Override
public String toString() {
return "나는 사과입니다.";
}
}
class Orange {
@Override
public String toString() {
return "나는 오렌지입니다.";
}
}
class Box {
private Object ob;
public Object get() {
return ob;
}
public void set(Object ob) {
this.ob = ob;
}
}
public class java_hard_1_p3 {
public static void main(String[] args) {
Box aBox = new Box();
Box oBox = new Box();
aBox.set(new Apple());
oBox.set(new Orange());
Apple ap = (Apple) aBox.get();
Orange og = (Orange) oBox.get();
System.out.println(ap);
System.out.println(og);
}
}
🔴 위 코드처럼 제네릭이 없다면, (Apple)와 같은 형변환이 필요하다. (자식=부모가 되기 때문)
🔴 또한 set()함수에 문자열이 들어간다면 컴파일 에러가 안남(Object가 최고 조상이므로 String을 넣어도 받음)
(단 get을 하면 형변환이 안되므로 실시간 에러 발생)
public static void main(String[] args) {
Box aBox = new Box();
Box oBox = new Box();
aBox.set("Apple");
oBox.set("Orange");
System.out.println(aBox.get());
System.out.println(oBox.get());
}
🔴 위 코드처럼 형변환을 없애면, 오류는 나지 않지만 원하는 결과를 얻을 수 없음 (오류조차 발생하지 않아서 큰 문제)
따라서, 제네릭이 등장!
class Box<T> {
private T ob;
public T get() {
return ob;
}
public void set(T ob) {
this.ob = ob;
}
}
🟢 Class 정의할 때, 옆에 <T>를 붙여줌 (T는 임의의 문자열)
Object 대신 T 작성
(T는 타입 매개변수임)
Box<Apple> aBox = new Box<Apple> : T를 Apple로 결정하여 인스턴스 생성
(Apple 또는 Apple의 하위 클래스 인스턴스 저장 가능)
🟢 이를 활용하면 사과를 꺼낼 때, 형변환 안해도 됨
public static void main(String[] args) {
Box<Apple> aBox = new Box<Apple>();
Box<Orange> oBox = new Box<Orange>();
aBox.set("Apple");
oBox.set("Orange");
Apple ap = aBox.get();
Orange og = oBox.get();
System.out.println(ap);
System.out.println(og);
}
🟢 위 코드의 경우 문자열을 넣는 과정에서 에러 발생, 타입 매개변수에 맞는 타입만 가능
🟢 Box<Apple> aBox = new Box<>();으로 작성 가능 (컴파일러가 알아서 Apple을 넣어줌)
<T extends Number> : 타입을 다음과 같이 제한하면 Number 또는 이를 상속하는 클래스만 가능
🔴 적용 전
class Box<T>{
private T ob;
public int toIntValue() {
return ob.intValue()
}
}
ob.intValue() : 에러
🔴 적용 후
class Box<T extends Number>{
private T ob;
public int toIntValue() {
return ob.intValue()
}
}
ob.intValue() : T를 Number로 특정했기 때문에 사용 가능
public static <T> Box<T> makeBox(T o) {}
<T> : 함수의 매개변수의 타입을 제네릭 형식으로 적어준 것 (제네릭 메소드라는 뜻)Box<T> : 리턴타입makeBox : 함수명T o : 매개변수 타입과 이름🔴 Box<String> sBox = BoxFactory.<String>makeBox("Sweet") : 제네릭 메소드의 T는 메소드 호출 시점에 결정
(매개 변수의 타입으로 제네릭 타입을 넣고 싶다면 생략 가능)