Java/자바의 신 VOL.2

11. 이제 주요 API도 알아봤으니 정리해봅시다

h2boom 2024. 7. 5. 17:41

자바의 예약어

  • 자바의 예약어는 총 51개가 있다.
    • 그 중 const, goto 예약어는 더 이상 사용하지 않는다.
  • 타입과 관련된 예약어 (8개)
타입 설명
byte 8 bit 정수형
short 16 bit 정수형
int 32 bit 정수형
long 64 bit 정수형
float 32 bit 실수형
double 64 bit 소수형
char 0 ~ 65,535 범위를 갖는 정수형 (unsigned)
boolean true, false 만 존재하는 타입
  • 클래스, 메소드, 변수 선언, 객체 생성과 관련된 예약어 (26개)
타입 설명
package 클래스의 패키지를 선언할 때 사용하며 코드 내 단 한 번만 지정할 수 있다.
import 다른 패키지에 있는 클래스 및 선언된 요소들을 사용하기 위해서 사용한다.
interface 인터페이스 선언 시 사용한다.
abstract abstact 클래스 선언 시 사용한다.
class 클래스 선언 시 사용한다.
enum enum 선언 시 사용한다.
implements interface를 구현하기 위해 선언할 때 사용하며 여러 개의 인터페이스를 ,로 구분하여 나열할 수 있다.
extends 클래스나 abstract 클래스를 확장 시 사용하며 하나의 클래스만 확장할 수 있다.
private 다른 클래스에서의 접근을 불가능하게 하는 접근 제한자 (접근 제어자)
protected 같은 패키지 내에 있거나 상속받은 경우에만 접근할 수 있도록 하는 접근 제한자
public 누구나 접근할 수 있도록 하는 접근 제한자
final 변수에 사용할 경우 값을 변경하지 못하도록 상수로 선언하며 클래스에 사용 시 확장할 수 없도록 선언하며
메소드에 사용 시 오버라이딩 할 수 없도록 선언한다.
synchronized 동시 접근 제어자로 Thread Safe하게 해준다.
void 메소드에서 반환하는 값이 없다는 것을 의미한다.
static 하나의 인스턴스만 허용하는 제어자로 객체 생성 없이 접근할 수 있다.
return 메소드를 종료하고 값을 반환하기 위해 사용한다.
assert 검증을 위한 로직 선언 시 사용한다.
native 다른 언어로 구현된 것을 선언 시 사용한다.
new 새로운 객체 생성을 선언한다.
null 참조되고 있는 객체가 없다는 것을 선언한다.
strictfp strict 소수 값 제어자
super 상위 클래스 참조
this 현 객체에 대한 참조를 명시적으로 나타낼 때 사용한다.
transient Serializable 할 때 저장 / 전송되지 않는 객체를 선언한다.
volatile 하나의 변수를 여러 쓰레드가 참조할 때 모두 동일한 값을 바라보도록 할 때 사용한다.
instanceof 객체의 타입을 확인할 때 사용한다.
  • 조건 및 반복문과 관련 있는 예약어 (10개)
타입 설명
if 데이터 조건을 확인할 때 사용하며 if 괄호 안의 결과는 반드시 boolean 타입이어야 한다.
else if 조건에 부합하지 않는 경우를 선언한다.
switch 정수형 및 String 문자열의 값에 따른 분기를 할 때 사용한다.
case switch에서 선언한 변수의 값에 따른 작업을 선언한다.
default switch에서 case 조건에 부합되는 값이 없을 때 기본적으로 수행되는 작업을 선언한다.
for 조건에 따른 반복을 변수에 따라 수행하고자 할 때 사용한다.
do 무조건 한 번 수행 후 조건 반복을 하고자 할 때 사용한다.
while 조건에 따른 반복만 수행하고자 할 때 사용한다.
continue 반복 작업시 조건 확인문으로 이동하고자 할 때 사용한다.
break 반복 작업을 종료하고자 할 때 사용한다.
  • 예외 처리와 관련된 예약어 (5개)
타입 설명
try 예외가 발생 가능한 코드의 범위를 선언한다.
catch try로 묶은 범위내에서 예외가 발생할 때 처리 방법을 선언한다.
finally try-catch 블록 수행 후 반드시 실행해야 하는 작업을 선언한다. 
throw 예외를 발생시키거나 호출한 클래스로 넘길 때 사용한다.
throws 예외를 던질수도 있다는 것을 선언할 때 사용한다.

제네릭 (Generic)

  • 형 변환 시 발생할 수 있는 문제들을 사전에 없애기 위해서 만든 개념
    • 실행했을 때가 아닌 컴파일 시점에서의 문제를 해결한다.
// 제네릭 클래스 예시
public class CastingGeneric<T> implements Serializable {
	private T object;
	public void setObject(T obj) { /* 생략 */ }
	public T getObject() { /* 생략 */ }
}
  • 제네릭 타입 명명 규칙
    • E : 요소, 자바 컬렉션에서 주로 사용한다.
    • K : 키
    • V : 값
    • N : 숫자
    • T : 타입
    • S, U, V : 2, 3, 4번째에 선언되는 타입
  • 제네릭의 wildcard 타입
    • 메소드 선언 시 제네릭 타입의 제한을 해소하기 위해 특정 타입 대신 <?>를 사용한다.
    • 해당 타입을 사용 시 정확한 타입을 모르기 때문에 Object로 받는다.
// 제네릭 일반적인 wildcard 타입
public void wildcard(WildcardGeneric<?> c) {
	Object value = c.getWildcard();
}
  • 제한이 있는 wildcard 타입
    • 기본 wildcard 타입 <?>는 어떤 타입도 올 수 있기에 특정 타입만 가능하도록 제한을 걸 수 있다.
    • ex) <? extends TypeName> 으로 선언 시 TypeName 클래스를 확장한 모든 클래스를 의미한다.
// 제한이 있는 wildcard 타입
public void wildcard2(WildcardGeneric<? extends Car> c) {
	Car value = c.getWildcard();
}
  • 제네릭한 메소드 선언하기
    • wildcard 사용 시 매개 변수로 넘어온 타입을 변경할 수 없다는 한계가 존재한다.
    • 메소드를 제네릭하게 선언하면 제네릭 타입의 값을 변경할 수 있다.
// 제네릭한 메소드 선언
public <T> void genericMethod(WildcardGeneric<T> c, T addValue) {
	c.setWildcard(addValue);
	T value = c.getWildcard();
}

쓰레드 (Thread)

  • 자바 프로그램 하나 실행 시 하나의 프로세스가 추가되고 그 안에서 여러 쓰레드가 수행된다.
  • 쓰레드를 시작할 수 있는 인터페이스 / 클래스
    • java.lang.Runnable
    • java.lang.Thread
  • Runnable 인터페이스 구현
    • implements로 Runnable 인터페이스 구현을 선언해야한다.
    • public void run() 메소드 내용으로 쓰레드가 수행할 내용을 작성한다.
// Runnable 인터페이스 구현
public class RunnableClass implements Runnable {
	public void run() {
		// 내용 생략
	}
}
  • Runnable 구현 클래스 사용 예시
    • Runnable 인터페이스를 구현한 경우 Thread 생성자에 해당 객체를 추가해서 사용해야 한다.
    • run() 메소드를 실행시키기 위해서 start() 메소드로 호출해줘야 한다.
RunnableClass runnable = new RunnableClass();
new Thread(runnable).start();
  • 쓰레드 클래스를 확장하려면 extends 키워드로 상속을 받은 후 마찬가지로 run() 메소드를 작성한다.
    • Runnable 인터페이스와 달리 Thread 클래스를 확장하면 바로 start() 메소드를 사용할 수 있다.
  • 쓰레드 내용 간단 정리
    • Runnable 인터페이스나 Thread 클래스를 직접/간접적으로 구현한 클래스만 쓰레드로 처리될 수 있다.
      • Runnable 인터페이스를 구현하든 Thread 클래스를 확장해야 한다.
    • 쓰레드 선언 시 public void run() 메소드를 꼭 선언해야 한다.
    • 쓰레드를 시작하려면 쓰레드 객체의 start() 메소드를 호출해야 run() 메소드가 실행된다.
    • run() 메소드가 종료 시 쓰레드가 끝난다.
    • 데몬 쓰레드(Daemon Thread)의 경우 프로세스 내 다른 쓰레드들이 종료되면 데몬 쓰레드의 run() 메소드가 종료되지 않았더라도 데몬 쓰레드는 종료된다.
    • 쓰레드를 실행한 메소드에서 쓰레드가 종료될 때까지 대기하기 위한 메소드는 join()이다.
    • Object 클래스의 wait() 메소드 호출 시 쓰레드는 대기 상태가 되며 notify() / notifyAll()을 호출해야 깨어난다. 
    • 수행중인 쓰레드를 종료시키는 메소드는 interrupt() 이며, join() / sleep() / wait() 메소드가 호출된 상태의 쓰레드만 종료시킬 수 있다.
  • 쓰레드의 상태
상태 의미
NEW 쓰레드 객체는 생성됐지만 아직 시작되지 않은 상태
RUNNABLE 쓰레드가 실행중인 상태
BLOCKED 쓰레드가 실행 중지 상태이며, 모니터 락이 풀리기를 기다리는 상태
WAITING 쓰레드가 대기중인 상태
TIMED_WAITING 특정 시간만큼 쓰레드가 대기중인 상태
TERMINATED 쓰레드가 종료된 상태
  • synchronized 키워드
    • 메소드 선언 시 사용하면 하나의 객체를 공유하는 많은 쓰레드가 있어서 동시에 이 메소드에 접근한다고 하더라도 하나의 쓰레드만 메소드를 수행할 수 있다. 
    • synchronized 블록에 포함될 경우 하나의 쓰레드에서만 해당 블록 내 내용을 수행할 수 있다.

컬렉션 (Collection)

  • 자료구조 분류
    • 순서가 있는 목록(List)형
    • 순서가 중요하지 않은 셋(Set)형
    • 먼저 들어온 것이 먼저 나가는 큐(Queue)형
    • 키-값(Key-Value)로 저장되는 맵(Map)형
  • java.util.Collection
    • List, Set, Queue 타입 구현의 기본이 되는 인터페이스
    • Iterable 인터페이스를 확장하고 있다.
    • add(), addAll() : 데이터를 담는 메소드
    • contains(), containsAll(), isEmpty(), equals(), size() : 데이터 확인용 메소드
    • clear(), remove(), removeAll() : 데이터 삭제용 메소드
  • Collection - List 인터페이스
    • 목록을 저장할 때 사용하며 크기가 변하는 배열이다.
    • 각 데이터에 대한 위치가 있다.
    • 원하는 위치에 있는 데이터를 꺼내고 지우고 저장하는 작업이 가능하다.
    • 특정 데이터의 중복을 허용한다.
    • 순서대로 들어오는 데이터를 담아둘 때 용이하다.
  • Collection - Set 인터페이스
    • List와 비슷하지만 데이터의 순서가 중요하지 않다.
    • 데이터를 목록 형태로 저장한다.
    • 데이터 위치는 정해져 있지 않고 중복된 데이터가 존재하지 않는다.
    • 유일한 값만 뽑아내 사용할 때 용이하다.
  • Collection - Queue 인터페이스
    • 데이터를 순차적으로 처리하기 위한 인터페이스다.
    • FIFO (선입선출) 구조로 데이터가 들어온 순서대로 처리하기 용이하다.
    • offer() : 데이터를 담는 메소드
    • poll() : 데이터를 꺼내고 지우는 메소드
    • peek() 데이터를 꺼내는 메소드
  • Map 인터페이스
    • 중복되지 않는 키와 그 키와 연결된 값을 쌍으로 묶어 처리하는 인터페이스다.
    • Collection 인터페이스를 확장하지 않은 인터페이스로 부모 인터페이스가 존재하지 않는다.
    • key-value 쌍으로 데이터를 관리한다.
    • key는 중복될 수 없으며 value는 key만 다르다면 중복되어도 상관 없다.
    • put() : 데이터를 담는 메소드
    • get() : 키로 데이터를 꺼내는 메소드

IO

  • 파일이나 네트워크로 데이터를 읽고 쓰는 것을 통틀어 IO라고 한다.
  • IO의 기본은 Stream
    • 데이터를 읽을 때는 InputStream을 사용한다.
    • 데이터를 쓸 때는 OutputStream을 사용한다.
    • char 기반 데이터를 읽을 때는 Reader, 쓸 때에는 Writer를 사용한다.
  • InputStream / Reader
    • read() : 스트림의 내용 읽기
    • close() : 스트림 닫기
    • 주요 자식 클래스
      • FileInputStream : 바이트 기반의 파일을 읽을 때 사용하는 클래스
      • ObjectInputStream : 저장되어 있는 객체를 읽을 때 사용하는 클래스
      • FilterInputStream : 기타 여러 형태의 스트림을 처리하는 클래스의 부모 클래스
  • OutputStream / Writer
    • write() : 스트림에 내용 쓰기
    • flush() : 강제로 쓰기
    • close() : 스트림 닫기
    • 주요 자식 클래스
      • InputStream 과 동일하게 OutputStream으로 바꿔주면 된다. 
  • File 클래스
    • 파일 및 경로를 관리하는 클래스
    • exists() : 존재 여부 확인
    • isFile(), isDirectory() : 파일인지 경로인지 여부 확인
    • isHidden() : 숨겨진 파일 및 경로인지 확인
    • lastModified() : 마지막 수정 시간 확인
    • delete() : 파일 및 경로 삭제
    • 파일일 경우 사용하는 메소드
      • renameTo() : 파일 이름 변경
      • createNewFile() : 파일 생성
      • canRead(), canWrite(), canExecute() : 읽기 / 쓰기 / 실행 가능 여부 확인
    • 경로인 경우 사용하는 메소드
      • list(), listFiles() : 파일 목록 확인
      • mkdir(), mkdirs() : 경로 생성
  • Serializable 인터페이스
    • 객체를 다른 서버로 전송하거나 파일에 쓰기 / 읽기 위해서 구현해야하는 인터페이스
    • static final long serialVersionUID : 객체에 대한 serial 버전 값을 갖는 변수
  • transient 키워드
    • Serializable로 선언한 객체 내 전송 / 저장하지 않는 변수를 선언할 때 사용한다.
  • NIO
    • 보다 빠른 IO를 위해 추가된 패키지
    • Stream 대신 Channel 기반으로 데이터와 연결하고 Buffer를 사용해 데이터를 읽고 쓴다. 
  • NIO Buffer 클래스
    • get() : 데이터 읽기
    • put() : 데이터 쓰기
    • int capacity() : 버퍼에 담을 수 있는 크기를 리턴한다.
    • int limit() : 버퍼에서 읽거나 쓸 수 없는 첫 위치를 리턴한다.
    • int position() : 현 버퍼의 위치를 리턴한다.
    • Buffer flip() : limit 값을 현 position으로 지정 후 position을 0으로 이동
    • Buffer mark() : 현 position을 mark한다.
    • Buffer reset() : 버퍼의 position을 mark한 곳으로 이동한다.
    • Buffer rewind() : 현 버퍼의 position을 0으로 이동한다.
    • int remaining() : limit-position 결과를 리턴한다.
    • boolean hasRemaining() : position과 limit 값에 차이가 있으면 true를 리턴한다.
    • Buffer clear() : 버퍼를 지우고 현 postion을 0으로 이동하고 limit 값을 버퍼의 크기로 변경한다.

네트워크 프로그래밍

  • TCP 통신을 위한 Socket 클래스와 UDP 통신을 위한 Datagram 관련 클래스가 존재한다.
  • Socket 클래스
    • 데이터를 전달하고 받기 위해서 사용하는 클래스
    • ServerSocket 클래스는 데이터를 수신하기 위해서 사용하는 클래스
      • 클라이언트에서 데이터를 전달하면 Socket 객체로 받아 처리할 수 있게 해준다.
    • 데이터를 주고 받을 시 Socket 클래스를 통해 Stream, Reader / Writer 객체로 처리한다.
  • Datagram 클래스
    • DatagramPacket 클래스는 데이터를 전달하고 받기 위해서 사용하는 클래스다.
    • DatagramSocket 클래스는 데이터를 수신하기 위해서 사용하는 클래스다.
      • 클라이언트에서 데이터를 전달하면 DatagramPacket 객체로 받아 처리할 수 있게 해준다.
    • TCP는 연결할 때부터 서버가 시작되어 있어야 데이터를 전송할 수 있지만 UDP는 서버 시작 여부와 상관 없이 클라이언트에서 데이터를 전송할 수 있다. 

출처: 이상민, <자바의 신 VOL.2> 로드북