자바 기초지식

Sieun Sim·2020년 6월 1일
1

CS 지식

목록 보기
2/2

OOP의 4가지 특징

  • 상속 추상화 캡슐화 다형성 (상추 캡이다)
  • 추상화 : 객체들의 공통적인 특징을 뽑아내는 것. 객체들의 공통적인 데이터와 기능을 도출: 현실의 복잡성을 극복하고 목적에 집중
  • 캡슐화 : 맡은 목적 실행 위해 상태와 행동을 하나의 단위로 묶는 자율적 실체 + 데이터 은닉
  • 상속 : 새로운 클래스가 기존의 클래스의 자료와 연산을 이용하게 해주는 것. 중복되는 속성과 기능을 재사용
  • 다형성 : 다양한 형태로 표현이 가능하다는 의미 + 동일 요청에 대해 서로 다른 방식으로 응답할 수 있음
    • Overriding : 상속받은 동일한 메소드 재정의
    • Overloading : 동일한 메소드가 매개변수 타입, 개수 차이에 따라 다르게 동작

JVM, JRE, JDK

  • JVM(Java Virtual Machine) : 자바 가상머신

    • JVM은 자바 소스코드로부터 만들어지는 자바 바이너리 파일(.class)을 실행할 수 있는 런타임 환경을 제공해주는 규격
    • JVM은 플랫폼에 의존적(리눅스의 JVM과 윈도우즈의 JVM은 다름)
    • 단 컴파일된 바이너리 코드는 어떤 JVM에서도 동작시킬 수 있음
      • OS마다 구성이 다르므로 JDK, JRE, JVM은 플랫폼에 의존적이지만 자바 자체는 플랫폼에 독립적임
  • JRE(Java Runtime Enviroment) : 컴파일된 자바 프로그램을 실행시킬 수 있는 자바 환경

    • JRE는 JVM이 자바 프로그램을 동작시킬 때 필요한 라이브러리 파일들과 기타 파일들을 가지고 있음
    • JRE는 JVM의 실행환경을 구현했다고 할 수 있음
    • 자바 프로그램을 실행시키기 위해선 JRE를 반드시 설치해야 함
    • 하지만 자바 프로그래밍 도구는 포함되어있지 않기 때문에 자바 프로그래밍을 하기 위해선 JDK가 필요
  • JDK(Java Development kit) : 자바 프로그래밍시 필요한 컴파일러 등 포함

    • JDK는 개발을 위해 필요한 도구(javac, java등)들을 포함
    • JDK를 설치하면 JRE도 같이 설치됨
    • JDK = JRE + @

자바의 메모리 구조

참조형(Reference Type)의 데이터 타입을 갖는 객체(인스턴스), 배열 등은 Heap 영역에 데이터가 저장된다. 이때 변수(객체, 객체변수, 참조변수)는 Stack 영역의 공간에서 실제 데이터가 저장된 Heap 영역의 참조값(reference value, 해시코드 / 메모리에 저장된 주소를 연결해주는 값)을 new 연산자를 통해 리턴 받는다. 다시 말하면 실제 데이터를 갖고 있는 Heap 영역의 참조 값을 Stack 영역의 객체가 갖고 있다. 이렇게 리턴 받은 참조 값을 갖고 있는 객체를 통해서만 해당 인스턴스를 핸들 할 수 있다.

  • Method Area

    • 프로그램 실행 중 클래스가 사용되면 JVM은 해당 클래스 파일을 읽어서 분석하여 클래스 변수, 메소드 코드 등을 Method Area에 저장
    • 객체 생성 후 메소드를 실행하면 해당 클래스 코드에 대한 정보를 Method Area에 저장.
    • 자바의 모든 로직은 메서드에만 존재 ->메서드의 실행 로직에 대한 바이트 코드가 메모리로 적재되는데 실행 로직이 메모리에 적재 되야 cpu가 fetch할 수 있음. 객체 생성할 시점에 main() 제외한 메서드 바이트코드를 메모리에 적재
    • 코드에서 사용되는 클래스들을 클래스 로더로 읽어 클래스 별로 런타임 상수 풀(runtime constant pool), 필드(field) 데이터, 메소드(method) 데이터, 메소드 코드, 생성자 코드 등을 분류해 저장
  • Heap Area

    • 인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 인스턴스는 모두 이 곳에 생성
    • 인스턴스 변수도 이곳에 저장됨
    • 이 인스턴스를 가리키는 레퍼런스 변수는 stack에 저장
    • 상수 풀(Constant String pool)이란?
      • 만약 이전에 같은 char sequence의 문자열이 이미 상수풀에 있다면 문자열을 힙에서 해제하고 그 상수풀의 레퍼런스를 반환해 고유의 인스턴스를 공유
      • Constant String pool은 논리적으로는 힙에 위치하나 Permanent area(고정 영역)에 생성되어 프로세스 생성부터 종료까지 가비지 콜렉터에 의해 관리되지 않고 쭉 있음
  • Stack Area

    • method 안에 선언시 스택에
    • 각 Thread 는 자신만의 stack 을 가짐
    • 원시타입의 데이터가 값과 함께 할당됨(참조값이 아니라 실제 값)
    • 지역 변수에 스택 자료형을 쓰는 이유?
      • 프로그램은 함수의 호출로써 실행. 함수는 다른 함수를 호출하고, 그 함수는 또 다른 함수를 호출하고, 처리가 완료되면 그 결과를 다시 자신을 호출한 함수에게 반환함. 차곡차곡 메모리에 쌓고, 처리가 끝나면 위에서부터 해당 함수에서 사용한 지역 변수를 메모리에서 해제해 LIFO로 관리
  • 메소드 영역과 힙 영역은 쓰레드 공유하므로 주의필요

  • 자바 메모리 예시: https://javacpro.tistory.com/11

자바 프로그램 실행 과정

  • 자바 컴파일러(Java compiler): 작성한 자바 소스 코드를 JVM이 이해할 수 있는 자바 바이트 코드로 변환
    • 컴파일: 프로그래밍 언어를 Runtime 이전에 기계어로 해석하는 작업 방식
    • 자바 바이트 코드(Java bytecode): JVM이 이해할 수 있는 언어로 변환된 자바 소스 코드(.class)
    • 자바 바이트 코드는 JVM이 설치되어 있으면, 어떤 운영체제에서라도 실행될 수 있습니다.
  • 자바 인터프리터:
    • interpret: Runtime 이후에 Row 단위로 해석하며 프로그램을 구동시키는 방식
    • 프로그래밍 언어를 기계어로 바로 바꾸지않고 중간 단계를 거친 뒤 런타임에 즉시 해석하기 때문에 바로 컴팩트한 패키지 형태로 Binary 파일을 뽑아낼 수 있는 Compile 방식에 비해 낮은 퍼포먼스
    • Bytecode -> BinaryCode로 해석

클래스 변수와 인스턴스 변수

https://itmining.tistory.com/20

public class test {
    int iv; // 인스턴스 변수
    static int cv; // 클래스 변수
    void method() {
        int lv; // 지역 변수 
    }
}


-> 개인적으로 용어가 약간 혼동되는데 여기서의 선언위치란 메모리 위치가 아닌 코드상의 위치이다

  • 인스턴스 변수
    • 인스턴스가 생성될 때 생성->값을 읽어오거나 저장하려면 인스턴스를 먼저 생성해야 함
    • 인스턴스 별로 다른 값을 가질 수 있으므로, 각각의 인스턴스마다 고유의 값을 가져야할 때는 인스턴스 변수로 선언
  • 클래스 변수
    • 인스턴스 변수 + static
    • 클래스 변수는 모든 인스턴스가 공통된 값을 공유하게 됨
    • 한 클래스의 모든 인스턴스들이 공통적인 값을 가져야할 때
    • 클래스가 로딩될 때 생성, 메모리에 딱 한번만 올라감
    • 인스턴스를 생성하지 않고 클래스이름.클래스변수명 으로 접근 가능
    • -> Static 변수와 static 메소드는 Static 메모리 영역에 존재하므로 객체가 생성되기 이전에 이미 할당이 되어 있기 때문
    • static 변수의 초기화
      • primitive type이 static이라면 명시적으로 초기화하지 않으면 default value로 초기화, reference인 경우에는 null로 초기화
      • 객체가 생성될 때
      • 클래스의 static 맴버를 처음 액세스 할 때
    • static method는 상속이 되지 않는다. static 메서드는 클래스가 컴파일 되는 시점에 결정이 되지만 Override에 경우에는 런타임 시점에 사용될 메서드가 결정이 되기 때문. 대신 hiding이라고 override를 하지 않고 같은 이름으로 하는 잔꾀기술이 있는데 되도록 쓰지 않아야함
  • 클래스변수의 초기화시점 : 클래스가 처음 로딩될 때
  • 인스턴스변수의 초기화시점 : 인스턴스가 생성될 때마다 각 인스턴스별로 초기화
  • 지역 변수
    • 메서드 내에서 선언되며 메서드 내에서만 사용 가능
    • 메서드가 실행될 때 메모리를 할당 받으며 메서드가 끝나면 소멸되어 사용할 수 없음

Interface vs Abstract Class

  • 자바8 부터는 인터페이스의 변화
    1. default 키워드를 통해 구현체를 가질 수 있음(일반적인 메소드 구현 가능). 인터페이스가 변경 되면 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제를 해결하기 해 인터페이스에 메소드를 구현해 놓을 수 있도록 함
    2. static 메소드 선언 가능
    • 인터페이스에서 정의한 static메소드는 반드시 인터페이스명.메소드 형식으로 호출해야한다. 인터페이스에 static 메소드를 선언함으로써, 인터페이스를 이용하여 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있게 되었다.
    public interface Calculator {
        public int plus(int i, int j);
        public int multiple(int i, int j);
        
        default int exec(int i, int j){
            return i + j;
        }
        public static int exec2(int i, int j){   //static 메소드 
            return i * j;
        }
    }



    public class MyCalculatorExam {
        public static void main(String[] args){
            Calculator cal = new MyCalculator();
            int value = cal.exec(5, 10);
            System.out.println(value);

           //인터페이스에서 정의한 static메소드는 반드시 인터페이스명.메소드 형식으로 호출해야한다.  
            int value2 = Calculator.exec2(5, 10);  //static메소드 호출 
            System.out.println(value2);
        }
    }
  • 공통점

    1. 자기 자신이 new를 해서 객체를 생성할 수 없으며,
      추상클래스를 extends 받거나, interface를 implements 한 자식만이 객체를 생성할 수 있다.
    2. 상속받은 자식이 구현을 반드시 하도록 해야할 때 사용한다.
    3. 추상 메소드가 있으면 자식은 반드시 다 구현해야 한다.
  • 추상클래스

    • abstract 메소드가 하나라도 존재하는 클래스
    • 구현되어 있는 메소드도 존재할 수 있음 (JAVA8부터는 인터페이스도)
    • 동일한 부모를 가지는 클래스를 묶는 개념으로 상속을 받아서 기능을 확장시키는 것이 목적
    • 관련성이 높은 클래스 간에 코드를 공유하고 싶은 경우
  • 인터페이스

    • 구현해야 할 메소드들의 명세
    • 인터페이스의 경우, default 또는 static 으로 선언되지 않은 모든 메소드는 암묵적으로 abstract
    • 서로 관련성이 없는 클래스들이 인터페이스를 구현하게 되는 경우에 사용한다. 예를 들어, Comparable, Cloneable 인터페이스는 여러 클래스들에서 구현되는데, 구현클래스들 간에 관련성이 없는 경우가 대부분
    • 특정 데이터 타입의 행동을 명시하고 싶은데, 어디서 그 행동이 구현되는지는 신경쓰지 않는 경우.
  • 차이점

    • 인터페이스에서 모든 변수는 기본적으로 public static final 이며, 모든 메소드는 public abstract 인 반면
    • 추상클래스에서는 static 이나 final 이 아닌 필드를 지정할 수 있고, public, protected, private 메소드를 가질 수 있다.
      인터페이스를 구현하는 어떤 클래스는, 다른 여러개의 인터페이스들을 함께 구현할 수 있다. 추상클래스는 상속을 통해 구현되는데, 자바에서는 다중상속을 지원하지 않으므로 추상클래스를 상속받은 서브클래스는 다른 클래스를 상속받을 수 없다.

예시: HashMap

public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
  • AbstractMap 의 서브클래스인 HashMap, TreeMap, ConcurrentHashMap 에서는 AbstractMap 에 정의되어 있는 get, put, isEmpty, containsKey, containsValue 등의 메소드를 공유한다.

  • 또한 HashMap은 Serializable, Cloneable, Map<K,V> 세 개의 인터페이스를 구현한 클래스이다. 위 인터페이스를 통해 HashMap 의 인스턴스는 복제가능하며, 직렬화(byte stream 으로 컨버팅)가 가능하며, map 으로써의 기능을 가진다는 것을 추론할 수 있다.

원시형 데이터, 참조형 데이터

  • 원시형 데이터(Primitive)
    • 반드시 사용하기 전에 선언되어야 함
    • OS에 따라 자료형의 길이가 변하지 않음
    • 비객체 타입이므로 null 값을 가질 수 없음
  • 참조형 데이터(Reference)
    • 클래스에 정의된 생성자를 사용하여 만들어지며 디폴트 값은 null
    • 객체를 참조하는데 사용
  • 저장 위치

Wrapper Class

  • 박싱(boxing): 기본형을 참조형으로 변환하는 것

  • 언박싱(unboxing): 참조형을 기본형으로 바꾸는 것

  • 래퍼 클래스가 필요할 때

    1. 매개변수로 객체가 요구 될때
    2. 기본형 값이 아닌 객체로 저장해야 할 때
    3. 객체간의 비교가 필요할 때
public final class Integer extends Number implements Comparable {
      ...
      private int value;
      ...
 } 
  • 이런식으로 Wrapper Class안에 값이 들어있음
  • Wrapper Class는 unboxing을 하지 않으면 산술 연산 불가능
  • null값 처리 가능
  • wrapper 클래스들은 모드 equals()가 오버라이딩되어 있어 비교를 해도 주소값이 아닌 객체가 가지고 있는 값을 비교
  • MAX_VALUE, MIN_VALUE, SIZE, TYPE 등 static 멤버 공통으로 가짐

직렬화와 역직렬화

  • 직렬화

    • 자바 시스템 간의 데이터 교환을 위해서 존재
    • 객체를 스트림을 통해 입출력하기 위해 바이트 배렬로 변환하는 것. 역직렬화는 반대
  • 왜 CSV, JSON 두고 굳이?

    • 복잡한 데이터 구조의 클래스의 객체라도 직렬화 기본 조건만 지키면 큰 작업 없이 바로 직렬화 가능
      자바에서 입출력에 사용되는 것은 스트림이라는 데이터 통로를 통해 이동함
    • JVM의 메모리에서만 상주되어있는 객체 데이터를 그대로 영속화(Persistence)가 필요할 때 사용
  • 예시: 서블릿 세션

    • 단순히 세션을 서블릿 메모리 위에서 운용한다면 직렬화를 필요로 하지 않지만, 파일로 저장하거나 세션 클러스터링, DB를 저장하는 옵션 등을 선택하게 되면 세션 자체가 직렬화가 되어 저장되어 전달
  • serialVersionUID를 선언해야 하는 이유

    • JVM은 직렬화와 역직렬화를 하는 시점의 클래스에 대한 버전 번호를 부여
    • SUID가 선언되어 있지 않으면 클래스의 기본 해쉬값을 사용
    • 클래스의 멤버 변수 하나만 추가되어도 java.io.InvalidClassException 예외 발생
    • serialVersionUID 를 직접 기술하지 않아도 내부 적으로 serialVersionUID 정보가 추가됨
    • 직접 serialVersionUID 값을 관리해주어야 클래스 변경 시 혼란 X
    • serialVersionUID값을 저장할 때 클래스 버전이 맞는지 확인하기 위한 용도

제네릭(Generic)

  • 클래스를 선언할 때 타입을 결정하지 않고 객체를 생성할 때 유동적인 타입으로 재사용하기 위해

  • 형변환 필요X, 타입 에러 발생할 확률 감소

  • 타입 추론은 메서드를 호출하는 코드에서 타입인자가 정의한대로 제대로 쓰였는지 살펴보는 컴파일러의 능력

    • Something< T > 의 위치에 지정한 타입이 대체되어서 들어가는 것 처럼 컴파일러가 인식함. Raw 타입 으로 사용하는데 컴파일러에 의해 필요한 곳에 형변환 코드가 추가됨
    • int var3 = (Integer)var1.get(1); 이런식으로 자동으로 형변환 추가됨
  • 제너릭을 사용하지 않으면?

    • Object 타입으로 선언 시 String, Integer 등을 모두 인자로 줄 수 있고 컴파일 시점에서는 어떤 오류도 발생하지 않음
    • 어떤 타입으로 형변환 할 수 있는지 조차 모호한 경우도 많기 때문에 잠재적인 오류를 가짐
  • 컬렉션(collection) 클래스에서 제네릭을 사용하는 이유
    • 컬렉션 클래스에 저장하는 인스턴스 타입을 제한하여 런타임에 발생할 수 있는 잠재적인 모든 예외를 컴파일타임에 잡아낼 수 있도록 도와줌

자바 Reflection API

  • 클래스의 구조를 개발자가 확인할 수 있고, 값을 가져오거나 메소드를 호출하는데 사용
  • JVM에서 실행되는 애플리케이션의 런타임 동작을 검사하거나 수정할 수 있는 기능이 필요한 프로그램
  • 구체적인 클래스 타입을 알지 못해도 클래스의 타입, 메소드, 변수를 접근할 수 있게 해주는 API
  • 예시: 스프링 프레임워크, 대표적 ORM 기술인 하이버네이트, jackson라이브러리 등
    • 스프링에서는 런타임 시에 개발자가 등록한 빈을 애플리케이션에서 가져와 사용할 수 있게 되는 것
  • .getClass, Class.forName("ko.maeng.reflection.ReflectionApplication");

String과 StringBuffer의 차이

  • String은 immutable(불변)하고 StringBuffer, StringBuilder는 mutable(가변)
  • String (literal)
  • 리터럴로 생성하면 String Pool에 생성, 문자열 값은 절대 변하지 않음

  • '+' 연산이나 .concat() 메소드를 이용해서 문자열 값에 변화를 줘도 메모리 공간 내의 값이 변하는 것이 아니라, String Pool에 메모리를 할당받아 새로운 String 클래스 객체를 만듬

  • String 클래스가 적절한 경우

    • 문자열 연산이 적고 자주 참조하는 경우(멀티 쓰레드 환경에서 신경쓸일X)
  • StringBuffer, StringBuilder

  • .append() 등을 통해 동일 객체내에서 문자열 변경 가능

  • StringBuffer/StringBuilder 클래스가 적절한 경우
    • 문자열의 수정이 빈번한 경우
  • StringBuffer VS StringBuilder
    • StringBuffer는 동기화 키워드를 지원, thread-safe
    • StringBuilder는 동기화 키워드 지원X, thread-unsafe 하지만 단일쓰레드에서의 성능은 StringBuffer보다 뛰어남

Jar(Java Archive) vs War(Web Application Archive) vs Ear(Enterprise Archive)

  • 공통점

    • JAVA의 jar tool을 이용해 생성된 압축(아카이브) 파일
    • 압축의 해제없이 JDK에서 각 파일들을 접근하여 사용할 수 있도록 설계
    • 관련 파일(리소스, 속성파일 등)들을 패키징
    • 각각 다른 목적을 가지고 사용
  • Jar

    • Class, 라이브러리 등 자바 프로젝트를 압축한 파일
    • 원하는 구조로 구성 가능, JDK의 JRE만 가지고도 실행 가능
  • War

    • Servlet, JSP Container에 배치할 수 있는 웹 어플리케이션 압축 포맷
    • Servlet Context 관련 파일들로 패키징
    • 웹 응용 프로그램을 위한 포맷이므로 웹 관련 자원만 포함
    • WEB-INF, META-INF 디렉토리로 사전 정의 된 구조 사용
    • 실행하려면 Tomcat같은 웹 서버 혹은 WAS가 필요
    • war도 java -jar을 이용해 생성함
  • Ear

    • 실행하려면 완전한 JAVA EE가 필요

참고자료

https://itmining.tistory.com/20
https://goodgid.github.io/Java-JDK-JRE/
https://ktko.tistory.com/entry/%EA%B0%9C%EB%B0%9C%EC%9E%90-%EB%A9%B4%EC%A0%91-%EC%A7%88%EB%AC%B8%EC%9E%90%EB%B0%94-%EC%8A%A4%ED%94%84%EB%A7%81
https://woowabros.github.io/experience/2017/10/17/java-serialize2.html
https://yaboong.github.io/java/2019/01/19/java-generics-1/
http://tcpschool.com/java/java_intro_programming
https://medium.com/msolo021015/%EC%9E%90%EB%B0%94-reflection%EC%9D%B4%EB%9E%80-ee71caf7eec5
https://jusungpark.tistory.com/17
https://ifuwanna.tistory.com/221
https://jeong-pro.tistory.com/85
https://yaboong.github.io/java/2018/09/25/interface-vs-abstract-in-java8/
https://programmers.co.kr/learn/courses/5/lessons/241

0개의 댓글