wrapper 클래스란?
기본 자료형을 참조형 자료형처럼 사용하기 위한 클래스이다.
기본 자료형의 값을 감싸 객체형태로 만든 것이 바로 wrapper 클래스이다.
wrapper 클래스의 경우 string 과 같이 불변성을 갖고 있다. 따라서 wrapper 클래스 안에 객체의 값은 변경 불가능하다.

Boxing Primitive 자료형 -> Wrapper 클래스
Unboxing Wrapper 클래스 -> Primitive 자료형
public static void main(String[] args) {
Integer a = new Integer(3);
int b = 3;
Integer c = (Integer) b; // boxing
int d = (int) a; // Unboxing
int e = a; // 자동으로 된다.
Integer f = b; // 자동으로 된다.
}
wrapper 클래스 사용하는 이유
wrapper 클래스를 사용하는 이유는 참조형 자료형을 사용하는 이유와 같다.
기본 자료형의 값을 단순히 값으로만 사용하지 않고 그 값에 대한 메서드를 사용 혹은 null값을 이용하기 위해 사용된다.
하지만 우리가 wrapper 클래스를 흔히 사용하는 이유는 밑의 두가지 이유일 것이다.
첫째 제네릭
둘째 기본 자료형의 값을 문자열로 변환 혹은 반대 경우
래퍼 클래스는 제네릭 사용 시 필수로 들어가는데
제네릭이란
<>를 생각해보면 된다

보면 제네릭 안에 Wrapper class를 사용할 경우 정의가 제대로 잘 되지만
primitive type을 사용할 경우 에러가 뜬다.
즉 제네릭 안에 객체 자료형을 쓸 때는 무조건 Wrapper class를 사용해야 한다는 것이다.
다음으로는 wrapper class에는 null이 들어가지는데

Primitive type인 int는 에러가 뜨지만 wrapper class는 에러가 뜨지 않는다.
int와 Integer 차이점
int : 자료형(primitive type)
산술 연산 가능함
null로 초기화 불가
Integer : 래퍼 클래스 (Wrapper class)
Unboxing하지 않을 시 산술 연산 불가능함
null값 처리 가능하기 때문에 SQL과 연동할 경우 처리가 용이하다.
String str1 = new String("abc");
//힙 메모리에 인스턴스로 생성되는 경우 다른 주소값을 가진다.
String str2 = "abc";
//상수 풀의 문자열은 모두 같은 주소 값을 가진다.
String java = new String("java");
String android = new String("android");
System.out.println(System.identityHashCode(java));
java = java.concat(android);
System.out.println(java);
System.out.println(System.identityHashCode(java));
String java = new String("java");
String android = new String("android");
StringBuilder buffer = new StringBuilder(java);
System.out.println(System.identityHashCode(buffer));
buffer.append(android);
System.out.println(System.identityHashCode(buffer));
String test = buffer.toString();
System.out.println(test);
StringBuffer sb = new StringBuffer(); // StringBuffer 객체 sb 생성
sb.append("hello");
sb.append(" ");
sb.append("jump to java");
String result = sb.toString();
System.out.println(result); // hello jump to java
String 처럼 문자형 배열(char[])을 내부적으로 가지고 있지만 String(불변)과 달리 내용을 변경할 수 있다.
new 연산자를 이용해 StringBuffer 객체를 생성하고 문자를 더 추가하고 싶다면 append()를 이용하면 된다.
String result = "";
result += "hello";
result += " ";
result += "jump to java";
System.out.println(result);
첫번 째 예제의 경우 StringBuffer 객체는 한번만 생성된다. 두번 째 예제는 String 자료형에 + 연산이 있을 때마다 새로운 String 객체가 생성된다(문자열 간 + 연산이 있는 경우 자바는 자동으로 새로운 String 객체를 만들어 낸다).
StringBuffer 자료형은 String 자료형보다 무거운 편에 속한다. new StringBuffer() 로 객체를 생성하는 것은 일반 String을 사용하는 것보다 메모리 사용량도 많고 속도도 느리다. 따라서 문자열 추가나 변경등의 작업이 많을 경우에는 StringBuffer를, 문자열 변경 작업이 거의 없는 경우에는 그냥 String을 사용하는 것이 유리하다.
StringBuffer sb = new StringBuffer("abc");
String s = sb.toString();
System.out.println(s.equals("abc");
equals()가 오버라이딩되어있지 않기 때문에 내용비교가 아닌 주소비교를 한다. 즉, 내용이 같아도 false를 반환한다. 내용을 비교하고 싶다면 StringBuffer를 String으로 변환한 후에 equals()로 비교해야 한다.
💡 쓰레드와 동기화
싱글쓰레드는 한번에 1개의 작업을 하고 멀티 쓰레드는 한번에 여러개의 작업을 하는 것이다. 멀티 쓰레드의 경우 한번에 여러개의 작업을 하다보니 데이터 공유하기 때문에 한 사람이 작업하는 와중에 다른 사람이 건드려서 데이터가 꼬일 수 있다. 이런 것을 막기 위한 것이 동기화이다.
StringBuffer는 동기화되어있는 반면 StringBuilder는 동기화 되어있지 않다. 동기화란 멀티 쓰레드에 안전(thread-safe) 하는 것, 즉 데이터를 보호하는 것을 의미한다. 멀티 쓰레드 프로그램이 아닌 경우, 동기화는 불필요한 성능 저하를 발생시키 때문에 StringBuffer 대신 StringBuilder를 사용하면 성능이 향상된다.
멀티쓰레드인 경우는 StringBuffer를 싱글 쓰레드인 경우는 StringBuilder로 클래스 이름만 변경해주면 된다.
//StringBuffer 사용
StringBuffer sb;
sb = new StringBuffer();
sb.append("abc");
//StringBuilder 사용
StringBuilder sb;
sb = new stringBuilder();
sb.append("abc");
Math 메소드
Math.sin(r) , Math.cos(r), Math.tan(r) : 싸인, 코싸인, 탄젠트
Math.pow(2,16) : 2의 16제곱
Math.log(25) : 로그 25
(int) (Math.random() * 100) + 1 1~100랜덤 (Math.random() : 0~1사이의 랜덤 실수값)
Math.PI : 파이값
추상클래스이므로 객체를 생성할 수 없고 getInstance()를 통해 구현된 객체를 얻어야한다.
Calendar cal = Calendar.getInstance();
Calendar cal = Calendar.getInstance(); //현재 날짜와 시간으로 생성
int thisYear = cal.get(Calendar.YEAR); //올해가 몇년인지
int lastDayOfMonth = cal.getActualMaximum(Calendar.DATE); //이 달의 마지막날