Java
1. Java의 특징
- Java는 객체지향 프로그래밍 언어이다.
- 기본 자료형을 제외한 모든 요소들이 객체로 표현되고, 객체 지향 개념의 특징인 캡슐화, 상속, 다형성이
잘 적용된 언어이다.
1) 장점
- JVM(자바 가상 머신)위에서 동작하기 때문에 운영체제에 독립적이다.
- GabageCollector를 통한 자동적인 메모리 관리가 가능하다.
가비지 컬렉션 (Garbage Collection)
- JVM의 메모리 관리 기법중 하나이다.
- 시스템에서 동적으로 할당됐던 메모리 영역 중에서 필요없어진 메모리 영역을 회수하여 메모리 관리해주는 기법
가비지 컬렉션 과정
- JVM이 어플리케이션의 실행을 잠깐 멈춘다.
- GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업을 중단 후 (Stop The World 과정)
- 사용하지 않는 메모리를 제거 (Mark and Sweep 과정)후 작업이 재개
- GC의 작업은 Young 영역에 대한 Minor GC와 Old 영역에 대한 Major GC로 구분된다.
2) 단점
- JVM 위에서 동작하기 때문에 실행 속도가 상대적으로 느리다.
- 다중 상속이나 타입에 엄격하며, 제약이 많다.
2. JVM의 역할
- JVM은 스택 기반으로 동작한다.
- Java Byte Code를 OS에 맞게 해석 해주는 역할을 한다.
- 가비지 컬렉션을 통해 자동적인 메모리 관리를 해준다.
3. Java의 컴파일 과정
- 개발자가
.java
파일을 생성한다.
- build를 한다.
- java compiler의 javac의 명령어를 통해 바이트코드
.class
를 생성한다.
- Class Loader를 통해 JVM 메모리 내로 로드한다.
- 실행엔진을 통해 컴퓨터가 읽을 수 있는 기계어로 해석된다. (각 OS에 맞는 기계어)
4. Java에서 제공하는 원시 타입
1) 정수형
- byte : 1 byte
- Short : 2 byte
- int : 4 byte
- Long : 8 byte
2) 실수형
- float : 4 byte
- double : 8 byte
3) 문자형
3) 논리형
5. Overriding(오버라이딩) vs Overloading(오버로딩)
1) Overriding
- 상위 클래스에 있는 메소드를 하위 클래스에서 재정의 하는 것
2) Overloading
- 매개변수의 개수나 타입을 다르게 하여 같은 이름의 메소드를 여러 개 정의 하는 것
6. 객체지향 프로그래밍 (OOP)란?
- 역할과 책임으로 나눈다.
- 모든 데이터를 객체취급하여, 처리요청을 받은 객체는 객체 그안의 기능을 사용해 요청에 응답한다.
- 특징으로는 캡슐화, 다형성, 상속, 추상화 등이 있다.
- 모듈 재사용으로 확장 및 유지보수가 용이하다.
7. try - with - resources
- try-with-resources 는 try-catch-finally의 문제점을 보완하기 위해 나온 개념
- try(…)안에 자원 객체를 전달하면, try 블록이 끝나고 자동으로 자원 해제 해주는 기능
- 따로 finally구문이나 모든 catch 구문에 종료 처리를 하지 않아도 되는 장점이 있다.
8. 불변 객체
- 불변 객체는 객체 생성 이후 내부의 상태가 변하지 않은 객체를 말합니다.
- Java에서는 필드가 원시 타입인 경우 fianl를 사용해 불변 객체를 만든다.
- 참조 타입일 경우엔 추가적인 작업 필요
9. 추상 클래스와 인터페이스의 차이
- 추상 클래스는 클래스 내 추상 메소드가 하나 이상 포함되거나 abstract로 정의됨
- 인터페이스는 모든 메소드가 추상 메소드로만 이루어져 있음
1) 공통점
- new 연산자로 인스턴스 생성 불가능
- 사용하기 위해서 하위 클래스에서 확장/구현 해야한다.
2) 차이점
- 인터페이스는 그 인터페이스를 구현하는 모든 클래스에 대해 특정한 메소드가 반드시 존재해야 함.
- 추상클래스는 상속받는 클래스들의 공통적인 로직을 추상화 시키고, 기능확장을 할 수 있음
- 추상 클래스는 다중 상속 x , 인터페이스는 다중 상속 o
10. 싱글톤 패턴
- 싱글톤 패턴은 단 하나의 인스턴스를 생성해 사용하는 디자인 패턴
- 인스턴스가 1개만 존재해야 한다는것을 보장하고 싶은 경우 사용
- 동일한 인스턴스를 자주 생성해야 하는 경우에 주로 사용 (메모리 방지 낭비)
1) 대표적인 예시
- Spring Bean
- 스프링 빈 등록 방식은 기본적으로 싱글톤 스코프이고, 스프링 컨테이너는 모든 빈들을 싱글톤으로 관리
- 새로운 객체 -> @Scope(“prototype)
11. 객체지향 설계원칙
1) SRP - 단일 책임 원칙
2) OCP - 개방-폐쇄 원칙
- 확장에는 열려있고, 수정에는 닫혀있어야 한다.
3) LCP - 리스코프 치환 원칙
- 상위 타입은 항상 하위 타입으로 대체 가능해야 한다.
4) ISP - 인터페이스 분리 원칙
5) DIP - 의존관계 역전 원칙
- 구체적인 클래스보다 상위 클래스, 인터페이스, 추상클래스와 같이 변하지 않을 가능성이 높은 클래스와
관계를 맺어야한다. (DI)
12. 자바의 메모리 영역
- 자바의 메모리 공간은 크게 Method 영역, Stack 영역, Heap 영역으로 구분되고, 데이터 타입에 따라
할당된다.
1) 메소드 영역
- 전역변수와 static 변수를 저장하며, Method영역은 프로그램 시작부터 종료까지 메모리에 남아있다.
2) 스택 영역
- 지역변수와 매개변수 데이터 값이 저장되는 공간이다.
- 메소드가 호출될때 메모리에 할당되고 종료되면 메모리가 해체된다.
- LIFO (Last In First Out) 구조를 갖고 변수에 새로운 데이터가 할당되면 이전 데이터는 지워진다.
3) 힙 영역
- new 키워드로 생성되는 객체 (인스턴스), 배열 등이 Heap 영역에 저장되며, 가비지 컬렉션에 의해
메모리가 관리되어 진다.
4) 각 메모리 영역이 할당되는 시점
- Method 영역 : JVM이 동작해서 클래스가 로딩 될때 생성
- Stack 영역 : 런타임시 할당 ( 컴파일 타임 이후 실행되는 때)
- Heap 영역 : 컴파일 타임 시 할당 (소스코드가 기계어로 변환되어 실행가능한 프로그램이 되는 과정)
13. 클래스와 객체
- 클래스는 객체를 만들어내기 위한 설계도 혹은 틀
- 객체를 생성하는데 사용
- 객체는 설계도(클래스)를 기반으로 생성되며, 자신의 고유 이름과 상태, 행동을 갖는다.
- 객체는 메모리가 할당되어 실제로 활용되는 실체는 ‘인스턴스’라고 부름
14. 생성자 (Constructor)
- 생성자는 클래스와 같은 이름의 메소드로, 객체가 생성될 때 호출되는 메소드이다.
- 명시적으로 생성자를 만들지 않아도 default로 만들어진다.
- 생성자는 파라미터를 다르게하여 오버로딩 할 수 있다.
15. Wrapper Class, Boxing, UnBoxing
- 기본 자료형 (Primitive data type)에 대한 객체 표현을 Wrapper Class라고 한다.
- 기본 자료형 -> Wrapper class로 변환 하는 것을 Boxing이라 한다.
- Wrapper class -> 기본 자료형으로 변환하는 것을 UnBoxing이라고 한다.
16. Synchronized
- 여러 개의 쓰레드가 한개의 자원을 사용하고자 할때, 현재 데이터를 사용하고 있는 쓰레드를 제외하고
나머지 쓰레드들은 데이터에 접근할 수 없게 막는 개념
- 데이터의 thread-safe를 하기 위해 자바에서 Synchronized 키워드를 제공해 멀티 쓰레드 환경에서
쓰레드간 동기화를 시켜 데이터의 thread - safe를 보장
- Synchronized는 변수와 메소드에 사용해서 동기화 할 수 있다.
- Synchronized 키워드를 남발하게 되면 오히려 프로그램 성능저하를 일으킬수 있다.
17. new String()과 리터럴(““)의 차이
- new String()은 new 키워드로 새로운 객체를 생성하기 때문에 Heap 메모리 영역에 저장
- "”는 Heap 안에 있는 String Constant Pool 영역에 저장된다.
18. String, StringBuffer, StringBuilder 차이
1) String
2) StringBuffer
- 가변의 속성을 가진다.
- 동기화를 지원하여 멀티 쓰레드 환경에서 주로 사용한다.
3) StringBuilder
- 동기화를 지원하지 않아 싱글 쓰레드 환경에서 주로 사용한다.
19. String 객체가 불변인 이유
1) 캐싱 기능에 의한 메모리 절약과 속도 향상
- Java에서 String 객체들은 Heap의 String Pool 이라는 공간에 저장된다.
- 참조하려는 문자열이 String Pool에 존재하는 경우 새로 생성하지 않고 Pool에 있는객체를 사용
- 특정 문자열 값을 재사용하는 빈도가 높을 수록 상당한 성능 향샹을 기대할 수 있다.
2) thread - safe
- String 객체는 불변이기 때문에 여러 쓰레드에서 동시에 특정 String 객체를 참조하더라도 안전
3) 보안 기능
- 중요한 데이터를 문자열로 다루는 경우 강제로 해당 참조에 대한 문자열 값을 바꾸는 것이 불가능
20. 접근 제한자 (Access Modifer)
- 변수 또는 메소드의 접근 범위를 설정해주기 위해서 사용하는 Java의 예약어
- Public : 접근 제한 x (같은 프로젝트 내 어디서든 사용 가능)
- protected : 해당 패키지내, 다른 패키지에서 상속받아 자손 클래스에서 접근 가능
- (default) : 해당 패키지 내에서만 접근 가능
- private : 해당 클래스에서만 접근 가능
21. 클래스 멤버 변수 초기화 순서
- static 변수 선언 부 : 클래스가 로드 될때 변수가 제일 먼저 초기화 된다.
- 필드 변수 선언부 : 객체가 생성될 때 생성자 block 보다 앞서 초기화 된다.
- 생성자 block : 객체가 생성될 때 JVM이 내부적으로 locking(thread-safe 영역)
22. static
- static 키워드를 사용한 변수나 메소드는 클래스가 메모리에 올라갈 때 자동으로 생성된다.
- 클래스 로딩이 끝나면 바로 사용할수 있다. 즉, 인스턴스 (객체) 생성 없이 바로 사용 가능
- 모든 객체가 메모리를 공유한다는 특징이 있다.
- GC 관리 영역 밖에 있기 때문에 프로그램이 종료될때까지 메모리에 값이 유지된채로 존재
1) 사용하는 이유
- static은 자주 변하지 않는 값이나 공통으로 사용되는 값 같은 공용자원에 대한 접근에 있어서 매번
메모리를 로딩하거나 값을 읽어들이는 것보다 ‘전역변수’같은 개념을 통해 접근하는것이 비용도
줄이고, 효율을 높일 수 있다.
- 인스턴스 생성 없이 바로 사용가능하기 때문에 프로그램 내에서 공통으로 사용되는 데이터들을 관리할 때
이용
23. Inner Class 의 장점
- 내부 클래스에서 외부 클래스의 멤버에 손쉽게 접근할 수 있다.
- 서로 관련 있는 클래스를 논리적으로 묶어서 표현함으로써, 코드의 캡슐화를 증가시킨다.
- 외부에서는 내부 클래스에 접근할 수 없으므로, 코드의 복잡성을 줄일 수 있다.
24. 리플렉션 (Reflection)
- 리플렉션이란 구체적인 클래스 타입을 알지 못해도 그 클래스의 메소드, 타입, 변수들에
접근할 수 있도록 해주는 자바 API이다.
1) 어떤 경우에 사용할까
- 코드를 작성할 시점에 어떤 타입의 클래스를 사용할지 모르지만, 런타임 시점에 지금 실행되고 있는
클래스를 가져와서 실행해야 하는 경우 사용된다.
- 프레임워크나 IDE에서 이런 동적인 바인딩을 제공한다.
- intelliJ의 자동완성 기능, 스프링의 어노테이션이 리플렉션을 이용한 기능
25. Error와 Exception의 차이
1) Error
- 실행 중 일어날 수 있는 치명적인 오류를 말한다.
- 컴파일 시점에 체크할 수 없고, 오류가 발생하면 프로그램은 비정상 종료 된다.
- 예측 불가능한 UncheckedException에 속한다.
2) Exception
- Error보다 비교적 경미한 오류이며, try-catch를 이용해 프로그램의 비정상 종료를 막을 수 있다.
26. CheckedException과 UnCheckedException의 차이
1) CheckedException
- 실행하기 전에 예측 가능한 예외를 말하고, 반드시 예외 처리를 해야한다.
- 대표적 ex) IOException, ClassNotFoundException 등
2) UnCheckedException
- 실행하고 난 후에 알수 있는 예외를 말하고, 따로 예외처리를 하지 않아도 된다.
- 대표적 ex) NullPointerException, ArrayIndexOutOfBoundException 등
- RuntimeException은 UnCheckedException을 상속한 클래스이다.
27. 컬렉션 프레임워크
- 다수의 데이터를 쉽고 효과적으로 관리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미
- 자바 컬렉션에는 List, Set, Map 인터페이스를 기준으로 여러 구현체가 존재한다.
- 이에 더해 Stack, Queue 인터페이스도 존재한다.
1) List
- 순서가 있는 데이터의 집합
- 데이터 중복을 허용
- 대표적인 구현체로는 ArrayList가 있다. (Vector를 개선한 것)
- LinkedList, Stack, Queue, Vector, ArrayList
—
- 직접 new 키워드로 사용할 수 있으며, Queue 인터페이스는 LinkedList에 new 키워드를 적용해
사용할 수 있다.
2) Set
- 순서가 없는 데이터의 집합
- 데이터 중복을 허용 X
- 대표적인 구현체로 HashSet이 있고, 순서를 보장하기 위해서는 LinkedHashSet을 사용
- (Map의 key-value 구조에서 key대신 value가 들어가 value를 key로하는 자료구조)
- HashSet, LinkedHashSet, TreeSet
3) Map
- 키와 같이 한쌍으로 이뤄져 있다.
- 키를 기준으로 중복 허용 X
- 순서가 없다.
- key의 순서를 보장하기 위해서는 LinkedHashMap을 사용
- HashMap, TreeMap, HashTable, Properties
28. Set과 Map의 타입이 Wrapper Class가 아닌 Object를 받을때 중복검사
- hasCode() 메소드를 오버라이딩하여 리턴된 해시코드 값이 같은지를 보고 해시코드 값이 다르다면
다른 객체로 판단하고, 같으면 equals()메소드를 오버라이딩하여 다시 비교
- 이 두개가 모두 맞으면 중복 객체
29. Vector와 List의 차이
- 벡터는 데이터 삽입시 원소를 밀어내지만 리스트는 노드를 연결만 하기 때문에, 삽입 삭제 부분에서
리스트가 시간복잡도의 우위를 가진다.
- 벡터는 랜덤부분접근이 가능하지만 리스트는 더블링크드리스트(노드가 양쪽으로 연결)로 되어있기 때문에
랜덤 접근이 되지 않는다. 검색적인 측면에서는 벡터가 우위에 있다.
- 벡터는 리스트와 달리 항상 동기화되는 장점이자 단점을 가지고 있다.
- 멀티스레드 한경에서 안전하게 추가하고 삭제할 수 있지만, 단일쓰레드 환경에서도 동기화 하기 때문에
List보다 성능이 떨어진다.
30. 제너릭
- 제너릭은 데이터의 타입을 하나로 지정하지 않고, 사용할 때마다 범용적이고 포괄적으로 지정한다는 의미
- 제너릭 타입을 사용함으로써 잘못된 타입이 사용될수 있는 문제를 컴파일 과정에서 제거할 수 있어
에러를 사전에 방지할 수 있다.
31. final, finally, finalize의 차이
1) final
- final은 클래스, 메소드, 변수, 인자를 선언할때 사용할수 있다.
- 한번만 할당하고 싶을때 사용한다.
- fianl 변수는 한번 초기화 하면 그 이후에 변경할 수 없다.
- fianl 메소드는 다른 클래스가 이 클래스를 상속할 때 메소드 오버라이딩을 금지
- fianl 클래스는 다른 클래스에서 이 클래스를 상속할 수 없다.
2) finally
- try - catch와 함께 사용된다.
- try - catch가 종료될 때 finally block이 항상 수행되기 때문에 마무리 해줘야 하는 작업이
존재할 경우에 해당하는 코드를 작성해주는 코드 블록이다.
3) finalize
- Object 클래스에 정의되어 있는 메소드이다.
- GC에 의해 호출되는 메소드로 호출되서는 안되는 메소드이다.
- GC가 발생하는 시점이 불분명하기 때문에 해당 메소드가 실행된다는 보장이 없고, fianlize() 메소드가
오버라이딩 되어 있으면 GC가 이루어질때 바로 Garbage Collecting되지 않는다.
- GC가 지연되면서 OOME(Out of Memory Exception)이 발생할 수 있기 때문에 finalize()
메소드를 오버라이딩하여 구현하는 것을 권장하지 않고 있습니다.
32. 직렬화 (Serialize)
- 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 시스템에서도 사용할 수 있도록 바이트(byte)형태로
데이터 변환하는 기술
- 반대로 바이트 형태의 데이터를 다시 객체로 변환하는 과정을 ‘역직렬화’라고 한다.
- JVM의 메모리에 상주(힙 or 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술
33. SerialVersionUID를 선언해야하는 이유
- JVM은 직렬화와 역직렬화를 하는 시점의 클래스에 대한 버전 번호를 부여한다.
- 만약 그시점에 클래스의 정의가 바뀌어 있다면 새로운 버전 번호를 할당하게 된다.
- 그래서 역직렬화할 때의 버전 번호와 역직렬화 할때의 버전 번호가 다르면 역직렬화가 불가능 하게
될 수 있기 때문에 이런 문제를 해결하기 위해 사용한다.
- 만약, 직렬화할 때 사용한 SerialVersionUID의 값과 역직렬화 하기 위해 사용했던 SVUID가
다르다면 InvalidCalssException이 발생할 수 있다.
출처 : 슬기로운 개발생활
댓글남기기