
모든 모듈이 의존하는 기본 모듈, 모듈 중 유일하게 requires 하지 않아도 사용할 수 있다.
extends 키워드로 다른 클래스를 상속하지 않으면, 암시적으로 java.lang.Object 클래스를 상속하게 된다 → 자바의 모든 클래스는 Object의 자식이거나 자손 클래스임
⏬ Object 가 가진 주요 메소드
| 메소드 | 용도 |
|---|---|
| boolean equals(Object obj) | 객체의 번지를 비교하고 결과를 리턴 |
| int hashCode() | 객체의 해시코드(객체를 식별하는 정수)를 리턴 |
| String toString() | 객체 문자 정보를 리턴 |
레코드 : 데이터 전달을 위한 DTO(Data Transfer Object)를 작성할 때 반복적으로 사용되는 코드를 줄이기 위해 사용
public record Person(String name, int age){}
레코드 소스를 컴파일 하면 변수의 타입과 이름을 이용한 private final 필드가 자동 생성, 생성자 및 Getter 메소드가 자동 추가됨. (+ hashCode(), equals(), toString() 메소드를 재정의한 코드도 자동으로 추가)
롬복(Lombok)은 JDK에 포함된 표준 라이브러리는 아니지만 개발자들이 즐겨쓰는 자동 코드 생성 라이브러리이다.
DTO 클래스를 작성할 때 Getter, Setter, hasCode(), equals(), toString() 메소드를 자동 생성하므로 작성할 코드의 양을 줄여줌
포장 객체 : 기본 타입(byte, char, short, int, long, float, double, boolean) 의 값을 갖는 객체를 생성
☝️ 포장 객체는 포장하고 있는 기본 타입의 값을 변경할 수 없고, 단지 객체로 생성하는 게 목적. 컬렉션 객체 때문에 필요
박싱(boxing) : 기본 타입의 값을 포장 객체로 만드는 과정
언박싱(unboxing) : 포장 객체에서 기본 타입의 값을 얻어내는 과정
박싱은 포장 클래스 변수에 기본 타입 값이 대입될 때 발생. 반대로 언박싱은 기본 타입 변수에 포장 객체가 대입될 때 발생.
Integer obj = 100; //박싱
int value = obj; //언박싱
⚠️ 포장 객체는 내부 값을 비교하기 위해 ==와 ≠ 연산자를 사용할 수 없다. 내부의 값을 비교하는 게 아니라 포장 객체의 번지를 비교하기 때문이다.
Math 클래스는 수학 계산에 사용할 수 있는 메소드 제공
//절대값
int v1 = Math.abs(-5); //v1 = 5
//올림값
double v3 = Math.ceil(5.3); //v3 = 6.0
//버림값
double v5 = Math.floor(5.3); //v5 = 5.0
//최대값
int v7 = Math.max(5, 9); //v7 = 9
//최소값
int v9 = Math.min(5, 9); //v9 = 5
//랜덤값
double v11 = Math.random(); // 0.0 <= v11 <= 1.0
//반올림값
long v14 = Math.round(5.3); //v14 = 5
날짜와 시간을 읽을 수 있도록 java.util 패키지에서 Date와 Calendar 클래스, 날짜와 시간을 조작할 수 있도록 java.time 패키지에서 LocalDateTime 등의 클래스를 사용하면 된다
| 클래스 | 설명 |
|---|---|
| Date | 날짜 정보를 전달하기 위해 사용 |
| Calendar | 다양한 시간대별로 날짜와 시간을 얻을 때 사용 |
| LocalDateTime | 날짜와 시간을 조작할 때 사용 |
숫자 또는 날짜를 원하는 형태의 문자열로 변환
| Format 클래스 | 설명 |
|---|---|
| DecimalFormat | 숫자를 형식화된 문자열로 변환 |
| SimpleDateFormat | 날짜를 형식화된 문자열로 변환 |
문자열이 정해져 있는 형식으로 구성되어 있는지 검증하기 위해 정규 표현식(Regular Expression)을 사용한다.
| 기호 | 설명 | ||
|---|---|---|---|
| [ ] | 한 개의 문자 | [abc] | a, b, c 중 하나의 문자 |
| [^abc] | a, b, c 이외의 하나의 문자 | ||
| [a-zA-Z] | a~z, A~Z 중 하나의 문자 | ||
| \d | 한 개의 숫자, [0-9]와 동일 | ||
| \s | 공백 | ||
| \w | 한 개의 알파벳 또는 한 개의 숫자, [a-zA-Z_0-9]와 동일 | ||
| ? | 없음 또는 한 개 | ||
| * | 없음 또는 한 개 이상 | ||
| + | 한 개 이상 | ||
| {n} | 정확히 n개 | ||
| {n,} | 최소한 n개 | ||
| {n,m} | n개부터 m개까지 | ||
| ( ) | 그룹핑 |
자바는 클래스와 인터페이스의 메타 정보를 Class 객체로 관리한다.
(메타 정보 ❓ 패키지 정보, 타입 정보, 멤버(생성자, 필드, 메소드) 정보 등을 말한다 )
⏩ 리플렉션 : 메타 정보를 프로그램에서 읽고 수정하는 행위
리플렉션을 사용하는 이유
객체의 타입은 모르지만 특정 클래스의 메서드 또는 필드를 호출해야 하는 경우에 사용한다
Class claz = 클래스이름.class; - 클래스로부터 얻기Class claz = Class.forName(”패키지…클래스이름”); - 클래스로부터 얻기Class claz = 객체참조변수.getClass(); - 객체로부터 얻기1, 2번은 클래스 이름만 가지고 Class 객체를 얻는 방법, 3은 객체로부터 Class 객체를 얻는 방법
패키지와 타입 정보 얻기
| 메소드 | 용도 |
|---|---|
| Package getPackage() | 패키지 정보 읽기 |
| String getSimpleName() | 패키지를 제외한 타입 이름 |
| String getName() | 패키지를 포함한 전체 타입 이름 |
멤버 정보 얻기
| 메소드 | 용도 |
|---|---|
| Constructor[] getDeclaredConstructors() | 생성자 정보 읽기 |
| Field[] getDeclaredFields() | 필드 정보 읽기 |
| Method[] getDeclaredMethods() | 메소드 정보 읽기 |
리소스 경로 얻기
| 메소드 | 용도 |
|---|---|
| URL getResource(String name) | 리소스 파일의 URL 리턴 |
| InputStream getResourceAsStream(String name) | 리소스 파일의 InputStream 리턴 |
어노테이션의 용도
ex. @Override 어노테이션
컴파일러가 메소드 재정의 검사를 하도록 설정. 정확하게 재정의 되지 않았을 경우, 컴파일러는 에러를 발생
Spring Framesork 나 Spring Boot는 다양한 종류의 어노테이션을 사용하니 잘 익히자!
어노테이션 정의
public @interface AnnotationName{}
// 어노테이션은 아래처럼 사용됨
@AnnotationName
public @interface AnnotationName{
String prop1();
int prop2() default 1;
}
@AnnotationName(prop1 = "값"); //값을 초기화 하지 않았으니 반드시 값을 기술해야함
@AnnotationName(prop1 = "값", prop2 = 3); // prop2는 기본값이 있으므로 생략 가능
어노테이션은 속성을 가질 수 있다. 속성은 타입과 이름으로 구성되고 이름 뒤에 괄호를 붙인다.
속성의 기본값을 default로 지정할 수 있다.
public @interface AnnotationName{
String value();
int prop2() default 1;
}
@AnnotationName("값"); // 어노테이션을 코드에 사용할 떄는 값만 기술할 수 있다
@AnnotationName(value = "값", prop2 = 3); //다른 속성값과 동시에 주려면 속성 이름 언급
어노테이션은 기본 속성인 value를 가질 수 있다.
어노테이션은 설정 정보!
어떤 대상에 설정 정보를 적용할 것인지, 클래스인지 메소드인지…등등을 명시해야 한다.
| ElementType 열거 상수 | 적용 요소 |
|---|---|
| TYPE | 클래스, 인터페이스, 열거 타입 |
| ANNOTATION_TYPE | 어노테이션 |
| FIELD | 필드 |
| CONSTRUCTOR | 생성자 |
| METHOD | 메소드 |
| LOCAL_VARIABLE | 로컬 변수 |
| PACKAGE | 패키지 |
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface AnnotationName{
}
@AnnotationName //TYPE(클래스)에 적용
public class ClassName{
@AnnotationName //필드에 적용
private String fieldName;
//@AnnotationName @Target에 CONSTRUCTOR가 없으니 생성자는 적용 안 됨
public ClassName(){}
@AnnotationName //메소드에 적용
public void methodName(){}
}
@AnnotationName을 어제까지 유지할 것인지 지정
| RetentionPolicy 열거 상수 | 어노테이션 적용 시점 | 어노테이션 제거 시점 |
|---|---|---|
| SOURCE | 컴파일 할 때 적용 | 컴파일 된 후에 제거 |
| CLASS | 메모리로 로딩할 때 적용 | 메모리로 로딩된 후에 제거 |
| RUNTIME | 실행할 때 적용 | 계속 유지 |
@Target ({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationName{
}
어노테이션은 아무런 동작을 가지지 않는 설정 정보!
설정정를 이용해서 처리할 것인지는 애플리케이션의 몫이다
| 리턴 타입 | 메소드명(매개변수) | 설명 |
|---|---|---|
| boolean | isAnnotationPresent(AnnotationName.class) | 지정한 어노테이션이 적용되었는지 여부 |
| Annotaiton | getAnnotation(AnnotationName.class) | 지정한 어노테이션이 적용되어 있으면 어노테이션을 리턴, 아니면 null을 리턴 |
| Annotaiton[] | getDeclaredAnnotations() | 적용된 모든 어노테이션을 리턴 |
package ch12.sec12;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD}) //적용대상 : METHOD
@Retention(RetentionPolicy.RUNTIME) //유지정책 : RUNTIME
public @interface PrintAnnotation {
String value() default "-"; //선의 종류
int number() default 15; //출력횟수
}
이것이 자바다(신용권, 임경균 지음)