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