< 김영한의 실전 자바 - 중급편 > 강의를 보고 이해한 내용을 바탕으로 합니다.
자바는 객체 지향 언어이지만 자바 안에 객체가 아닌 것이 있다.
바로 기본형이다. -- int, double.. 등
기본형은 객체가 아니기 때문에 다음과 같은 한계가 있다.
래퍼 클래스는 기본형을 객체로 감싸서 더 편리하게 사용하도록 도와준다.
즉, 래퍼 클래스는 기본형의 객체 버전이다.
자바는 기본형에 대응하는 래퍼 클래스를 기본으로 제공한다.
그리고 자바가 제공하는 기본 래퍼 클래스는 불변
이며 equals
로 비교해야 한다는 특징을 가진다.
래퍼클래스.valueOf()
를 사용해서 객체를 생성한다. --Integer.valueOf(10)래퍼 클래스에 들어있는 기본형 값을 다시 꺼내는 메서드.
(박스에 들어있는 물건을 꺼내는 것 같다고 해서 언박싱이다.)
--intValue(), doubleValue()
래퍼 클래스는 객체를 그대로 출력해도 내부에 있는 값을 문자로 출력하도록 toString()도 재정의 되어있다.
public static void main(String[] args) {
// Primitive -> Wrapper
int value = 7;
Integer boxedValue = Integer.valueOf(value);
// Wrapper -> Primitive
int unboxedValue = boxedValue.intValue();
System.out.println("boxedValue = " + boxedValue); //boxedValue = 7
System.out.println("unboxedValue = " + unboxedValue); //unboxedValue = 7
}
위는 기존 박싱, 언박싱 기법.
자바 1.5 부터 오토 박싱, 오토 언박싱을 지원한다.
public static void main(String[] args) {
// Primitive -> Wrapper
int value = 7;
Integer boxedValue = value; // 오토 박싱(Auto-boxing)
// Wrapper -> Primitive
int unboxedValue = boxedValue; // 오토 언박싱(Auto-Unboxing)
System.out.println("boxedValue = " + boxedValue); //boxedValue = 7
System.out.println("unboxedValue = " + unboxedValue); //unboxedValue = 7
}
오토 박싱과 오토 언박싱은 컴파일러가 개발자 대신 valueOf(), xxxValue() 등의 코드를 추가해주는 기능. => 기본형과 래퍼형을 서로 편리하게 변환할 수 있다.
Integer boxedValue = value; //오토 박싱(Auto-boxing)
Integer boxedValue = Integer.valueOf(value); //컴파일 단계에서 추가
int unboxedValue = boxedValue; //오토 언박싱(Auto-Unboxing)
int unboxedValue = boxedValue.intValue(); //컴파일 단계에서 추가
래퍼 클래스는 객체이기 때문에 기본형보다 다양한 기능 제공.
그렇다면 기본형은 왜 제공하는가?
기본형 연산이 래퍼 클래스보다 빠르기 때문이다.
자바에서 Class 클래스는 클래스의 정보(메타데이터)를 다루는데 사용된다.
Class 클래스를 통해 실행중인 자바 애플리케이션 내에서 필요한 클래스의 속성과 메서드에 대한 정보를 조회하고 조작할 수 있다.
Class clazz = String.class; // 1.클래스에서 조회
Class clazz = new String().getClass();// 2.인스턴스에서 조회
Class clazz = Class.forName("java.lang.String"); // 3.문자열로 조회
Class 클래스에는 클래스의 모든 정보가 들어있다.
이 정보를 기반으로 인스턴스 생성하거나 메서드 호출하고 필드의 값 변경이 가능하다.
public static void main(String[] args) throws Exception {
Class helloClass = Class.forName("lang.clazz.Hello");
Hello hello = (Hello) helloClass.getDeclaredConstructor().newInstance();
String result = hello.hello();
System.out.println("result = " + result); //result = hello!
}
getDeclaredConstructor().newInstance()
Class를 사용하면 클래스의 메타 정보를 기반으로 클래스에 정의된 메서드, 필드, 생성자 등을 조회하고 이들을 통해 객체 인스턴스를 생성하거나 메서드를 호출하는 작업을 할 수 있다. => 리플렉션
추가로 애노테이션 정보를 읽어서 특별한 기능을 수행할 수도 있고, 최신 프레임워크들은 이런 기능을 적극 활용한다.
시스템과 관련된 기본 기능들을 제공한다.
수학 문제 해결. 너무 많은 기능을 제공하므로 실제 필요할 때 검색하거나 API 문서 찾아보자.
public static void main(String[] args) {
// 기본 연산 메서드
System.out.println("max(10, 20): " + Math.max(10, 20)); //최대값 max(10, 20): 20
System.out.println("min(10, 20): " + Math.min(10, 20)); //최소값 min(10, 20): 10
System.out.println("abs(-10): " + Math.abs(-10)); //절대값 abs(-10): 10
// 반올림 및 정밀도 메서드
System.out.println("ceil(2.1): " + Math.ceil(2.1)); //올림 ceil(2.1): 3.0
System.out.println("floor(2.7): " + Math.floor(2.7)); //내림 floor(2.7): 2.0
System.out.println("round(2.5): " + Math.round(2.5)); //반올림 round(2.5): 3
// 기타 유용한 메서드
System.out.println("sqrt(4): " + Math.sqrt(4)); //제곱근 sqrt(4): 2.0
System.out.println("random(): " + Math.random()); //0.0 ~ 1.0 사이의
double 값 random(): 0.006347084592260965
}
Math.random()을 사용해도 되지만 Random 클래스를 사용하면 더욱 다양한 랜덤값을 구할 수 있다.
(Math.random()도 내부에서는 Random 클래스를 사용한다. Random 클래스는 java.util 패키지 소속이다.)
public static void main(String[] args) {
Random random = new Random();
//Random random = new Random(1); //seed가 같으면 Random의 결과가 같다.
int randomInt = random.nextInt();
System.out.println("randomInt: " + randomInt); //randomInt: -1316070581
double randomDouble = random.nextDouble(); //0.0d ~ 1.0d
System.out.println("randomDouble: " + randomDouble); //randomDouble: 0.37735342193577215
boolean randomBoolean = random.nextBoolean();
System.out.println("randomBoolean: " + randomBoolean); //randomBoolean: false
// 범위 조회
int randomRange1 = random.nextInt(10); //0 ~ 9까지 출력
System.out.println("0 ~ 9: " + randomRange1); //0 ~ 9: 5
int randomRange2 = random.nextInt(10) + 1; //1 ~ 10까지 출력
System.out.println("1 ~ 10: " + randomRange2); //1 ~ 10: 7
}
랜덤은 내부에서 씨드 값을 사용해서 랜덤 값을 구한다. 이 씨드 값이 같으면 항상 같은 결과가 출력된다.
Random random = new Random(1); //seed가 같으면 Random의 결과가 같다.
Seed가 같으면 실행 결과는 반복 실행해도 같다.