Java

Java

∘ 재사용성과 유지보수가 좋다. (캡슐화, 상속, 다형성, 추상화)

∘ OS에 독립적이다. (JVM)

∘ 자동 메모리 관리 (GC)

∘ 보안성이 뛰어나다.

∘ 멀티스레드 & 동적 로딩 지원

[ Object-Oriented Programming : OOP ]

[ 객체지향 프로그래밍 ]

∘ 데이터를 추상화시켜 상태(변수)와 행위(함수)를 가진 객체를 만들고 객체간 상호작용을 통해 로직을 구성

∘ 여러 개의 독립된 단위(객체)들의 모임으로 파악하여 객체들이 메시지를 주고받고, 데이터를 처리(협력)

∘ 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프 트웨어 개발에 많이 사용

∘ 장점

ⅰ. 코드의 재사용성이 높다.

⇨ 만들어진 클래스를 가져와 사용할 수 있고 상속을 통해 확장이 가능하다.

ⅱ. 유지보수가 쉽다.

⇨ 수정해야 할 부분이 클래스 내부에 변수나 메서드로 존재하기에 해당 부분만 수정하면 된다.

ⅲ. 대형 프로젝트에 적합하다.

⇨ 클래스 단위로 모듈화하여 개발이 가능하다.

∘ 단점

ⅰ. 처리속도가 느리다.

ⅱ. 객체가 많으면 용량이 커진다.

ⅲ. 설계시 많은 노력과 시간이 필요하다.

추상화

∘ 인터페이스로 클래스들의 공통 특성을 묶어 표현하는 것

∘ 불필요한 정보는 숨기고 필요한 정보만을 표현할 수 있다.

캡슐화(정보 은닉)

∘ 속성(멤버변수)과 기능(메서드)을 캡슐(클래스)에 넣어 모으고 분류

∘ 장점 : 재활용 & 정보은닉

상속

∘ 자식 클래스가 부모 클래스의 특성과 기능을 물려받아 사용 및 수정

∘ 코드 수정 & 클래스의 재사용 용이

다형성

∘ 오버라이딩, 오버로딩 가능

∘ 역할 & 구현으로 구분 ⇨ 단순해지고, 유연해지며 변경도 편리

∘ 유연하고 변경 용이 & 확장 가능한 설계 가능

[ 객체지향 설계 원칙 SOLID ]

1. SRP 단일 책임 원칙 [ Single Responsibility Principle ]

• 한 클래스는 하나의 책임만 가져야 한다.

• 책임은 상황에 따라 다를 수 있다.

• 중요한 기준은 변경 : 변경이 있을 때 파급 효과가 적으면 SRP를 잘 따른것

ex) UI 변경, 객체의 생성과 사용을 분리

2. OCP 개방-폐쇄 원칙 [ Open/Closed Principle ]

• 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다

• 다형성을 활용 : 인터페이스를 구현한 새로운 클래스에 새로운 기능을 구현

• 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요

3. LSP 리스코프 치환 원칙 [ Liskov Substitution Principle ]

• 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.

• 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것

• 다형성을 지원하기 위한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요

ex) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능

뒤로 가게 구현하면 LSP 위반, 느리더라도 앞으로 가야함

4. ISP 인터페이스 분리 원칙 [ Interface Segregation Principle ]

• 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다

• Car 인터페이스 -> 운전, 정비 인터페이스로 분리

• User 클라이언트 -> 운전자, 정비사 클라이언트로 분리

• 분리하면 임의의 인터페이스 자체가 변해도 특정 클라이언트에 영향을 주지 않음

• 인터페이스가 명확해지고, 대체 가능성이 높아진다.

5. DIP 의존관계 역전 원칙 [ Dependency Inversion Principle ]

• 추상화에 의존해야지, 구체화에 의존하면 안된다.

⇨ 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻

• 의존성 주입(DI)은 이 원칙을 따르는 방법 중 하나

• 클라이언트가 인터페이스에 의존해야 유연하게 구현체 변경 가능

[ JVM : Java Virtual Machine ]

∘ Java Byte Code를 OS에 맞게 해석하는 역할

∘ 이후 실행과정 속 필요에 따라 스레드 동기화, GC와 같은 메모리 관리작업 수행

∘ 어떤 기기상에서 실행되고 있는 프로세스에 대한 자원을 대표하고 통제하는 서버

∘ 기능

① 자바 프로그램이 어느 기기나 OS 상에서도 실행되도록 함

② 프로그램 메모리를 관리&최적화

∘ 구성

① Class Loader

∘ Runtime 시점에 클래스를 로딩

∘ 클래스의 인스턴스 생성시 메모리에 인스턴스 로드

② Runtime Data Areas ( JVM Memory )

∘ JVM이 프로그램을 수행하기 위해 OS로부터 할당받은 메모리 공간

ⅰ. PC Register ⇨ Thread별로 현재 수행중인 JVM의 주소를 지니다.

ⅱ. JVM Stack ⇨ Thread별로 변수 / 메서드 저장

ⅲ. Native Method Stack⇨ 실제 실행할 수 있는 기계어로 작성된, 프로그램을 실행시키는 영역

ⅳ. Method ⇨ JVM이 시작할 때 생성되어 정적변수 / 메서드 코드 등을 보관

ⅴ. Heap ⇨ 런타임시 동적할당되는 데이터 저장

③ Excution Engine

∘ Class Loader에 의해 JVM 내의 Runtime Data Areas에 배치된 Byte Code를 실행하는 영역

[ GC : Garbage Collection ]

∘ 특정 기능 수행이 완료되어 더이상 필요없는 객체를 효과적으로 처리(제거)하는 작업

∘ 자바에서는 메모리를 GC를 통하여 관리하기 때문에, 개발자가 메모리를 처리하기 위한 로직을 만들 필요가 없다.

∘ 자바 메모리 영역에서 Heap 영역을 관리

∘ OOM Error : GC를 해도 더 이상 사용가능한 메모리 영역이 없는데 메모리를 할당하고자 할 때 발생하는 오류

∘ 영역

① Young : 생성된지 얼마 안된 객체들이 저장되는 장소, Minor GC

② Old : 오랫동안 사용중인 객체들이 저장되는 장소, Full GC

③ MetaSpace(Perm) : 클래스 & 메타 데이터가 저장되는 영역

∘ Garbage Collection : Minor GC, Full GC

∘ Garbage Collector

① Serial Collector : Minor GC와 Full GC가 하나의 스레드에서 이루어지는 알고리즘

② Parallel : Serial Collector를 병렬화한 알고리즘. 멀티CPU에서 성능이 좋다.

③ Concurrent Mark Sweep(CMS) : Stop the World 처리시간을 최소화하는데 초점을 맞춘 방식

④ Garbage-First (G1) : 대용량 메모리가 있는 멀티 프로세서 시스템용

※ STW (Stop The World)

∘ GC를 실행하기위해 JVM이 애플리케이션 실행을 멈추는 것

∘ GC 튜닝이란 STW 시간을 줄이는 것이다.

[ Java 컴파일 과정 ]

① 개발자가 자바 소스코드(.java) 작성

② 자바 컴파일러가 소스파일(.java)을 컴파일 ⇨ 바이트코드(.class) 파일 생성

바이트 코드 : 각 명령어가 1바이트 크기의 명령코드와 추가 피연산자로 이루어짐

③ 컴파일된 바이트코드를 JVM 클래스로더에게 전달

④ 클래스로더는 동적로딩을 통해 클래스들을 로딩&링크하여 JVM 메모리 (런타임 데이터 영역) 에 올린다.

⑤ 실행 엔진이 JVM 메모리에 올라온 바이트코드들을 명령어 단위로 하나씩 가져와 실행

5-1. 인터프리터 : 바이트코드 명령어를 하나씩 읽어서 해석하고 실행 ( 하나하나는 빠르지만 전체적으로 느림 )

5-2. JIT Compiler : 바이트코드 전체를 컴파일하여 바이너리코드로 변경하고 직접 실행시키는 방식 ( 빠르다. )

[ Java 메모리 구조 ]

① Class ( Method )

∘ 클래스, 클래스 변수(static Variable), 메서드

② Stack

∘ 메소드 호출 정보(스택프레임)

∘ 메소드 호출시 관계되는 멤버변수 & 지역변수

∘ 스레드마다 할당

∘ 메소드 호출이 완료되면 소멸

∘ 높은주소 → 낮은주소 순으로 할당

③ Heap

∘ 멤버 변수, new 키워드를 통해 생성된 인스턴스

∘ 낮은주소 → 높은주소 순으로 할당

[ 변수 ]

Class Variable { static int classValue; // 클래스 변수 int instanceValue; // 인스턴스 변수 void method() { int localValue; // 지역 변수 } }

클래스 변수

∘ static 키워드가 붙은 변수

∘ 해당 클래스의 모든 인스턴스가 공통된 값을 공유하게 된다.

따라서 한 클래스의 모든 인스턴스가 공통적인 값을 가져야할 때, 클래스 변수로 선언한다.

∘ 클래스가 로딩될때 생성되어 종료될때까지 유지, public을 붙이면 전역변수가 된다.

∘ 인스턴스 생성 없이 접근할 수 있으므로 클래스명.변수명 을 통해 접근할 수 있다.

∘ Method Area

인스턴스 변수

∘ 인스턴스가 생성될 때 생성

따라서 인스턴스 변수를 사용하기 전에 먼저 객체를 생성해야 한다.

∘ 인스턴스 변수는 독립적인 저장공간을 가지므로 인스턴스 별로 다른 값을 가질 수 있다.

∘ Heap Area

지역 변수

∘ 메소드 내에 선언되며 메소드 내에서만 사용할 수 있는 변수이다.

∘ 메소드가 실행될 때, 메모리를 할당받으며 메소드가 끝나면 소멸되어 사용할 수 없게 된다.

∘ Stack Area

[ Java Type ]

기본형 타입

∘ boolean, char, byte, short, int, long, float, double (8개)

∘ 비객체 타입, null 불가능

∘ NULL을 넣고 싶다면 Wrapper class 활용

∘ Stack Area에 저장

참조형 타입

∘ class, interface, array, enum

∘ JAVA 최상인 java.lang.Object 클래스를 상속하는 모든 클래스

∘ new로 인해 생성되어 Heap Area에 저장, GC에 의해 관리

∘ 비교시 equals( ) 사용

[ Casting ]

∘ 변수가 원하는 정보를 다 갖고있는것

∘ 목적 : 다형성 + 상속

ex) int a = 0.1 ⇨ 0.1은 int로 될 정보 또한 지니고 있다. ( upCasting )

but int b = (int)true ⇨ boolean을 int로 캐스트 불가능 ( downCasting )

묵시적 형변환

∘ 캐스팅이 자동으로 발생 (UpCasting)

∘ Parent p = new Child();

⇨ Parent를 상속받은 Child는 Parent의 속성을 포함하고 있으므로 명시할 필요가 없다.

명시적 형변환

∘ 캐스팅할 내용을 적어줘야 하는 경우 (DownCasting)

∘ Parent p = new Child();

Child c = (Child) p;

[ Call By Value & Call By Reference ]

Call By Value : 값에 의한 호출

∘ 함수가 호출될 때 메모리 공간 안에서 함수를 위한 임시공간 생성

∘ 변수값을 복사해서 전달받음 ( Local Value 속서을 지닌다 )

⇨ 함수 안 인자값이 변경되어도 외부 변수값은 변경되지 않음

Call By Reference : 참조에 의한 호출

∘ 함수 호출시 인자로 전달되는 변수의 레퍼런스를 전달

∘ 함수 안에서 인자 값이 변경되면 객체 값도 변경됨

∘ 자바는 항상 Call By Value로 값을 넘긴다.

∘ 메모리에 저장된 주소를 보내는 것도 물리적 관점으로 값으로 볼 수 있기 때문

∘ 객체의 참조값을 직접 바꾼것이 아니라 객체의 참조값을 통해 멤버변수에 접근하여 실제 값을 바꾼것

∘ 객체를 매개변수로 전달했을때 객체 안의 매개변수 값을 변경하면 주소 안의 실제 값을 바꿀 수 있다.

( 나머지는 불가능 )

[ Java 의 String ]

∘ 불변 객체 (Immutable) 이므로 동기화를 신경쓰지 않아도 된다.

∘ 문자열 연산시 새로운 객체를 만드는 오버헤드 발생

∘ 문자열 연산이 적고 조회가 많은 상황에 쓰기 좋다.

∘ GC로 제거되어야 한다.

[ StringBuilder & StringBuffer ]

∘ Mutable 객체

∘ 문자열 연산 시 처음 만든 객체를 이용해 연산하고 크기를 변경시켜 문자열을 변경한다.

∘ 문자열 연산이 자주 발생하는 상황에 쓰기 좋다.

∘ 문자열 연산시 크기를 변경시킨다.

StringBuilder

∘ Thread Unsafe

∘ 동기화를 고려하지 않는 싱글스레드 환경에 적합

StirngBuffer

∘ Thread Safe

∘ 동기화가 필요한 멀티스레드 환경에 적합

[ == equals ]

== : 비교하고자 하는 대상의 주소값 비교

equals() : 비교하고자 하는 대상의 값 비교

[ Collection ]

∘ List, Map, Set 인터페이스를 기준으로 여러 구현체 존재 ( Stack, Queue etc. )

∘ 동적배열의 개념

∘ 다수의 Data를 다르는데 표준화된 클래스를 제공해주기 때문에 편하게 사용할 수 있음

∘ 객체를 보관하기 위한 공간을 미리 정하지 않아도 되므로 객체 수를 동적으로 정할 수 있다.

List

∘ ArrayList, LinkedList, Stack, Queue

∘ 중복 O, 저장공간 가변적

Map

∘ HashMap, LinkedHashMap (key순서보장)

∘ key 중복 X

∘ key-value 쌍으로 이루어진 자료구조

∘ 데이터에 접근하기 위해 index가 아닌 key로 접근

Set

∘ HashSet (무작위 값), LinkedHashSet (순서보장), TreeSet(자동정렬)

∘ 집합, 중복 X

[ Access Modifier ]

∘ 변수 or 메서드 접근 범위를 설정하는 Java 예약어

∘ public : 어떤 클래스에서도 접근 가능

∘ protected : 해당 패키지&클래스를 상속받은 외부 패키지의 클래스에서 접근 가능

∘ package(defalut) : 클래스가 정의된 해당 패키지에서만 접근 가능

∘ private : 해당 클래스 내에서만 접근 가능

[ final ]

∘ final 클래스 : 다른 클래스에서 상속 불가능

∘ final 변수 : 변하지 않는 상수값이 되어 새롭게 할당 불가능

∘ final 메서드 : 다른 메소드에서 오버라이딩 불가능

[ static ]

∘ 프로그램이 시작할 때 Stack Area에 메모리가 할당되어 프로그램이 종료될때 해체되는 변수

∘ static 클래스 : 객체를 생성하지 않고도 변수&함수 사용 가능

∘ static 변수 : 객체들이 다같이 공유하는 데이터

∘ static 메서드 : 객체들의 데이터와 관계없는 완벽하게 공통적인 로직을 정의할 때 사용

인스턴스변수나 객체의 함수를 사용할 수 없다

[ Overriding vs. Overloading ]

∘ Overriding : 상위 클래스/인터페이스에 존재하는 메소드를 하위클래스에서 재정의하는 것

∘ Overloading : 같은 이름과 return형의 함수를 다른 매게변수로 만들어 사용

[ 추상 클래스 ]

∘ 미완성 클래스(설계도)

∘ 혼자로써의 역할은 못하지만, 새로운 클래스의 부모 클래스로서의 의미를 갖는다.

∘ 일반 함수, 멤버 포함 가능 [ 차이점 ]

∘ 추상 메소드를 포함한다면 반드시 추상 클래스로 선언

∘ 인스턴스 생성 불가능 [ 공통점 ]

목적 : 자식클래스로 하여금 구현을 강제한다, 메소드의 동작은 자식클래스에게 위임한다.

[ 인터페이스 ]

∘ 기본 설계도

∘ 인터페이스를 구현하는 모든 클래스에 대해 특정 메소드가 반드시 존재하도록 강제

∘ 일종의 추상클래스지만 추상화 정도가 높아 일반메소드, 일반멤버변수를 가질 수 없다.

∘ 오직 추상메소드와 상수만을 가질 수 있다.

∘ 모든 멤버변수 : public static final 이어야 하며 생략가능

∘ 모든 메소드 : public abstract 이어야 하며 생략 가능

∘ 클래스에서 인터페이스 다중 상속 가능, 다중 구현 가능

∘ 장점 : 대규모 프로젝트 개발시 일관된 표준화 가능

∘ 클래스 작성 & 인터페이스 구현 동시에 진행 가능 ⇨ 개발시간↓

∘ 클래스간 관계를 인터페이스로 연결하면 클래스마다 독립적 프로그래밍 가능

목적 : 구현 객체가 같은 동작을 하는것을 보장하는것

[ 추상 클래스 vs 인터페이스 ]

추상클래스 인터페이스 ∘ 클래스 o

∘ 추상메소드 , 일반메소드 , 일반멤버 가능

∘ 다중 상속 불가능

∘ 목적

- 상속을 받아 기능을 확장시키는 목적

- 공유의 목적

- 자식클래스에게 구현 강제화 ∘ 클래스 x

∘ 추상메소드와 상수 , default/static 메소드

∘ 다중 구현 가능

∘ 목적 : 구현 객체와 같은 동작을 보장하기 위해 사용

[ Wrapper Class ]

∘ 기본자료형 8가지에 대한 클래스 표현

∘ null을 사용해야 할때 사용하는 경우가 있음

∘ == 사용 대신 .intValue( ) 메소드를 통해 값을 가져와 비교해야 한다.

∘ 사용 이유

1. null을 사용해야 할때

2. Genereics( < > ) 에 넣어야 할때

3. String타입으로 변환하고자 할때

∘ Boxing (to Wrapper) , Unboxing (from Wrapper)

[ Generic ]

∘ 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입을 가질 수 있도록 하는것

∘ Collection 클래스에서 사용하는 것으로 컴파일 과정에서 타입체크를 해주는 기능

∘ Collection 내부에 들어온 값이 내가 원하는 값인지 별도로 로직처리를 구현할 필요가 없다.

∘ API 설계시 보다 명확한 의사전달 가능

class Generic { private K key; private V value; void set(K key, V value) { this.key = key; this.value = value; } void print() { System.out.println(key + " : " + value); } } public class Main { public static void main(String[] args) { Generic generic = new Generic<>(); generic.set("TEN", 10); generic.print(); // TEN : 10 Generic generic2 = new Generic<>(); generic2.set(10, "TEN"); generic2.print(); // 10 : TEN } }

[ Annotation (@) ]

∘ 컴파일러에게 코드 문법 에러를 체크하도록 정보 제공

∘ 실행 시 특정 기능을 실행하도록 정보 제공

∘ built-in ano (@Override) , Meta ano , Custom ano

[ Reflection ]

∘ 자바에서 이미 로딩이 완료된 클래스 or 다른 클래스를 동적로딩하여

구체적인 타입을 몰라도 생성자, 멤버필드, 멤버메소드를 사용할 수 있는 기법

∘ 객체를 통해 클래스의 패키지정보, 접근지정자, 부모클래스, 어노테이션을 얻을 수 있음

∘ 컴파일 타임이 아니라 런타임에 동적으로 특정 클래스의 정보를 객체화하여 추출할 수 있는 기법

∘ 사용 목적 : Runtime중 다른 클래스를 동적로딩하여 접근할 필요가 있을때

∘ 주의 : private 멤버도 Field.setAccessible( ) 를 true로 지정하면 접근&조작이 가능해진다.

∘ JVM 최적화 수행 불가능 ⇨ 성능↓

[ Java Thread ]

∘ JDK에서 지원하는 java.lang.Thread 제공

∘ 생성방법

① Thread 클래스 이용

∘ Thread 클래스로부터 제공되는 run() 메소드를 오버라이딩해서 사용

public class ThreadX extends Thread { public void run ( ) { // 수행할 문장 기술 } } ... ThreadX TX = new ThreadX( ); TX.start( );

② Runnalbe 인터페이스를 구현해서 생성

∘ 현재 클래스가 이미 다른 클래스로부터 상속받고 있다면 Runnable인터페이스를 이용하여 스레드 생성

∘ Runnable Interface : JDK 라이브러리 인터페이스, run( ) 메소드만 정의되어 있다.

∘ run( ) 메소드가 종료되면 스레드는 종료

∘ 한번 종료한 스레드는 다시 시작할 수 없다.

∘ 한 스레드에서 다른 스레드를 강종 가능

public class RunnableX implements Runnable { public void run ( ) { // 인터럽트 예외처리 + 수행할 문장 기술 } } ... RunnableX RX = new RunnableX( ); Thread th = new Thread(RX); th.start( );

∘ 스레드 상태 6가지

⇨ NEW(생성) / RUNNABLE(실행or준비완료) / WAITING(wait, 동기화) /

TIME_WAITING(sleep) / BLOCK(I/O작업) / TERMINATED(종료)

∘ 스레드 상태는 JVM에 의해 기록&관리

∘ wait( ) : 스레드가 lock을 가지고 있으면, lock 권한을 반납하고 대기하게 만든다.

∘ notify( ) : 대기상태인 스레드에게 다시 lock 권한을 부여하고 수행하게 한다.

[ Error vs Exception ]

Throwable 클래스

∘ 예외처리를 할 수 있는 최상위 클래스 ( Exception, Error가 상속받음 )

Error

∘ 컴파일 시 문법적인 오류

∘ 런타임 시 NullPoint 참조와 같은 오류 등으로 심각한 문제를 야기시켜 프로세스가 종료

⇨ OOM, StackOverflow 등 복구할 수 없는 심각한 오류

∘ OOM : JVM에서 설정된 메모리의 한계를 벗어난 상황

∘ Heap 사이즈 부족 / 너무 많은 class 로드 / 가용가능한 swap X / 큰 메모리의 native 메소드가 호출

∘ 해결 : dump 파일 분석, jvm 옵션 수정

Exception

∘ 동작 도중 예기치 않았던 이상 상태가 발생하여 수행중인 프로그램이 영향을 받는것

∘ 수습할 수 있는 비교적 덜 심각한 오류

∘ 예외가 주로 발생하는 원인

⇨ 사용자의 잘못된 입력, 잘못된 연산, 잘못된 로직, HW/Network 오작동, 시스템 과부하 etc.

∘ Checked Exception(예외처리 필수, 컴파일 불가) : RuntimeE, IOE, SQLE

∘ Unchecked Exception(런타임에 발생하는 예외) : RuntimeE 하위의 모든 예외 [ NullPointerE, IndexOutOfE etc... ]

[ Exception Handling ]

① try-catch를 이용하여 예외에 대한 최종적인 책임을 지고 처리

∘ try에는 위험한 로직이 들어가고 catch에는 예외발생시 수행할 로직이 들어간다.

∘ catch는 else if 처럼 여러개 사용 가능

∘ finally는 마지막에 실행하고 싶은 로직 ( 대표적으로 .close( ) )

② throws Exception을 이용하여 예외의 책임을 호출하는 쪽이 지도록 하는 방식

from http://gudwnsgur.tistory.com/12 by ccl(A) rewrite - 2021-11-15 02:27:34