[Java] 핵심 키워드

Updated: Categories:

자바에서 꼭 알아야하는 핵심 키워드에 대해 알아보자

용어정리

변수

  • 전역 변수(== 멤버 변수, 필드)
    • 인스턴스 변수 : 클래스 내부에 선언한 변수
    • 클래스 변수 : 인스턴스 변수를 static으로 선언한 변수
  • 지역 변수
    • 메소드 내부에 선언한 변수
    • 매개 변수(파라미터) 포함

클래스 vs 객체 vs 인스턴스

  • 클래스 : 코드상으로만 존재하는 설계
  • 객체 : 설계된 클래스를 선언한 상태
  • 인스턴스 : 객체를 초기화하여 메모리에 할당한 상태
  • 객체가 인스턴스의 의미까지 포함하므로 굳이 구분하여 말하지 않아도 된다.

함수 vs 메소드

  • 함수 : 독립적으로 존재함
  • 메소드 : 객체지향 언어에서 클래스에 종속적인 함수. 클래스 함수라고도 함
  • 클래스 외부에 함수가 존재할 수 없으므로, 자바에서는 모든 함수를 메소드라 칭함

Overloading vs Overriding

  • Method Signature
    • 자바 컴파일러가 메소드를 구분하는 기준
    • 메소드의 이름, 매개변수 개수, 매개변수 타입의 순서
      • 리턴 타입은 포함 X
      • 매개변수 타입은 다형성을 보장함 (ex. Object라면 모든 타입 가능)
  • Overloading
    • 기존에 없는 메소드를 추가하는 것
    • 메소드 이름을 제외한 메소드 시그니처가 달라야함
      • 매개변수 개수, 타입이 다르면 새로운 메소드를 선언할 수 있음
    • 같은 클래스 내에서 적용됨
  • Overriding
    • 기존에 존재하는 메소드를 상속하여 재정의하는 것
    • 기존의 메소드와 메소드 시그니처 + 리턴 타입이 같아야함
      • 메소드 이름, 매개변수 개수, 타입, 리턴 타입이 같아야 함
    • 상속관계에서 적용되며, 부모클래스보다 접근제어자를 좁게 재정의 불가
    • static 메소드는 재정의 불가
  • 객체지향의 다형성을 장점을 얻는다.


Type

원시타입 (Primitive Type)

  • 실제 데이터를 메모리에 저장하는 타입
    • 실제 값을 stack 영역에 저장하며, 고유한 주소를 가진다.
  • 8가지 종류가 있음
    • boolean, byte, short, int, long, float, double, char
종류 데이터형 byte bit 범위
논리형 boolean 1 8 true 또는 false
문자형 char 2 16 ‘\u0000’ ~ ‘uFFFF’ (16비트 유니코드 문자 데이터)
정수형 byte 1 8 -128 ~ 127
정수형 short 2 16 -32768 ~ 32767
정수형 int 4 32 -2147483648 ~ 2147483647 (21억)
정수형 long 8 64 -9223372036854775808 ~ 9223372036854775807 (100경)
실수형 float 4 32 1.4E-45 ~ 3.4028235E38
실수형 double 8 64 4.9E-324 ~ 1.7976931348623157E308
  • Java에서 데이터를 다루는 최소 범위는 1 Byte
    • boolean도 1bit만 필요하지만, 어쩔수 없이 1 Byte로 저장.
  • jvm에서는 스택 영역에 4 Byte 단위로 저장함
    • 기본적으로 int로 형변환하여 연산함
    • long 사용시 L, float 사용시 F를 붙여야함

참조타입 (Reference Type)

  • 데이터가 저장된 주소값을 저장하는 타입
    • stack 영역에 저장된 데이터의 주소값을 heap 영역에 저장한다
      • 주소값으로 4 byte를 할당받는다
  • 원시타입을 제외한 모든 타입이다

차이점

  • 각 타입마다 기본값이 있기 때문에 원시타입에는 null을 넣을수 없지만, 참조타입은 가능
  • 원시타입은 제네릭 타입으로 사용할 수 없지만, 참조타입은 가능
  • 원시타입은 stack에 바로 접근하기에 접근속도가 빠르지만, 참조타입은 주소를 통해 한번더 접근해야하기에(언박싱) 느리다.

Wrapper Class

  • 8가지의 원시타입을 객체로 표현한 것
  • jdk 1.5부터 오토박싱과 오토언박싱을 지원한다.
    • 오토박싱 : Integer a = 1
    • 오토언박싱 : int a = new Integer(1)
  • 비교시에도 오토박싱과 오토언박싱을 지원한다.
    • 1 == Integer(1)
    • 단 래퍼 클래스 비교시 == 사용하면 주소값을 비교함
  • 사용이유
    1. 객체이므로 Object를 사용함으로써 타입이 유연함 (메소드의 매개변수로 받을때)
    2. java.util 패키지에서 객체만 처리하므로 래퍼 클래스 필요
      • 원시타입을 제네릭 타입으로 사용 불가
      • ex) ArrayList<Integer>에 1 저장시 오토박싱 일어남
    3. 멀티스레드에서 동기화를 하기 위해서 (공유 메모리 영역인 힙영역에 저장되므로)

Call By Reference vs Call By Value

  • 메소드의 매개변수 호출 방식
  • Call By Reference
    • 매개변수에 데이터를 가리키는 주소값을 복사
  • Call By Value
    • 매개변수에 데이터 값 자체를 복사
  • 자바는 Call By Value !!!
    • 자바는 데이터(주소값) 자체를 복사함
    • 헷갈리는 이유 : 참조타입은 데이터에 주소값이 들어있는데, 이를 복사하기 때문에 Call By Reference처럼 보이기 때문


동일성 vs 동등성

  • 동일성(identity) : 두 객체가 완전히 같은 경우
    • 주소까지 완전히 동일한 객체일 때 (stack or heap 영역이 완벽히 일치)
    • == 연산의 결과
  • 동등성(equality) : 두 객체가 같은 정보를 갖고 있는 경우
    • 주소가 달라도 내용이 동일할때
    • equals 연산의 결과

hashcode & equals

  • hashcode()
    • 객체가 가지는 고유의 값을 반환하는 메소드
    • Object 클래스의 기본 메소드는 객체의 메모리 주소값을 해시코드로 만들어 반환한다
    • HashMap과 같은 자료구조에서 동등성 비교를 위해 사용된다.
  • equals()
    • 객체가 가진 정보로 객체의 동등성을 비교한 결과를 나타내는 메소드
    • Object 클래스의 기본 메소드는 객체의 메모리 주소값을 비교한다
      • == 연산도 메모리 주소값을 비교한다
  • equals()와 hashcode() 두 메소드 모두 객체의 동등성을 검사하기 위한 것이다.
  • 한 객체의 동등성 검사 기준은 동일해야 한다.
    • 즉, 두 메소드 중 하나를 재정의한다면 나머지 하나도 반드시 재정의해줘야 한다!


Throwable

Error와 Exception의 차이

  • Error
    • 시스템에 오류가 발생한 경우 (메모리 부족, 스택오버플로우 등등)
    • jvm에서 발생시키기 때문에 어플리케이션 레벨에서 잡을 수 없다
  • Exception
    • 정상적인 프로그램 흐름이 어긋날 때 발생한다 (배열 인덱스 초과, 널포인터 등등)
    • 예외 상황을 예측하여 개발자가 직접 핸들링할 수 있다

Checked Exception vs UnChecked Exception

  • Checked Exception
    • 실행 전 발생할 수 있는 에러 -> 컴파일 시점에서 발생함
    • Exception 처리를 강제한다
  • UnChecked Exception
    • 실행 중 발생할 수 있는 에러 -> 런타임 시점에서 발생함
    • RuntimeException을 상속받는다.
  • 롤백 관련 참고링크


제어자

접근제어자

image

  • 허용범위 : public > protected > default > private
  • 접근제어자는 타 사용자로부터 객체내부 접근을 제한하여 의도치 않은 오작동을 막기 위해 사용한다.
    • 캡슐화(정보은닉)

일반제어자

  • static, final, abstract, native, transient, synchronized, volatile, strictfp


static

  • 일반적인 변수는 jvm 힙 영역에 저장되는 반면, static 변수는 메소드 영역에 저장된다
  • 메소드 영역은 가비지 컬렉터가 동작하지 않으므로, 프로그램 종료시까지 할당된 채로 존재함
    • 모든 인스턴스가 같은 값을 유지해야할 때 사용
    • 유틸 클래스처럼 인스턴스를 생성할 필요가 없는 클래스에서 사용.
  • 장점
    • 할당 과정없이 빠른 호출이 가능
  • 단점
    • 무분별하게 사용시 JVM 메소드 영역을 너무 많이 차지함


final

  • 객체를 단 한번만 할당하는 제어자. 두번 할당하려하면 컴파일 오류 발생
  • 변수, 메소드, 클래스에 적용할 수 있음
    • 변수는 상수처럼 고정하여 사용
    • 메소드는 Overriding 불가
    • 클래스는 상속 불가
      • ex) Wrapper class
      • 하지만 내부 값은 변경 가능

Effectively final

  • Java 8 에 추가된 syntactic sugar의 일종 (문법적인 의미)
  • 변수가 초기화 된 이후 값이 한번도 변경되지 않았다면 Final과 동일하게 컴파일러에서 처리하는 것.


generic

  • 객체 생성 시점에 타입을 결정하여, 유연한 설계를 가능하게 하는 기능
  • 컴파일시 타입을 미리 체크한다
  • ex) Collection 라이브러리

Object와의 차이

  • Object는 객체 생성시 타입을 지정하지 않는다.
    • generic은 객체 생성시 타입을 지정해준다
  • Object를 사용하면 값을 리턴받을 때마다 캐스팅을 해줘야 하고, 개발자가 실수할 수도 있다
    • generic을 사용하면 객체 생성시 타입을 지정했기에 캐스팅이 필요 없다.
  • Object는 런타임시 오류가 발생한다
    • generic은 컴파일 시점에서 오류를 체크할수 있다.


syncronized

  • 멀티 스레드 환경에서 동기화 문제를 해결하기 위한 제어자
    • thread-safe한 환경을 만들기 위해 사용
    • 경쟁(Race condition)을 방지
  • 한 스레드가 자원을 점유하면 코드블록을 block 상태로 바꾸어 다른 스레드가 접근하지 못하게 함
    • 코드블록을 synchronized 제어자로 감싸주면 된다
    • 인스턴스 단위로 동기화됨 -> 메소드에는 잘 사용하지 않음
  • 제대로 설정하지 않으면 비효율적으로 동작하게 된다


volatile

  • 변수를 CPU 캐시가 아닌 메인 메모리에서 저장 + 조회할 것을 명시하기 위해 쓰이는 제어자
    • 변수가 CPU 캐시를 사용하지 않도록 선언하기

image

  • 자바는 성능 향상을 위해 메인 메모리에서 읽은 변수를 CPU 캐시에 저장한다
  • 멀티스레드 환경에서 스레드마다 다른 CPU 캐시를 가지고, 이는 동기화되지 않기 때문에 데이터 무결성 보장 X
    • 따라서 멀티스레드 환경에서 사용될 변수는 volatile 제어자를 붙여 메인메모리만 사용하도록 한다
    • 물론 동시성 처리는 thread-safe하도록 따로 구현해야함


interface vs abstract class

abstract class

  • 부모 클래스에서 필요한 대부분의 기능을 구현하고, 자식 클래스가 재정의할 부분은 추상 메소드로 선언하는 것
    • 상속 + 다형성을 통해 기능을 확장하는 것
    • 클래스와 메소드에 abstract 제어자를 붙여준다
  • 다중 extends 불가능
  • 필드값과 일반 메소드를 가질 수 있다.

interface

  • 인터페이스를 implements하는 여러 클래스들의 메소드 구현을 강제하기 위해 사용한다
    • 다형성을 통해 기능을 구현하는것
  • static 필드는 선언 가능
  • 다중 implements가 가능하다
  • java 8부터 default 메소드로 기본 구현이 가능하다

정리

  • 추상 메소드를 구현해야 한다

차이점

  • 인터페이스는 필드값을 가지지 못한다
  • 추상 클래스는 다중 상속이 불가능하지만 인터페이스는 다중 구현이 가능하다
  • 의미에 차이가 있다
    • 추상 클래스는 공통된 개념에 초점을 맞춘다
    • 인터페이스는 공통된 기능에 초점을 맞춘다


Annotation

  • 주석의 의미로 특별한 의미를 부여하거나 기능을 수행하도록 하는 메타데이터
    • javadoc에서 파생되었음

기능

  • 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보 제공
  • 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보 제공
  • 런타임시 특정 기능을 실행하도록 정보를 제공

종류

  • 표준 어노테이션 : 자바의 기본 제공 어노테이션
    • @Override, @Deprecated
  • 메타 어노테이션 : 어노테이션을 위한 어노테이션
    • @Target, @Retention
  • 마커 어노테이션 : 값을 지정할 필요가 없는 경우. 의미만 나타냄
    • @Serializable, @Cloneable, @Test

생성하기

@Target()   // 적용 가능한 대상 종류 지정
@Retention( )   // 어노테이션 적용 시점 지정
public @interface 어노테이션 {
    타입 요소();
    String str(); default{};
}
  • 정의는 인터페이스와 동일함
  • 규칙
    • 상속 불가
    • 요소 타입은 기본형, String, enum, 어노테이션, Class만 허용
    • ()안에 매개변수 선언 불가
    • 예외 선언 불가
    • 요소를 타입 매개변수로 정의 불가


Enum


Lambda

  • 익명함수를 뜻하고, 그 자체로 일급객체가 되며 매개변수처럼 사용할 수 있다.
  • 람다함수 내부에서는 외부 지역 변수를 사용할 수 없음
    • but final or Effectively final 변수는 사용할 수 있다
    • 람다 실행시 임시 스레드가 따로 생성되므로, 스택영역을 공유하지 않기 때문
    • final 변수 또한 공유하는 것이 아닌 람다식에서 ‘복사’하여 사용하는 것.

Functional Interface

  • 추상메소드가 하나만 존재하는 인터페이스
    • 인터페이스가 포함하는 메소드가 여러개여도 추상메소드만 하나면 조건 만족
    • @FunctionalInterface 어노테이션을 달아준다.
  • Functional Interface의 메소드를 람다식으로 재정의하여 사용한다
  • 여러 종류가 있음
종류 인자값 리턴값 용도
Runnable X X 실행시키기
Supplier X T 데이터 생성
Consumer T X 데이터 사용
Function T R 타입 변환
Predicate T bool 조건식


Stream

  • 컬렉션이나 배열의 요소를 내부적으로 반복 처리하는 기능
  • 원본 객체를 변경하지 않는다.
    • 원본 객체를 참조하여 어떠한 새로운 결과를 도출해 내는것
  • 일회용으로만 사용가능하다
    • stream 객체는 한번 선언하면 재사용이 불가능하다.
  • 3가지 단계를 거쳐 사용된다
    • stream 생성
    • 중개 연산 : filter-map API를 사용하여 지연(lazy) 연산을 통해 선응을 최적화함
    • 최종 연산 : 이때 실제로 연산이 이루어지며, 지연됐던 모든 연산을 처리한다
  • lambda와 stream의 장점
    • 불필요한 코드를 줄여 가독성을 좋게한다.
    • 내부 연산으로 병렬 처리가 가능하다
  • 단점
    • 디버깅이 힘들다
    • 예외처리도 힘들다.


Reflection

  • 객체에서 클래스의 정보를 가져와 분석할 수 있도록하는 기법
  • JVM에서의 런타임시 동작을 검사하고 수정하기 위해 사용된다
    • 이미 로딩된 클래스에서 동일한 새로운 클래스를 동적로딩하여 사용할 수 있도록 함
    • Proxy 패턴을 구현하기 위해 자주 사용된다
Class class = "객체".getClass();