Backend
home

2024. 7. 19

API 도큐먼트

자바 표준 모듈에서 제공하는 방대한 라이브러리들을 쉽게 찾아서 사용할 수 있도록 해주는 API 문서가 있다.
클래스와 인터페이스의 집합을 라이브러리라고 한다면, 이러한 라이브러리들의 사용 방법을 기술한 것을 API 도큐먼트라 한다.
String 예시
선언부를 통해 String 클래스가 어떻게 정의 되었는지 볼 수 있고, 상속 계층도를 통해 전체 상속 관계를 한 눈에 파악할 수 있다.
SUMMARY
NESTED : 중첩 클래스/중첩 인터페이스 목록으로 이동
FIELD : 필드 목록으로 이동
CONSTR : 생성자 목록으로 이동
METHOD : 메소드 목록으로 이동
⇒ 만약 링크가 없는 경우에는 공개된(public, protected) 멤버가 없다는 뜻이다.

java.base 모듈

String, System, Integer, Double, Exception, RuntimeException 등의 클래스는 모두 java.lang 패키지에 있고, Scanner는 java.util 패키지에 있다.
java.lang 패키지는 import 없이 사용 가능하다.

java.lang 패키지

Object 클래스

클래스를 선언할 때 extends 키워드로 다른 클래스를 상속하지 않으면 암시적으로 Object 클래스를 상속하게 된다.
자바의 모든 클래스는 Object의 자식이거나 자손 클래스가 된다.
Object가 가진 메소드는 모든 객체에서 사용 가능하다.
boolean equals(Object obj): 객체의 번지를 비교하고 결과를 반환한다.
int hashCode(): 객체의 해시코드를 반환
String toString(): 객체의 문자 정보를 반환

hashcode

객체 해시코드란 객체를 식별하는 정수를 말한다.
해시 - 암호화 기술에 많이 쓰인다.
예시 1 - 양방향 암호화
1q2w3e!! ⇒ 1234567890
1234567890 ⇒ 1q2w3e!!
예시 2 - 단방향 암호화
1q2w3e!! ⇒ 1234567890
예제 코드
package com.object; public class StudentExample { public static void main(String[] args) { Student s1 = new Student(1, "홍길동"); Student s2 = new Student(1, "홍길동"); Student s3 = new Student(1, new String("홍길동")); System.out.println(s1.getName() == s2.getName()); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s3.hashCode()); System.out.println("홍길동".hashCode()); } } // ---------------------------------------------------------------------------- package com.object; public class Student { private int no; private String name; public Student(int no, String name) { this.no = no; this.name = name; } public int getNo() { return no; } public String getName() { return name; } @Override public int hashCode() { int hashCode = no + name.hashCode(); return hashCode; } @Override public boolean equals(Object obj) { if (obj instanceof Student) { Student target = (Student) obj; if (no == target.getNo() && name.equals(target.getName())) { return true; } } return false; } }
Java
복사

Object 클래스 - toString

toString() 메소드는 객체의 문자 정보를 반환한다.
객체의 문자 정보란 객체를 문자열로 표현한 값을 의미하며, 기본적으로 “클래스명@16진수해시코드”로 구성되어 있다.
Date 클래스는 현재 날짜와 시간을 반환하고, String 클래스는 저장된 문자열을 반환하도록 오버라이딩 하고 있다.

롬북(Lombok) 사용하기

DTO 클래스 작성시 Getter, Setter, hashCode, equals, toString 메소드 자동으로 생성하여 코드 양을 줄여준다.
DTO (Data Transfer Object, 데이터 전송 객체):
데이터를 전송하기 위해 사용하는 객체.
클라이언트와 서버가 데이터를 주고받을 때 사용한다.

System 클래스

System 클래스의 정적 필드와 메소드를 이용하면 프로그램 종료, 키보드 입력, 콘솔 출력, 현재 시간 읽기 시스템 프로퍼티 읽기가 가능하다.

System 클래스 - exit()

Java 프로그램 시작하면 JVM 프로세스가 생성되고, 이 프로세스에서 main() 메소드를 호출한다.
프로세스를 강제 종료하고 싶다면 System.exit() 메소드를 사용한다.
exit() 메소드는 int 매개값이 필요한데, 이 값을 종료 상태값이라 한다.

System 클래스 - getProperty(), getProperties()

package com.system; import java.util.Properties; import java.util.Set; public class GetPropertyExample { public static void main(String[] args) { String osName = System.getProperty("os.name"); String userName = System.getProperty("user.name"); String userHome = System.getProperty("user.home"); System.out.println(osName + ", " + userName + ", " + userHome); Properties props = System.getProperties(); Set keys = props.keySet(); for(Object key : keys) { System.out.println(key + ": " + System.getProperty((String) key)); } } }
Java
복사

문자열 클래스 - String

문자열 리터럴인 경우에 자동으로 String 객체로 생성된다.
String 클래스의 다양한 생성자를 통해 직접 객체를 생성할 수도 있다.
예를 들어, 네트워크 통신으로 얻은 byte 배열을 원래 문자열로 변환하는 경우에 주로 쓰인다.

문자열 클래스 - StringBuilder

String은 내부 문자열을 수정할 수 없다.
String data = "JAVA"; data += "SCRIPT";
Java
복사
문자열을 변경이 가능한 것처럼 보이지만, 실제로는 새로운 String 객체를 생성하는 것이다.
새로운 String 객체가 생성되고 이전 객체는 계속 버려지기 때문에 효율성이 좋지 않다.
StringBuilder는 내부 버퍼(데이터를 저장하는 메모리)에 문자열을 저장해두고, 그 안에서 추가, 수정, 삭제 작업이 가능하도록 설계되어 있다.
잦은 문자열 변경이 필요하다면 String보다는 StringBuilder 를 사용하는 것이 좋다.

Wrapper 클래스

기본 타입의 값을 갖는 객체를 생성할 수 있다. 이러한 객체를 포장 객체라 한다.
포장 객체는 포장하고 있는 기본 타입의 값을 변경할 수는 없고, 오직 객체로 생성하는데 목적이 있다.
컬렉션 객체는 기본 타입의 값은 저장할 수 없고, 객체만 저장 가능하다는 특징이 있다.
(포장 객체가 필요한 이유는 컬렉션 객체 때문)
기본 타입의 값을 포장 객체로 만드는 과정을 박싱(boxing)이라 한다.
반대로 포장 객체에서 기본 타입의 값을 얻어내는 과정을 언박싱(unboxing)이라 한다.
// 박싱 Integer obj = 100; int value = obj; // 언박싱은 연산 과정에서도 발생한다. Integer obj = 100; int value = obj + 50;
Java
복사
대부분의 포장 클래스에는 ‘parse + 기본타입’ 으로 되어있는 정적 메소드가 있어서 문자열을 해당 기본타입 값으로 변환한다.
포장 객체 내부 값 비교 시 == 이나 != 와 같은 비교연산자를 사용할 수 없다.
엄밀히 말하면 범위의 값을 갖는 포장객체(boolean 또는 char 또는 -128 ~ 127 범위의 byte, short, int) 는 비교 연산자 사용이 가능하다.
포장 객체 내 어떤 값이 저장될 지 모르는 상황일 경우, equals() 메소드로 내부 값을 비교해야 한다.

Random 클래스

package com.util; import java.util.Arrays; import java.util.Random; public class LottoExample { public static void main(String[] args) { int[] selectNumber = new int[6]; Random r = new Random(); for(int i = 0; i < 6; i++) { selectNumber[i] = r.nextInt(45) + 1; } System.out.println(Arrays.toString(selectNumber)); } }
Java
복사

날짜와 시간 클래스

Data 클래스에는 여러 개의 생성자가 선언되어 있으나, 대부분 Deprecated 되어 기본 생성자만 주로 사용된다.
package com.util; import java.text.SimpleDateFormat; import java.util.Date; public class DateExample { public static void main(String[] args) { Date now = new Date(); System.out.println(now.toString()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy년 MM월 dd일 HH시 mm분 ss초"); System.out.println(sdf.format(now)); } }
Java
복사
Calendar 클래스는 달력을 표현하는 추상 클래스이다.
날짜와 시간을 계산하는 방법이 지역과 문화에 따라 차이가 있어 달력은 자식 클래스에서 구현하도록 되어 있다.
package com.util; import java.util.Calendar; public class CalendarExample { public static void main(String[] args) { Calendar today = Calendar.getInstance(); int year = today.get(Calendar.YEAR); int month = today.get(Calendar.MONTH) + 1; int day = today.get(Calendar.DAY_OF_MONTH); int weekInt = today.get(Calendar.DAY_OF_WEEK); int amPmInt = today.get(Calendar.AM_PM); String week = null; // 스위치 문으로 요일 가져오기 switch(weekInt) { case Calendar.MONDAY -> week = "월"; case Calendar.TUESDAY -> week = "화"; case Calendar.WEDNESDAY -> week = "수"; case Calendar.THURSDAY -> week = "목"; case Calendar.FRIDAY -> week = "금"; case Calendar.SATURDAY -> week = "토"; case Calendar.SUNDAY -> week = "일"; } String amPm = "오전"; // 조건문으로 "오전" 또는 "오후" 가져오기 uh~ if (amPmInt == Calendar.PM) { amPm = "오후"; } System.out.println(year + "년 " + month + "월 " + day + "일 " + week + "요일 " + amPm); } }
Java
복사

리플렉션

Java는 클래스와 인터페이스의 메타 정보(패키지 정보, 타입 정보, 멤버 정보 등)를 Class 객체로 관리한다.
메타 정보를 프로그램에서 읽고 수정하는 행위를 리플렉션(Reflection) 이라 한다.
예제 코드
package com.reflection; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Parameter; public class ReflectionExample { public static void main(String[] args) { Class clazz = Car.class; System.out.println(clazz.getPackage().getName()); // 패키지 이름 가져옴 System.out.println(clazz.getSimpleName()); // 클래스 이름 가져옴 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getType().getName() + " " + field.getName()); // 유형 이름, 필드 이름 가져옴 } Annotation[] declaredAnnotations = clazz.getDeclaredAnnotations(); for (Annotation anno : declaredAnnotations) { System.out.println(anno.getClass().getName()); } // 생성자 이름 가져옴 Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); for (Constructor c : declaredConstructors) { System.out.println(c.getName()); } // 파라미터 이름 가져옴 Constructor[] declaredConstructors2 = clazz.getDeclaredConstructors(); for (Constructor c : declaredConstructors2) { Parameter[] parameters = c.getParameters(); for (Parameter p : parameters) { System.out.println(p.getType().getName() + " " + p.getName()); } } } }
Java
복사

어노테이션

컴파일 시 사용하는 정보 전달
ex) @Override
빌드 툴이 코드를 자동으로 생성할 때 사용하는 정보 전달
ex) @Data, @Getter, @Setter
실행 시 특정 기능을 처리할 때 사용하는 정보 전달
ex) @Scheduled
어노테이션은 자바 프로그램 개발 시 필수 요소다.
웹 개발 시 사용되는 Spring, SpringBoot 프레임워크에서는 다양한 종류의 어노테이션을 사용한다.

제네릭

결정되지 않은 타입을 파라미터로 처리하고, 실제 사용 시 파라미터를 구체적인 타입으로 대체시키는 기능이다.
package com.generic; public class Box { public Object content; }
Java
복사
모든 객체는 부모 타입인 Object로 자동 타입 변환 되므로, content 필드에는 어떤 객체든 대입이 가능해진다.
public class BoxExample { public static void main(String[] args) { Box box = new Box(); box.content = "안녕하세요"; box.content = 100; } }
Java
복사
제너릭 타입은 선언부에 ‘<>’ 부호가 붙고 그 사이에 타입 파라미터들이 위치한다.
만약 지정하지 않으면 Object 타입이 암묵적으로 사용된다.
package com.generic; public class Product <K, M> { private K kind; private M model; public K getKind() { return this.kind; } public M getModel() { return this.model; } public void setKind(K kind) { this.kind = kind; } public void setModel(M model) { this.model = model; } } package com.generic; public class Tv { } package com.generic; public class Car { } package com.generic; public class GenericExample { public static void main(String[] args) { Product<Tv, String> product1 = new Product<>(); } }
Java
복사

제네릭 - 제한된 타입 파라미터

경우에 따라 타입 파라미터를 대체하는 구체적인 타입을 제한할 필요가 있다.
숫자를 연산하는 제네릭 메소드는 Number 또는 자식 클래스(Byte, Short, Integer, Long, Double)로 제한할 필요가 있다.
모든 타입으로 대체할 수 없고, 특정 타입과 자식 또는 구현 관계에 있는 타입만 대체할 수 있도록 하는 타입 파라미터를 제한된 타입 파라미터(Bounded Type Parameter)라고 한다.
제한된 타입 파라미터를 사용하면 오버로딩을 줄일 수 있다.
public class GenericExample3 { public static <T extends Number> boolean compare(T t1, T t2) { // Number에 정의되어 있는 메소드 사용 double v1 = t1.doubleValue(); double v2 = t2.doubleValue(); return (v1 == v2); } public static void main(String[] args) { boolean result1 = compare(10, 20); System.out.println(result1); boolean result2 = compare(20L, 20D); System.out.println(result2); boolean result3 = compare(4.5, 4.5); System.out.println(result3); } }
Java
복사

제네릭 - 와일드카드 타입 파라미터

제네릭 타입을 매개값이나 반환 타입으로 사용할 때, 타입 파라미터로 와일드카드(?)를 사용할 수 있다.
와일드카드(?)는 범위에 있는 모든 타입으로 대체할 수 있다는 표시이다.
타입 파라미터의 대체 타입으로 Student의 자식 클래스만 가능하도록 선언할 수 있다.
반대로 Worker의 부모 클래스만 가능하도록 선언할 수도 있다.
// Applicant.java package com.generic5; import lombok.AllArgsConstructor; @AllArgsConstructor public class Applicant<T> { public T kind; }
Java
복사
// Course.java package com.generic5; // 와일드 카드 이해 public class Course { // 모든 사람이 들을 수 있는 과정 등록 public static void registerCourse1(Applicant<?> applicant) { String simpleName = applicant.kind.getClass().getSimpleName(); System.out.println(simpleName + ": 코스1 등록"); } // 학생만 들을 수 있는 과정 등록 public static void registerCourse2(Applicant<? extends Student> applicant) { String simpleName = applicant.kind.getClass().getSimpleName(); System.out.println(simpleName + ": 코스2 등록"); } // 직장인과 일반인만 들을 수 있는 과정 등록 public static void registerCourse3(Applicant<? super Worker> applicant) { String simpleName = applicant.kind.getClass().getSimpleName(); System.out.println(simpleName + ": 코스3 등록"); } }
Java
복사
// CourseExample.java package com.generic5; // 와일드 카드 이해 public class CourseExample { public static void main(String[] args) { Applicant<Person> p = new Applicant<>(new Person()); Applicant<Worker> w = new Applicant<>(new Worker()); Applicant<Student> s = new Applicant<>(new Student()); Applicant<HighStudent> hs = new Applicant<>(new HighStudent()); Applicant<MiddleStudent> ms = new Applicant<>(new MiddleStudent()); // 전체 다 됨 Course.registerCourse1(p); Course.registerCourse1(w); Course.registerCourse1(s); Course.registerCourse1(hs); Course.registerCourse1(ms); // 학생(급식이들)만 됨 // Course.registerCourse2(p); // Course.registerCourse2(w); Course.registerCourse2(s); Course.registerCourse2(hs); Course.registerCourse2(ms); // 노비(일반인, 직장인)만 됨 Course.registerCourse3(p); Course.registerCourse3(w); // Course.registerCourse3(s); // Course.registerCourse3(hs); // Course.registerCourse3(ms); } }
Java
복사
// Person.java package com.generic5; public class Person { } class Worker extends Person {} class Student extends Person {} class HighStudent extends Student {} class MiddleStudent extends Student {}
Java
복사