객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임 중 하나로, 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법입니다.
과거에 코드를 작성하면 절차적으로 이루어지는 절차 지향적인 언어와는 달리 구성요소들이 객체 안에 담겨있어 특정 객체만 동작하게 하거나 데이터를 처리하기 등 다양한 일을 할 수 있게 되었다.
- 장점
▶코드 재사용이 용이
남이 만든 클래스를 가져와서 이용할 수 있고 상속을 통해 확장해서 사용할 수 있다.
▶유지보수가 쉬움
절차 지향 프로그래밍에서는 코드를 수정해야할 때 일일이 찾아 수정해야하는 반면 객체 지향 프로그래밍에서는 수정해야 할 부분이 클래스 내부에 멤버 변수혹은 메서드로 존재하기 때문에 해당 부분만 수정하면 된다.
▶대형 프로젝트에 적합
클래스 단위로 모듈화시켜서 개발할 수 있으므로 대형 프로젝트처럼 여러 명, 여러 회사에서 프로젝트를 개발할 때 업무 분담하기 쉽다.- 단점
▶처리 속도가 상대적으로 느림
▶객체가 많으면 용량이 커질 수 있음
▶설계시 많은 시간과 노력이 필요
객체지향 프로그래밍은 크게 캡슐화, 상속, 추상화, 다형성으로 나눌 수 있습니다.
캡슐화,
객체 지향 프로그래밍에서 기능과 특성의 모음을 "클래스"라는 "캡슐"에 분류해서 넣는것이 캡슐화라고 합니다.
객체가 외부에 노출하지 않아야할 정보 또는 기능을 접근제어자를 통해 적절히 제어 권한이 있는 객체에서만 접근하도록 할 수 있기에, 코드의 수정이 일어났을 때 책임이 있는 객체만 수정하면 되어 영향 범위를 예측할 수 있습니다. 그리고, 뿐만 아니라 관련된 기능과 특성을 한 곳에 모으고 분류하기 때문에 객체 재활용이 원활해졌습니다.상속,
상속은 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게하고 기능의 일부분을 변경해야 할 경우 상속받은 자식클래스에서 해당 기능만 다시 수정(정의)하여 사용할 수 있게 하는 것입니다.추상화,
추상화는 "공통의" 속성이나 기능을 묶어서 이름을 붙여 클래스를 설계하는 것 입니다.다형성,
하나의 변수명, 함수명 등이 상황에 따라 다른 의미로 해석될 수 있는 것 입니다. 즉 오버라이딩(Overriding), 오버로딩(Overloading)이 가능하다는 것 입니다.
- 오버라이딩 : 상위 클래스가 가지고 있는 메소드를 상속 받을 때 자식 클래스에서 메소드를 재 정의하는것을 말합니다.
- 오버로딩 : 같은 이름의 함수를 여러개 정의하고, 매개변수의 타입과 개수를 다르게 하여 매개변수에 따라 다르게 호출할 수 있게 하는 것 입니다.
객체지향 설계 5대 원칙은 SOLID라 하며, 각 원칙의 앞글자를 따왔습니다.
SRP 단일 책임 원칙 (single responsiblity principle)
"한 클래스는 하나의 책임만 가져야 하고 그 책임을 수행하는데 집중되어 있어야 한다"
여기에서 하나의 책임이라는 것은 모호한 의미를 가집니다. 책임은 상황에 따라서 클수도 있고 작을수도 있기 때문입니다. 설계가 잘 되었는지 확인할 수 있는 중요한 기준은 변경입니다. 변경이 있을때 파급 효과가 적으면(딱 하나의 클래스만 수정해도 된다면) 단일 책임 원칙을 잘 따른 것입니다.OCP 개방-폐쇄 원칙 (Open/closed principle)
"소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다"
요구 사항의 변경이나 추가사항이 발생했을때 기존 구성요소는 변경이 일어나지 않아야 하며, 기존 구성요소를 쉽게 확장해서 재사용 할 수 있어야 한다는 뜻입니다.
확장을 하려면 당연히 기존의 코드를 바꿔야 하는거 아닌가? 라고 생각할 수 있지만 다형성을 활용해서 기존의 코드를 바꾸지않고 확장할 수 있습니다.
인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현하는 경우 클래스를 새로 만드는 것은 기존 코드를 변경한 것이 아닙니다.LSP 리스코프 치환 원칙 (Liskov substitution principle)
"프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다"
다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것입니다. 인터페이스를 구현한 구현체를 믿고 사용하려면 이 원칙이 필요합니다.
자동차 인터페이스에 앞으로 가는 기능인 엑셀이 있습니다. 하지만 하위 클래스에서는 엑셀을 뒤로가게 하는 기능으로도 만들수 있습니다.(컴파일 오류는 발생하지 않음) 하지만 이 인터페이스 규약에서 엑셀은 앞으로 가는 기능이기 때문에 하위 클래스에서는 이 기능을 보장 해줘야 합니다.ISP 인터페이스 분리 원칙 (Interface segregation principle)
"특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다"
큰 덩어리의 인터페이스를 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 합니다. 인터페이스를 분리하게 되면 기능이 명확해지고, 대체 가능성이 높아집니다.DIP 의존관계 역전 원칙 (Dependency inversion principle)
"프로그래머는 "추상화에 의존해야지, 구체화에 의존하면 안된다." 의존성 주입(DI)는 이 원칙을 따르는 방법 중 하나다"
쉽게 말하면 구현 클래스에 의존하지 말고 인터페이스에 의존하라는 뜻입니다.
인터페이스에 의존하게 되면 구현 클래스에 대해서는 몰라도 되기 때문에 유연하게 구현체를 변경할 수 있습니다. 반대로 구현 클래스에 의존하게 되면 변경이 어려워 집니다.
추상클래스는 추상메소드를 포함하고 있는 클래스를 의미합니다. 추상메소드는 메소드의 내부가 구현되어 있지 않은 메소드 입니다. 클래스 내부에 이 추상 메소드가 하나라도 있다면 클래스 앞에 abstract 키워드를 붙여서 추상 클래스로 만들어 줘야 합니다. 추상 메소드는 상속받은 클래스에서 반드시 구현 되어야 하고 그렇기 때문에 추상 클래스에는 final 키워드를 붙일 수 없습니다.
그러나,
추상클래스 내부에는 추상메소드 외에 일반 메소드나 변수가 존재할 수 있습니다. 이렇게 구현된 일반 메소드는 다른 클래스의 메소드와 똑같이 동작합니다.인터페이스는 모든 메소드가 추상 메소드로만 구성된 것을 의미하며 상속하는 클래스에서는 인터페이스에 존재하는 모든 추상메소드를 구현해야만 합니다. 반드시 상속이 되어야 하기 때문에 인터페이스 역시 final 키워드가 붙을 수 없습니다.
인터페이스를 상속받은 클래스는 모든 메소드를 재정의 해야 합니다. 그리고 클래스의 인스턴스는 인터페이스를 통해 다형성을 가질 수 있습니다. 쉽게 말하면 인터페이스는 하위 클래스에게 일종의 설계도 역할을 합니다. 하위 클래스는 여러개의 설계도를 가질 수 있고 각각의 설계도에 맞는 구현체를 제공할 수 있는 것입니다.
그런데 추상 클래스의 경우는 조금 다릅니다. 일단 추상클래스는 다중상속을 할 수 없습니다. 하위 클래스는 오로지 상속받은 추상 클래스의 기능을 이용하고 확장하는 역할을 하게 됩니다.
추상클래스는 상속받은 클래스의 기능을 이용하고 확장하는 것이고, 인터페이스는 하위 클래스에게 일종의 설계도를 제공한다.' 라는 것이 추상클래스와 인터페이스의 궁극적인 차이점이라고 할 수 있겠습니다.
- "객체" 중심의 설계 vs "함수" 중심의 설계
- 클래스 디자인과 객체들의 관계 중심 코드 vs 값의 연산 및 결과 도출 중심 코드
- 클래스가 일급 객체 vs 함수 자체가 일급 객체
- 같은 인자값에 대해 다른 결과값이 반환될 수 있음 vs 항상 같은 결과값 반환됨
- 오버라이딩 : 상위 클래스가 가지고 있는 메소드를 상속 받을 때 자식 클래스에서 메소드를 재 정의하는것을 말합니다.
- 오버로딩 : 같은 이름의 함수를 여러개 정의하고, 매개변수의 타입과 개수를 다르게 하여 매개변수에 따라 다르게 호출할 수 있게 하는 것입니다.
JVM (Java Virtual Machine)은,
스택 기반의 가상 머신으로, Java가 OS에 구애받지 않고 재사용 가능하게 해주고 자바 바이트 코드를 실행할 수 있는 주체입니다.자바 프로그램 실행 과정입니다.
1. 프로그램이 실행되면 JVM은 OS로부터 프로그램이 필요로하는 메모리를 할당받는다. JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
2. 자바 컴파일러 javac가 자바 소스 코드를 읽어들여 자바 바이트 코드 .class로 변환시킨다.
3. Class Loader를 통해 class 파일들을 JVM으로 로딩한다.
4. 로딩된 class 파일들은 Execution Engine을 통해 해석된다.
5. 해석된 바이트코드는 Runtime Data Area에 배치되어 실질적인 수행이 이루어지게 된다. 이 실행과정 속에서 JVM은 필요에 따라 스레드 동기화와 GC같은 관리 작업을 수행한다.
1) Method Area
JVM이 실행되면서 생기는 공간이다.
Class 정보, 전역변수 정보, Static 변수 정보가 저장되는 공간이다.
Runtime Constant Pool 에는 말 그대로 '상수' 정보가 저장되는 공간이다.
모든 스레드에서 정보가 공유된다.2) Heap
new 연산자로 생성된 객체, Array와 같은 동적으로 생성된 데이터가 저장되는 공간
Heap에 저장된 데이터는 Garbage Collector 가 처리하지 않는한 소멸되지 않는다.
Reference Type 의 데이터가 저장되는 공간
모든 스레드에서 정보가 공유된다.3) Stack
지역변수, 메소드의 매개변수와 같이 잠시 사용되고 필요가 없어지는 데이터가 저장되는 공간
Last In First Out, 나중에 들어온 데이터가 먼저 나간다
만약, 지역변수 이지만 Reference Type일 경우에는 Heap 에 저장된 데이터의 주소값을 Stack 에 저장해서 사용하게 된다.
스레드마다 하나씩 존재한다.4) PC Register
스레드가 생성되면서 생기는 공간
스레드가 어느 명령어를 처리하고 있는지 그 주소를 등록한다.
JVM이 실행하고 있는 현재 위치를 저장하는 역할5) Native Method Stack
Java 가 아닌 다른 언어 (C, C++) 로 구성된 메소드를 실행이 필요할 때 사용되는 공간
자바는 동적 로드, 즉 컴파일 타임이 아니라 런타임(바이트 코드를 실행할 때)에 클래스 로드하고 링크하는 특징이 있다. 이 동적 로드를 담당하는 부분이 JVM의 클래스 로더이다. 정리하자면, 클래스 로더는 런타임 중에 JVM의 메소드 영역에 동적으로 Java 클래스를 로드하는 역할을 한다. 클래스 로더에는 로딩, 링크, 초기화 단계로 나뉘어져 있다.
로딩
- 자바 바이트 코드(.class)를 메소드 영역에 저장한다.
- 각 자바 바이트 코드(.class)는 JVM에 의해 메소드 영역에 다음 정보들을 저장한다.
- 로드된 클래스를 비롯한 그의 부모 클래스의 정보
- 클래스 파일과 Class, Interface, Enum의 관련 여부
- 변수나 메소드 등의 정보
링크
- 검증: 읽어 들인 클래스가 자바 언어 명세 및 JVM 명세에 명시된 대로 잘 구성되어 있는지 검사한다.
- 준비: 클래스가 필요로 하는 메모리를 할당하고, 클래스에서 정의된 필드, 메소드, 인터페이스를 나타내는 데이터 구조를 준비한다.
- 분석: 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.
초기화
- 클래스 변수들을 적절한 값으로 초기화 한다. 즉, static 필드들이 설정된 값으로 초기화한다.
클래스 로더는 새로운 클래스를 로드해야 할 때, 다음과 같은 방식으로 로드를 수행한다.
- JVM의 메소드 영역에 클래스가 로드되어 있는지 확인한다. 만일 로드되어 있는 경우 해당 클래스를 사용한다.
- 메소드 영역에 클래스가 로드되어 있지 않을 경우, 시스템 클래스 로더에 클래스 로드를 요청한다.
- 시스템 클래스 로더는 확장 클래스 로더에 요청을 위임한다.
- 확장 클래스 로더는 부트스트랩 클래스 로더에 요청을 위임한다.
- 부트스트랩 클래스 로더는 부트스트랩 Classpath(JDK/JRE/LIB)에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않는 경우 확장 클래스 로더에게 요청을 넘긴다.
- 확장 클래스 로더는 확장 Classpath(JDK/JRE/LIB/EXT)에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않을 경우 시스템 클래스 로더에게 요청을 넘긴다.
- 시스템 클래스 로더는 시스템 Classpath에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않는 경우 ClassNotFoundException을 발생시킨다.
자바나 코틀린 프로그램을 개발 하다 보면 유효하지 않은 메모리인 가바지(Garbage)가 발생하는데 이를 알아서 정리해주는 것이 가비지 콜렉터입니다.
처음 생성된 객체 new Model(); 는 Young Generation 영역의 일부인 Eden 영역에 위치하게된다. 그리고 Minor GC가 발생하게 되면, 사용하지 않는 다시말하면 다른 곳에서 참조되지 않는 객체는 메모리에서 제거된다.
Eden 영역에서 살아남은 객체는 Young Generation 영역의 또다른 일부인 Survivor 영역으로 이동하게된다. Survivor 영역은 Survivor1 영역과 Survivor2 영역으로 구성되어 있는데, Minor GC가 발생할 때마다 Survivor1 영역에서 Survivor2 영역으로 또는 Survivor2 영역에서 Survivor1 영역으로 객체가 이동하게되며, 이 과정에서 더이상 참조되지 않는 객체는 메모리에서 제거된다.
Minor GC가 발생하는 동안 Survivor1, Survivor2 영역을 오가며 살아남은 객체들은 최종적으로 Old Generation 영역으로 옮겨지며, Old Generation 영역에 있다가 미사용된다고 식별되는 객체들은 Full GC를 통해 메모리에서 제거된다.오래되었다고 하는 기준은 Young Generation 영역에서 Minor GC 가 발생하는 동안 얼마나 오래 살아남았는지로 판단한다. 각 객체는 Minor GC에서 살아남은 횟수를 기록하는 age bit 를 가지고 있으며, Minor GC가 발생할 때마다 age bit 값은 1씩 증가 하게되며, age bit 값이 MaxTenuringThreshold 라는 설정값을 초과하게 되는 경우 Old Generation 영역을 객체가 이동 되는 것이다.
GC 모니터링이란 JVM이 어떻게 GC를 수행하고 있는지 알아내는 과정을 말합니다. 예를 들어 Young 영역에 있던 객체를 Old 영역으로 언제 얼마나 이동했는지, stop-the-world가 언제 일어나고 얼마동안 일어났는지 등의 정보를 알 수 있습니다. GC를 모니터링 하는 이유는 JVM이 효율적으로 GC를 수행하는지 파악하고 추가적인 GC 튜닝 작업이 필요한지 확인하기 위해서입니다. GC 모니터링으로 파악한 정보를 바탕으로 애플리케이션을 수정하거나 GC를 튜닝할 수 있습니다.
배열을 사용하다 보면 여러가지 비효율적인 문제가 생깁니다. 가장 큰 문제점은 크기가 고정적이라는 것입니다. 배열의 크기는 생성할 때 결정되며 그 크기를 넘어가게 되면 더이상 데이터를 저장할 수 없습니다. 또 데이터를 삭제하면 해당 인덱스의 데이터는 비어있어 메모리가 낭비되는 등 여러 문제점들이 발생합니다. 그렇기에 자바는 배열의 이러한 문제점을 해결하기 위해, 널리 알려져 있는 자료구조를 바탕으로 객체나 데이터들을 효율적으로 관리(추가, 삭제, 검색, 저장)할 수 있는 자료구조들을 만들어 놓았습니다. 이러한 자료구조들이 있는 라이브러리를 컬렉션 프레임워크라고 합니다. 대표적으로는 List, Set, Map, Stack, Queue 등이 있습니다.
- 벡터는 한 번에 하나씩 쓰레드에서만 접근 가능
- 어레이리스트는 동시에 여러 쓰레드에서 접근 가능
HashSet 세트의 반복 순서를 보장하지 않거나 시간이 지나도 순서가 일정하게 유지됩니다.
-> 성능이 중요하고 요소의 순서가 중요하지 않은 경우 사용TreeSet, 사용된 생성자에 따라 요소의 자연스러운 순서에 따라 또는 지정된 Comparator에 따라 반복됩니다.
-> 요소가 자연적인 순서를 사용하거나 Comparator에 의해 순서화되어야 할 때.LinkedHashSet 요소가 집합에 삽입된 순서와 동일한 예측 가능한 반복 순서를 정의하는 모든 요소를 통해 이중 연결된 목록을 실행합니다.
-> 요소의 삽입 순서를 유지해야 하는지 여부.
HashMap, LinkedHashMap, TreeMap, Hashtable 네 가지 모두 키(key)에서 값(value)으로의 대응 관계 가 있고 키를 기준으로 순회할 수 있습니다. 이 클래스들의 가장 큰 차이점은 시간 복잡도와 키가 놓이는 순서에 있습니다.
HashMap
- 검색과 삽입에 O(1) 시간이 소요된다.
- 키의 순서는 무작위로 섞여 있다.
- 구현은 연결리스트로 이루어진 배열로 되어 있다.
- null key와 null value를 모두 허용 한다.
LinkedHashMap
- 검색과 삽입에 O(1) 시간이 소요된다.
- 키의 순서는 삽입한 순서대로 정렬되어 있다.
- 구현은 양방향 연결 버킷으로 구현되어 있다.
TreeMap
- 검색과 삽입에 O(log N) 시간이 소요된다.
- 키의 순서는 정렬되어 있다.
- 즉, 키는 반드시 Comparable 인터페이스를 구현하고 있어야 한다.
- 구현은 레드-블랙 트리로 구현되어 있다.
Hashtable
- 검색과 삽입에 O(1) 시간이 소요된다.
- 키의 순서는 무작위로 섞여 있다.
- 구현은 연결리스트로 이루어진 배열로 되어 있다.
- null key와 null value를 모두 불허 한다.
- 동기화를 지원한다 (thread safe)
=> 따라서 Hashtable은 멀티스레드 환경에서 동작가능하며, 동기화를 지원하기 때문에 HashMap보다는 느리다.일반적으로 별다른 이유가 없으면 HashMap 을 사용하는 것이 좋습니다. 일반적으로 빠르고 오버헤드가 적기 때문입니다.
- 삽입한 순서대로 키 정보를 얻고 싶다면 LinkedHashMap
- 정렬된 순서대로 키 정보를 얻고 싶다면 TreeMap
- 병렬 처리를 하면서 자원의 동기화를 고려해야 하는 상황이라면 Hashtable
Servlet은,
자바 플랫폼에서 웹 앱을 개발할 때 사용하는 핵심기술로, 서버에서 웹페이지 등을 동적으로 생성하거나 데이터 처리를 수행하기 위해 자바로 작성된 프로그램입니다. Servlet은 JAVA코드안에 HTML태그가 삽입되어 만들어지며 확장자는 .java입니다.서블릿 생명주기
1) 사용자가 url을 호출하여 컨테이너에 새로운 요청을 한다.
2) 컨테이너가 요청을 접수하여 HttpServletRequest request 객체 / HttpServletResponse response 객체를 생성
3) 접수된 url을 분석하여 해당 서블릿 객체를 생성
- 서블릿 객체가 생성되면서 서블릿에서 init() 메서드를 실행하여 Servlet 객체를 초기화 한다.
- 사용자 요청을 처리하기 위해 스레드를 생성
4) service(request, response) 메서드가 호출되어, request 타입을 분석하여 타입에 따라 적절한 메서드를 호출
- GET 방식이라면 doGet() 으로, POST 방식이라면 doPost를 호출하는 식.
5) 응답을 클라이언트에 전송
6) was가 종료되면서 destory()메서드 실행, 생성된 스레드를 소멸시킴.간략하게
1. 요청 시 서블릿 객체 생성
2. 서버는 init() 메소드를 호출하여 서블릿을 초기화
3. service() 메소드를 호출해서 서블릿이 브라우저의 요청을 처리
4. service() 메소드는 특정 HTTP요청(GET, POST 등)을 처리하는 메소드 - doGet(), doPost() 등 - 를 호출
5. 서버는 destroy()는 메소드를 호출하여 서블릿을 제거
HTML을 코딩하기 너무 어렵고 불편해서 HTML내부에 JAVA코드를 삽입하는 형식이 JSP입니다. 다시말해 서블릿의 단점을 보완해서 만든 서블릿 기반의 스트립트 기술입니다. 서블릿을 이용해서 웹프로그래밍을 할 수는 있지만 자바에 대한 지식이 필요하고 화면 인터페이스 구성에 너무 많은 코드들이 필요하는 등 비효율적인 측면들이 많습니다. 때문에 서블릿을 작성하지 않고도 웹프로그래밍을 쉽게 할 수 있게 해주는 기술이 바로 JSP(Java Server Page)입니다.
Servlet
- 자바코드로 구현하고 컴파일, 배포한다.
- HTML 태그로 문자열("")스크림으로 처리해야한다.
- 자바에대한 깊은 이해도를 요구한다.
- 코드가 수정되면 다시 컴파일하고 배포해야한다.
JSP
- 키워드가 태그화 되어있어 서블릿에 비해 배우기 쉽다.
- 자바코드를 <% %>태그 안에서 처리한다.
- 자바에대한 깊은 이해도가 필요하지 않다.
서블릿과 JSP는 각자 잘하는 역할을 담당해서 웹 어플리케이션을 구성합니다.
JSP는 사용자에게 결과를 보여주는 역할을 담당하고, 서블릿은 클라이언트의 요청을 받아 분석하고 비즈니스 층과 통신해 처리한 후 그 결과를 다시 클라이언트에게 응답하는 컨트롤러 층을 담당합니다.
한마디로, 클라이언트는 서블릿에 요청을 하고 서블릿은 이를 처리한 후 JSP를 이용해서 클라이언트에게 응답하는 구조입니다.
MVC패턴에서는 View는 JSP, Controller는 Servlet을 사용합니다.
지역변수(stack 영역)
- 지역안에서 선언된 변수
- 그 영역의 닫는 중괄호 "}" 를 만났을 때, 메모리에서 해제된다.
- 사용자가 직접 초기화 해야한다.
- 다른 영역에서 접근할 수 없기 때문에 보안성이 뛰어나다.
전역변수(data 영역)
- 클래스 영역 안에 있고, 전체 영역에서 사용가능한 변수
- 클래스 영역 외의 어떠한 영역에도 포함되어 있지 않다.
- new를 만났을 때 초기화 된다.
- 프로그램 종료시 메모리에서 해제된다.
- 다른 영역에서도 접근 할 수 있기 때문에, 보안성이 상대적으로 낮다.
static변수(data 영역)
- 컴파일을 하게 되면 가장 먼저 메모리에 올라가고, 어떠한 경우에도 초기화가 되지 않는다.
- 단, 프로그램 종료시 메모리에서 해제 된다.
- 메모리에 고정되기 때문에 남용시 메모리 혹은 프로그램 실행 속도에 악영향을 준다.
접근 제어자는 변수, 메서드의 접근을 제어하기 위해 적어주는 예약어를 말합니다. public부터 privated, protecte, default 네 가지 종류가 있습니다.
public
public이 붙은 변수나 메서드는 같은 프로젝트 안에서 사용 가능합니다.default
접근 제어자가 아무것도 붙지 않은 변수나 메서드는 default 상태로, 같은 패키지 안에서만 사용 가능합니다.protected
protected가 붙은 변수나 메서드는 다른 패키지에서는 사용이 불가능합니다. 다만, 상속 관계일 때는 다른 클래스에서 사용 가능합니다.private
private이 붙은 변수나 메서드는 같은 클래스 내에서만 사용 가능합니다.
접근 제어자를 사용하는 이유는 보안 때문이라고 할 수 있습니다. 만약에 웹사이트에서 아이디와 비밀번호 같은 중요한 정보를 public 변수에 저장을 한다면 아무데서나 직접적으로 접근하여 그 값을 변경할 수 있기 때문에 노출되기 쉽습니다. 이런 중요한 변수들은 대부분 private를 붙여줍니다.
또한, 여러 사람들과 함께 프로그램을 만들다 보면 다른 사람이 내가 만든 중요한 변수나 메서드를 무분별하게 사용하여 값을 변경할 수 있는데, 이를 막기 위해 상황에 맞는 접근 제어자를 사용합니다.
Java 직렬화는,
- 자바 시스템 내부에서 사용되는 객체 또는 데이터들을 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술과 바이트로 변환된 데이터를 다시 객체로 변환하는 역직렬화를 포함합니다.
- 시스템적으로 JVM의 Runtim Data Area(Heap 또는 스택영역)에 상주하고 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 말하기도 합니다.
자바의 자료형은 크게 기본 타입(primitive type)과 참조 타입(reference type)으로 나누어집니다. 대표적으로 기본 타입은 char, int, float, double, boolean 등이 있고 참조 타입은 class, interface 등이 있는데 프로그래밍을 하다 보면 기본 타입의 데이터를 객체로 표현해야 하는 경우가 종종 있습니다. 이럴 때에 기본 자료타입(primitive type)을 객체로 다루기 위해서 사용하는 클래스들을 래퍼 클래스(wrapper class)라고 합니다. 자바는 모든 기본타입(primitive type)은 값을 갖는 객체를 생성할 수 있습니다. 이런 객체를 포장 객체라고도 하는데 그 이유는 기본 타입의 값을 내부에 두고 포장하기 때문입니다. 래퍼 클래스로 감싸고 있는 기본 타입 값은 외부에서 변경할 수 없습니다. 만약 값을 변경하고 싶다면 새로운 포장 객체를 만들어야 합니다.
기본타입(primitive type) | 래퍼클래스(wrapper class) |
---|---|
byte | Byte |
char | Character |
int | Integer |
float | Float |
double | Double |
boolean | Boolean |
long | Long |
short | Short |
== 연산자와 String 클래스의 equals() 메소드의 가장 큰 차이점은 == 연산자는 비교하고자 하는 두개의 대상의 주소값을 비교하고, String클래스의 equals() 메소드는 비교하고자 하는 두개의 대상의 값 자체를 비교합니다.
int, char형 등은 Call by Value 형태로 기본적으로 대상에 주소값을 가지지 않는 형태로 사용됩니다.
하지만, String은 일반적인 타입이 아니라 클래스 입니다. 클래스는 기본적으로 Call by Reference형태로 생성 시 주소값이 부여됩니다. 그렇기에 String 타입을 선언했을 때는 같은 값을 부여하더라도 서로간의 주소값이 다를 수가 있습니다.
'데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법'
만약에 우리가 어떤 자료구조를 만들어 배포하려고 한다. 그런데 String 타입도 지원하고싶고 Integer타입도 지원하고 싶고 많은 타입을 지원하고 싶다. 그러면 String에 대한 클래스, Integer에 대한 클래스 등 하나하나 타입에 따라 만들 것인가? 그건 너무 비효율적이다. 이러한 문제를 해결하기 위해 우리는 제네릭이라는 것을 사용한다.이렇듯 제네릭(Generic)은 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 의미한다. 한마디로 특정(Specific) 타입을 미리 지정해주는 것이 아닌 필요에 의해 지정할 수 있도록 하는 일반(Generic) 타입이라는 것이다.
Generic(제네릭)의 장점
1. 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.
2. 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없다. 즉, 관리하기가 편하다.
3. 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.
final은 한 번만 할당할 수 있는 엔티티를 정의할 때 사용합니다.
메서드를 final로 선언하면 상속받은 클래스에서 오버라이딩이 불가능하게 되고 구현한 코드의 변경을 원하지 않을 때 사용합니다. side-effect가 있으면 안 되는 자바 코어 라이브러리에서 final로 선언된 부분을 많이 찾을 수 있습니다.
자바 8 특징
1. 람다 표현식
함수형 프로그래밍을 자바에서 사용 가능하게 해줍니다.
별도로 함수를 구현하지 않고 화살표를 사용해서 간단히 한 줄로 함수를 만들 수 있습니다.
2. Stream
반복문을 처리하는 방법 중 하나로, 병렬처리가 가능합니다.
예로, 스레드 풀에 가용할 수 있는 스레드들을 가져와서 사용함으로 반복문 처리 속도가 빠릅니다.
3. interface의 default라는 메소드를 구현할 수 있음
기존에는 공통적인 함수라도 인터페이스의 구현체들은 똑같은 것을 각각 다 따로따로 구현을 해줘야 했는데, default가 생김으로써 인터페이스안에 공통적으로 사용하는 함수를 미리 정의할 수 있게 되었습니다.
4. Optional
Null이 될 수 있는 객체를 감싸는 래퍼클래스입니다.
객체에 null이 대입되어 발생되는 오류들이 많아서, 이를 좀 더 안전하게 처리하기 위해 만들어졌습니다.자바 11 특징
1. String, File 클래스에 몇 가지 메소드 추가
2. 람다표현식에 var 키워드 사용 가능하도록 기능 추가
3. Http Client 추가
기존에는 아파치 라이브러리를 사용했는데, 11부터는 자바 표준 Http Client API가 생겼고, 성능이 이전 것보다 개선되었습니다.