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
복사