java
31편. 스레드(Thread) (4)
31편. 스레드(Thread) (4)
2023.04.09Callable과 Future Callable 기억을 되살려서 Runnable이 무엇이었는지 떠올려 봅시다. 전에 사용했던 Runnable은 실행이 끝난 후에 어떤 결과 값을 반환해 줄 수 없었으며, 예외가 발생할 수 있다고 throws 문을 통해서 표현할 수도 없었습니다. 하지만 Callable을 사용하면 결과 값도 돌려줄 수 있으며, 예외도 발생시킬 수 있도록 만들 수 있습니다. @FunctionalInterface public interface Runnable { public abstract void run(); } @FunctionalInterface public interface Callable { // 계산한 결과를 반환할 수 있는 메서드다. // 만약에 결과를 계산할 수 없으면 예외를 던질 ..
30편. 스레드(Thread) (3)
30편. 스레드(Thread) (3)
2023.04.07스레드의 상태 자바의 스레드는 총 6개의 상태(NEW, RUNNABLE, WAITING, TIMED_WAITING, BLOCKED, TERMINATED)를 가지고 있습니다. 참고로 자바의 스레드는 JVM(Java Virtual Machine, 자바 가상 머신) 위에서 돌아가며, 여기에 나와 있는 상태들은 가상 머신의 상태를 말하는 것입니다. 다시 말해서, 운영체제 스레드의 상태를 나타내는 것은 아닙니다. NEW 새로운 스레드를 만들면 NEW 상태가 됩니다. 이 상태의 스레드는 아직 시작되지 않았으며, start() 메서드를 호출하며 스레드를 시작하면 RUNNABLE 상태로 들어가게 됩니다. Thread thread = new Thread(new ThreadA()); System.out.println(th..
invokedynamic의 내부 동작
invokedynamic의 내부 동작
2022.05.22이 게시글은 자바 8을 기준으로 작성되었습니다. Invokedynamic 아래의 코드를 떠올려봅시다. 람다의 타입은 무엇일까요? 람다는 int, double 같은 기본 타입이 아니므로 참조 타입, 즉 객체의 참조여야 합니다. 다시 말해서, Runnable을 구현하는 클래스의 인스턴스에 대한 참조여야 합니다. package com.company; public class InvokeDynamicExample { public static void main(String [] args) { Runnable r = () -> System.out.println("Hello"); r.run(); } } 이를 javap로 뜯어보면 아래와 같은 바이트코드를 살펴볼 수 있습니다. 여기서는 명령 5~6에서 스택에 푸시된 람다..
38편. 레코드(Record)
38편. 레코드(Record)
2022.05.20도입 단순하게 데이터를 한쪽에서 다른 한쪽으로 전달하기 위해서만 사용되는 데이터 전송 객체(혹은 DTO)를 생각해봅시다. 이런 객체를 사용하는 이유는 다양한 집계 연산을 수행한 후의 결과를 담아두거나, 외부 시스템과 통신 시에 필요하지 않은 데이터를 제거하여 대역폭 사용량을 줄이기 위해, 세부 구현을 노출시키지 않기 위해서, 혹은 변경되지 말아야 하는 API 설계 상의 이유 등 다양한 이유가 있을 수 있습니다. 이를 제대로 구현하기 위해서는 (롬복이나 IDE의 도움을 받을 수도 있지만) 아래와 같이 게터(getter 혹은 accessor), equals(), hashCode(), toString() 처럼 계속 똑같은 구조의 코드를 반복해서 작성해야 했습니다. public class BookDto { pr..
JVM. 클래스로더 서브시스템(Class Loader Subsystem)
JVM. 클래스로더 서브시스템(Class Loader Subsystem)
2022.05.16JVM은 RAM에 위치하며, 실행 중에 클래스로더 서브시스템을 이용하여 클래스 파일을 RAM으로 가져옵니다. 이를 자바의 동적 클래스 로딩 기능이라고 합니다. 이 과정은 컴파일 타임이 아니라 런타임에 일어나며, 처음으로 클래스를 참조할 때 클래스 파일(.class)을 로드하고, 링크하고, 초기화 합니다. 로딩(Loading) 컴파일된 클래스(.class 파일)을 메모리에 적재하는 것이 클래스로더(class loader)의 주요 작업입니다. 보통, 클래스 로딩 과정은 메인 클래스(즉, static main() 메서드 선언이 있는 클래스)를 로드하는 것부터 시작됩니다. 이외에도 클래스 로딩은 아래의 상황에서 일어날 수 있습니다. // 클래스에 선언된 정적 메서드를 호출할 때 Car.invokeStaticMe..
번외편. 인터페이스라는 이름의 계약
번외편. 인터페이스라는 이름의 계약
2022.05.14이 글은 보호되어 있기 때문에 이것을 보려면 암호가 필요합니다.
37편. 열거형(Enum Types)
37편. 열거형(Enum Types)
2022.05.05열거형(Enum Type) 열거형(enum)은 여러 상수로 이루어진 고정 집합을 나타내는 특수 데이터 타입이라고 할 수 있습니다. 더 정확하게 말하면 자바 클래스의 특별한 한 종류라고 말할 수 있습니다. 보통 열거형은 아래와 같이 선언합니다. class, interface가 들어갔던 자리에 enum이 들어온 것을 눈여겨봐 주세요. enum 이름 { 상수1, 상수2, ..., 상수N } 열거형을 사용하면 서로 관련 있는 상수를 논리적으로 그룹화할 수 있습니다. 예를 들어서 방위(동, 서, 남, 북)를 나타내려면 열거형을 아래와 같이 쓸 수 있습니다. enum CardinalDirection { EAST, WEST, SOUTH, NORTH } 열거형 필드 작명 관습 열거형 작명 규칙은 클래스와 동일하고(즉,..
33편. 파일 입출력(File input and output)
33편. 파일 입출력(File input and output)
2022.05.04스트림(Stream) 파일 입출력을 알아보기 전에 스트림이 무엇인지 이해해야 합니다. 여기서 말하는 스트림은 읽거나 쓸 수 있는 1차원적인 데이터의 흐름을 말합니다. 마치 강이 상류에서 하류로 흐르는 것처럼, 데이터도 어느 한 출발지(source)에서 목적지(destination)로 흐르는 것처럼 말이죠. 여기서 출발지와 목적지는 파일, 키보드나 모니터, 원격 네트워크, 데이터베이스 시스템, 다른 프로그램 등과 같이 다양한 자원들이 될 수 있습니다. 프로그램을 기준으로 잡고 외부 자원(파일, 키보드 등)으로부터 데이터를 읽고 싶다고 해봅시다. 그러면 자연스럽게 외부 자원은 데이터의 출발지 혹은 데이터의 원천이 될 것입니다. 이렇게 출발지에서 생성된 데이터는 목적지인 프로그램으로 흐릅니다. 이때 이 흐름을..
32편. 람다식(Lambda expression)
32편. 람다식(Lambda expression)
2022.02.22함수형 인터페이스(Functional Interface) 람다식을 이해하기 전에 함수형 인터페이스에 대한 이해가 필요합니다. 함수형 인터페이스(Funcational Interface)란 하나의 추상 메서드를 갖는 인터페이스를 말합니다. 자바 8 이후에 추가되었으며, 이를 SAM 인터페이스(Single Abstract Method interface)라고도 부릅니다. 함수형 인터페이스의 대표적인 예로는 스레드에서 살펴봤던 Runnable 인터페이스를 꼽을 수 있습니다. @FunctionalInterface public interface Runnable { public abstract void run(); } @FunctionalInterface 자바 8 이후부터는 함수형 인터페이스를 나타내는 @Functio..
34편. 애노테이션(Annotation)
34편. 애노테이션(Annotation)
2022.02.18애노테이션(Annotation) 애노테이션은 소스 코드에 대한 메타데이터(metadata), 즉 다른 데이터를 설명해 주는 데이터를 제공합니다. 주석(comments)과 마찬가지로 코드를 실행하는데 있어서 직접적인 영향을 미치지는 않습니다. 클래스, 메서드, 변수, 매개변수 등에 애노테이션을 달 수 있으며, 애노테이션은 아래와 같이 문자 @로 시작합니다. @Override public void foo() { // ... } 보통은 리플렉션과 같이 활용되며, 문서, 컴파일러 혹은 IDE, 테스트 프레임워크(JUnit, JCStress 등)나 ORM(Hibernate, JPA 등) 등과 같이 다양한 곳에서 상당히 유용하게 사용됩니다. 애노테이션의 위치 애노테이션이 들어갈 수 있는 위치는 상당히 다양합니다. ..
26편. 제네릭(Generic)
26편. 제네릭(Generic)
2022.02.06여기서 컬렉션을 몰라도 크게 지장은 없으나 예제에서 사용된 List가 무엇인지 궁금하시다면 컬렉션 편이랑 같이 병행해서 보시기 바랍니다. 제네릭(Generic) 타입 안정성(type safety) 제네릭의 주 목적은 바로 타입 안정성을 제공하고 타입 캐스팅 문제를 해결하는 것입니다. 예를 들면, 아래의 코드를 생각해봅시다. 리스트에 값을 추가할 때는 문제가 없어보이지만, 리스트에서 값을 꺼낼 때는 컴파일러가 꺼낸 값이 무슨 타입인지 모르기 때문에 명시적으로 캐스팅을 해야 한다는 번거로움이 있습니다. 여기서 캐스팅을 잘못하면 캐스팅을 할 수 없다는 런타임 예외가 발생하므로 주의해야 합니다. List list = new ArrayList(); list.add(123); list.add("가나다"); // 타..
25편. 중첩 클래스(Nested Class)
25편. 중첩 클래스(Nested Class)
2022.02.06중첩 클래스(Nested classes) 중첩 클래스는 말 그대로 클래스 내에 정의된 클래스를 말합니다. 어떤 클래스가 한 곳에서만 쓰인다면 아래와 같이 해당 클래스를 중첩시키고 두 클래스를 한꺼번에 관리하는 것이 적절합니다. class OuterClass { // 외부 클래스 // ... class NestedClass { // 중첩 클래스 // ... } } 중첩 클래스는 다시 static으로 선언되지 않은 중첩 클래스인 내부 클래스(inner class)와 static으로 선언된 중첩 클래스인 정적 클래스(static class)로 나뉩니다. 여기서는 두 용어를 구분하도록 하겠습니다. class OuterClass { // 외부 클래스 // ... class InnerClass { // 내부 클래스..