자바 기본
포스트
취소

자바 기본

변수와 타입

변수

  • 데이터의 저장과 참조를 위해 ‘할당된 메모리 공간’에 붙인 이름

    기본 타입

  • 이진수의 음수화 : 1의 보수화 후 1을 더함. 올림 수는 버림
  • 소수점 기준, float, double은 각각 6, 15자리의 정밀도를 갖는다
  • long 타입 정수를 표현할 때 리터럴 끝에 ‘L’ 문자 추가
  • 숫자 표현, 리터럴 표현 - 2진수 : 0B 8진수 : 0 16진수 : 0x
  • 숫자 리터럴 표현 시 ‘100_000’ 처럼 언더바 사용 가능. 컴파일 과정에서 제거됨
  • 제곱수의 표현 - 3.4e3 == 3.4 x 10^3

    타입 변환

  • 자동 형변환 : 자료형의 크기가 큰 방향으로 형 변환이 일어남
  • 자료형의 크기에 상관없이 정수 자료형보다 실수 자료형이 우선함
  • 정수형 -> 실수형 변환시 오차는 존재하겠지만 데이터의 손실은 발생하지 않음

CHAPTER 3 연산자

연산자와 연산식

  • 정수형 연산을 4byte int형으로 진행
  • 연산을 동반하는 상황에선 byte, short 타입으로 선언하더라도 생각만큼 메모리가 절약되지 않고, 오히려 타입 변환 과정만 추가됨
  • 서로 다른 타입의 피연산자가 산술 연산식에 존재한다면, 더 큰 메모리를 할당하는 피연산자의 타입이 연산식의 결과에 부여된다.
  • 실수 연산은 기본적으로 오차가 존재한다고 가정해야 한다. 연산 시 소수점 이하 셋째 자리에서 오차가 발견될 수도 있다.

    연산자의 종류

  • 비교 연산자에서 실수 비교는 자제한다.
  • 쉬프트 연산자 예시 int num = A << Z : A의 비트 열을 Z만큼 왼쪽으로 이동 0000_0001의 경우 ‘«’ 하면 2씩 곱해지는 거와 마찬가지

조건문과 반복문

조건문: if문, switch문

  • 삼항 연산자로 간단한 if-else 처리

참조 타입

참조 타입과 참조 변수

  • 상수(final)는 값을 단 한번만 할당할 수 있으며 변경 불가하다

    배열

  • fill 메소드를 통해 특정 인자를 받아 한번에 초기화할 수 있다
  • 배열 복사 관련 메소드가 존재하므로 검색 활용
  • sort 메소드는 compareTo 메소드를 이용하여 정렬 기준을 설정

    열거 타입

  • enum 등장으로 정수 열거형을 별도 타입으로 빼낼 수 있게 됨
  • 구식 방법인 정수형 열거의 대안이다
  • 싱글턴, enumMap, enumSet 그리고 방어적 복사를 생략할 수 있는 강력한 불변객체로 활용할 수 있다

클래스

필드

  • 필드는 필드 답게, 객체의 속성과 관련 없는 변수는 최대한 지역 변수로

인스턴스 멤버와 정적 멤버

  • JVM에서 클래스 로드가 완료돼야 인스턴스 생성이 가능한데 클래스가 로드되는 시점에 정적 멤버는 이미 메모리 영역에 할당되어 있다
  • 클래스 내부에 블록 스코프를 활용하여 정적 메소드를 클래스 로드 시점에 호출할 수 있다
  • 정적 멤버는 인스턴스 없이 사용할 수 있고 불필요한 메모리 할당을 방지할 수 있지만 이 때문에 오히려 불필요한 메모리를 할당하는 걸로 볼 수도 있다 정적 멤버는 공유되고 반복되는 상황에서 효율적이다

상속과 추상클래스

상속

  • 연관된 일련의 클래스들에 대해 공통 규약을 정의
  • 자식 클래스 인스턴스 생성시 부모 클래스 생성자가 먼저, 함께 호출된다
  • private 멤버는 자식 클래스에서 직접 접근할 수 없다.
  • 상속 관계에서의 필드 선언 시 동일한 변수를 사용하지 않도록 주의
  • 정적 클래스는 오버라이딩의 대상이 아니다
  • 부모 타입의 구현 객체를 자식 객체로 했을 때 부모 타입의 멤버에만 접근 가능하고, 재정의된 메소드가 있다면 자식 메소드가 호출됨
  • is-a 관계과 명확할 때

    추상 클래스

  • 일반 클래스의 상속과 달리 추상 클래스는 객체 생성이 불가능하다
  • 추상 클래스는 하나의 규격이라 보면 되고 인터페이스가 좀더 추상적이다
  • 실체 클래스가 공통적으로 가져야할 멤버를 정의해놓으며 멤버 통일에 목적

인터페이스

인터페이스

  • 이미 형성된 계층 트리에서 인터페이스에 새로운 추상 메소드를 추가하긴 힘들다 이런 상황에서는 실체화가 필요 없는 디폴트 메소드를 활용하자
  • 정적 메소드를 활용하여 인터페이스만으로 메소드 사용이 가능하다
  • 주로 정적 멤버 인터페이스를 많이 사용하는데, UI 프로그래밍에서 이벤트를 처리할 목적으로 많이 활용된다
  • 주로 has-a 관계

    타입 변환과 다형성

  • 자식 instanceof 부모는 참이다

중첩 클래스와 중첩 인터페이스

중첩 클래스와 중첩 인터페이스 소개

  • 정적 중첩 클래스나 인스턴스 중첩 클래스에서 바깥 클래스의 필드가 private이어도 참조 가능
  • 중첩 클래스는 해당 클래스 정의를 감추어야할 때 유용하게 사용 된다
  • 컬렉션 프레임워크의 iterator 메소드도 Iterator 인터페이스를 구현한 중첩 클래스를 이용하는 것이다
  • 일반적으로 바깥 클래스 외부에서 해당 클래스의 중첩 클래스 객체를 생성하는 일은 거의 없다
  • 메소드 소속 중첩 클래스의 경우 메소드 내에서 객체를 생성하고 사용한다 주로 비동기 처리를 위해 스레드 객체를 만들 때 사용된다
  • 중첩 인터페이스의 경우 주로 정적 중첩 인터페이스로만 선언하며 UI 프로그래밍에서 이벤트를 처리할 목적으로 자주 활용되며 필드 멤버로만 선언된다

    익명 객체

    익명 객체의 가장 단순한 형태 new Printable()<익명>{ 실체 메소드 (...) {...}; }

  • 생성자에 바로 스코프와 함께 메소드 정의가 이루어진다
  • 인터페이스는 본래 자신이 구현 객체가 될 수 없지만 이러한 방식으로는 가능하다
  • 자식 클래스 또는 구현 클래스가 재사용되지 않고 오로지 특정 위치에서 사용할 경우라면 명시적으로 선언하는 것이 귀찮은 작업이므로 익명 클래스를 고려해볼만 하다 ex) comparator

예외 처리

예외 클래스

  • 에러 : 하드웨어 오동작으로 발생
  • 예외 : 프로그램 자체 오류
  • Exception 클래스를 상속하는 예외 중 RuntimeException을 제외한 예외에 대해선 예외 처리가 필수적
  • 직접 Exception을 상속하여 정의할 수도 있다

    예외 처리

  • main 메소드로 예외를 넘기면, 이 예외는 호출 주체인 가상머신에게 넘어감 즉, 프로그램이 종료됨
  • 과도한 예외 처리는 성능 저하로 이어진다
  • 종료해야될 리소스가 존재한다면 finally 스코프에 기입한다
  • 유효성 부적합 판정을 받았을 때 return이 아닌 비검사 예외를 명시하되 표준 예외를 사용하자
  • try/catch를 남발하면 오류가 발생했을 때 제어 흐름이 중단되지 않아 부차적 문제를 발생시킬 수 있고 stack trace를 보존하지 않는 로깅은 디버깅을 어렵게 만드는 일이다. 책임지지 못할 오류는 잡지 않는다 그래야 JVM이든 어딘가에서 로그를 남길 수 있기 떄문이다

기본 API 클래스

java.lang 패키지

Wrapper

  • toString 오버라이딩 되어있어 출력시 주소가 아닌 값이 나온다
  • 자동 박싱, 언박싱이 지원된다
  • 모든 Wrapper 클래스는 Number 클래스를 상속한다 Big
  • 생성자 매개변수로 문자열 형태의 숫자를 대입함
  • BigInteger : long 범위를 벗어난 정수를 표현
  • BigDecimal : double 범위를 벗어난 실수를 표현

    java.util 패키지

  • StringBuilder : 내부에 문자열 관리를 위한 메모리 공간이 존재하여 메소드 체인으로 참조 변수의 데이터를 변환하는 형식 기존 String concat 메소드와 비교하여 메모리에 유리함 StringBuffer의 대안. 스레드 안전하진 않지만 싱글 스레드상 속도 우위
  • Scanner : 생성자로 전달되는 대상으로부터 데이터를 추출하는 기능을 제공
  • StringTokenizer : 특정 기준을 가지고 문자열을 작게 나누어야할 때 사용 토큰 : 구분자를 기준으로 나뉜 문자열 조각
  • parsing이 필요하고 짧은 입력 값이면 Scanner
  • 단순히 한 줄씩 읽거나 입력 값이 많다면 BufferReader

컬렉션 프레임워크

컬렉션 프레임워크

  • 인스턴스의 저장을 목적으로 하는 자료구조 중 정형화된 것
  • 배열보다 컬렉션을 지향하는 이유는 제네릭 타입과 데이터 조작 시 다양한 api가 주는 편리함 때문이다
  • 중복 판단과 정렬 등에 equals, hashcode, compare 등을 이용함
  • 버킷의 개수가 예상된다면 생성자의 인자로 넣어 버킷의 개수를 늘리는 과정을 최대한 배제시키자
  • 동기화된 클래스로 Vector, Stack, HashTable 등이 있지만 보완품이 있다
  • Tree는 자체적으로 인스턴스를 정렬한다
  • 이진 탐색을 하려면 올바르게 정렬해야 한다
  • Arrays.asList의 반환 타입은 update 관련 메소드를 사용할 수 없다 수정이 필요하다면 new 연산자를 통한 ArrayList를 이용하면 된다 둘다 stream은 이용할 수 있다
  • Map은 Iterable 인터페이스를 구현하지 않으므로 직접 반복문을 활용할 수 없다 메소드를 활용하여 타입 변환한 뒤 순차적 접근이 가능하다
  • Stack 대신 Deque-ArrayDeque 를 사용하자 (Spec 권장) ArrayDeque는 스레드 안전하지 않기 때문에 멀티 스레드 환경에서는 LinkedBlockingDeque, ConcurrentLinkedDeque 를 이용하자 전자는 멀티 스레드 환경의 단일 스레드, 후자는 멀티 스레드 권장

네트워크

소켓

  • 멀티 스레드 환경에서 서버 소켓은 클라이언트 소켓이 connect 하였을 때 connection 에 대한 listener 인 accept 메소드로 인지한 뒤 클라이언트 소켓과 1대1로 연결된 소켓을 반환한다 이 소켓은 서버 소켓과 동일한 포트를 갖는다.

모던 자바

람다

  • 익명 클래스와 내부 동작 원리는 다르다
  • Predicate, Supplier, Consumer, Function<T, R>
  • 추상 메소드가 단 하나만 존재하는 함수형 인터페이스일 때 람다 사용 가능
  • 람다식을 더 줄인 게 메소드 참조 (System.out::println)
  • () -> obj.method 같은 건 Object::method 로 변환하자

    옵셔널

  • NullPointerException의 if 로직 대응 코드를 대체할 수 있음
  • NPE 방어 로직은 가독성과 유지 보수성이 떨어진다

    컬렉션 스트림

  • 컬렉션 데이터를 추상화하고 순차적으로 처리하는 데 쓰인다
  • 기존 반복문으로 처리하던 게 내부에서 동작할 뿐이다
  • 지연 처리 방식 적용으로 최종 연산 메소드를 호출해야 실행 된다 Parallel Stream
  • 병렬 처리의 경우 CPU 코어 개수가 그에 맞게 필요하다
  • 병렬 처리는 연산의 횟수를 줄이는데 있지 않고 연산의 단계를 줄이는데 있다
  • 스레드와 같이 병렬 처리를 남용하면 성능 저하만 초래한다 [참고] https://sejoung.github.io/2019/01/2019-01-31-java8_stream_tutorial_examples/
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

HTTP - 7 - header - caching & conditional request

자바 JVM