클래스, 객체, 인스턴스
클래스는 객체를 만들어 내기 위한 설계도이고
객체는 소프트웨어 세계에 구현할 대상, 클래스를 바탕으로 설계된 구체적인 실체,
인스턴스는 객체에 메모리가 할당되어 실제로 활용되는 실체를 말합니다.
오버라이딩과 오버로딩
오버라이딩은 상위 클래스가 가지고 있는 메소드를 하위 클래스에서 재정의하여 사용하는 기술이고
오버로딩은 매개변수의 타입과 개수가 다른 같은 이름의 메소드들을 정의하여 사용하는 기술입니다
객체지향 언어의 특징과 장점
객체지향 언어의 특징으로는 상속, 캡슐화, 다형성, 추상화가 있습니다.
상속은 자식 클래스가 부모클래스를 연장해서 다시 사용할 수 있는 것이고,
캡슐화는 내부의 코드를 보호하기 위해 데이터에 직접적으로 접근하는 것을 막고 메소드로만 접근할 수 있도록 하는 것입니다.
다형성은 오버로딩을 사용하여 하나의 객체를 여러가지 타입으로 해석할 수 있는것이고
추상화는 객체를 개념화하는 것입니다.
이러한 특징들로 인해서 코드의 재사용성이 높고 유지보수가 용이하다는 장점이 있습니다.
추상클래스 | 인터페이스 |
---|---|
Default 생성자를 가진다. | 생성자를 가지지 않는다 |
추상 메소드, 비 추상 메소드를 포함할 수 있다. | 추상 메소드만 선언할 수 있다. |
추상 클래스를 상속한 클래스는 꼭 모든 메소드를 구현할 필요는 없으며 추상 메소드만 클래스 안에서 구현되면 된다. | 인터페이스를 구현하는 클래스는 인터페이스에서 선언된 모든 메소드를 다 구현해야 한다. |
객체 생성이 불가하므로 extends로 구현한다. | 객체 생성이 불가하므로 implements로 구현한다. |
추상클래스와 인터페이스의 차이점
추상클래스는 추상메소드를 하나이상 포함하고 있는 클래스로 Default 생성자를 가지고,
추상 클래스를 상속한 클래스가 모든 메소드를 구현할 필요는 없고 추상 메소드들만 구현하면 됩니다.
인터페이스는 추상메소드로만 이루어진 클래스로 생성자를 가지지 않고,
인터페이스를 구현하는 클래스는 선언된 모든 메소드를 다 구현해야 합니다.
둘 다 객체 생성이 불가합니다.
“SOLID” 원칙
객체지향 프로그래밍과 절차지향 프로그래밍의 차이
절차지향 프로그래밍은 실행하고자 하는 흐름, 절차를 중점으로 구현하고
객체지향 프로그래밍은 객체의 표현, 객체 사이의 관계, 상호 작용을 중점으로 구현합니다.
JAVA의 장단점
JAVA의 객체지향언어이며 장점으로는 JVM에서 동작하기 때문에 운영체제에 독립적이고,
Garbage Collector로 인해 자동으로 메모리 관리를 해준다는 점이 있습니다.
그리고 멀티 스레딩을 지원하고 동적 로딩을 지원해줍니다.
단점으로는 JVM에 의해 기계어로 번역되고 실행되는 과정을 거치기 때문에
C나 C++에 비해 속도가 느리고 설계단계에서의 시간이 오래걸리며
예외처리가 불편하다는 점이 있습니다.
public은 같은 프로젝트 내에서 접근 제한이 없고,
protected는 같은 패키지 안에서 사용이 가능하지만 외부에서 상속을 받으면 접근할 수 있습니다.
default는 같은 패키지 안에서만 사용이 가능하고 상속으로도 접근 할 수 없으며,
private는 해당 클래스 안에서만 접근이 가능합니다.
Generic
제네릭은 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법입니다.
클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정하여 사용합니다.
제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있고 관리하기가 편하며 코드의 재사용성을 높일 수 있습니다.
Java Collection 에는 List, Map, Set 인터페이스를 기준으로 여러 구현체가 존재한다. Collection을 사용하는 이유는 다수의 데이터를 다루는데 표준화된 클래스들을 제공해주기 때문에 DataStructure를 직접 구현하지 않고 편하게 사용할 수 있기 때문이다. 또한 배열과 다르게 객체를 보관하기 위한 공간을 미리 정하지 않아도 되므로, 상황에 따라 객체의 수를 동적으로 정할 수 있다. 이는 프로그램의 공간적인 효율성 또한 높여준다.
List : List 인터페이스를 직접 사용자가 정의하여 사용할 수도 있고, 대표적인 구조체로는 ArrayList가 존재한다. 이는 기존에 있었던 Vector를 개선한 것이다. 이외에도 LinkedList 등의 구현체가 있다. 데이터를 순차적으로 저장, 데이터의 중복을 허용, 데이터로 null을 허용
Map : 대표적인 구현체로 HashMap이 존재한다. Key-value의 구조로 이루어져 있으며 Map 에 대한 구체적인 내용은 DataStructure 부분의 hashtable과 일치한다. Key 를 기준으로 중복된 값을 저장하지 않으며 순서를 보장하지 않는다. Key 에 대해서 순서를 보장하기 위해서는 LinkedHashMap을 사용한다. 순서없이 key, value로 데이터를 저장, value는 중복을 허용하지만 key는 중복을 허용하지 않는다.
Set : 대표적인 구현체로 HashSet이 존재한다. Value에 대해서 중복된 값을 저장하지 않는다. 사실 Set 자료구조는 Map의 key-value 구조에서 key 대신에 value가 들어가 value를 key로 하는 자료 구조일 뿐이다. 마찬가지로 순서를 보장하지 않으며 순서를 보장해주기 위해서는 LinkedHashSet을 사용한다. 순서없이 key로만 데이터를 저장, key의 중복을 허용하지 않는다, key로 null을 허용하지 않는다
Stack과 Queue
인터페이스 | 설명 | 구현 클래스 |
---|---|---|
List | 순서가 있는 데이터의 집합으로, 데이터의 중복을 허용함 | Vector, ArrayList, LinkedList, Stack, Queue |
Set | 순서가 없는 데이터의 집합으로, 데이터의 중복을 허용하지 않음 | HashSet, TreeSet |
Map<K, V> | 키와 값의 한 쌍으로 이루어지는 데이터의 집합으로, 순서가 없음. 이때 키는 중복을 허용하지 않지만, 값은 중복될 수 있음 | HashMap, TreeMap, HashTable, Properties |
Collection Framework
데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓은 것입니다.
이러한 컬렉션 프레임워크는 인터페이스를 사용하여 구현되며 주요 인터페이스로는 List, Map, Set가 있습니다.
List는 순서가 있는 데이터 집합으로, 데이터의 중복을 허용합니다.
Set은 순서가 없는 데이터의 집합으로, 데이터의 중복을 허용하지 않습니다.
Map은 키와 값의 한 쌍으로 이루어지는 데이터의 집합으로, 순서가 없습니다. 이때 키는 중복을 허용하지 않지만, 값은 중복될 수 있습니다.
Integer num = new Integer(17); // 박싱
int n = num.intValue(); // 언박싱
System.out.println(n); // 출력 값: 17
Character ch = 'X'; // Character ch = new Character('X'); : 오토박싱
char c = ch; // char c = ch.charValue(); : 오토언박싱
System.out.println(c); // 출력 값: X
래퍼 클래스의 비교 연산도 오토언박싱을 통해 가능해지지만, 인스턴스에 저장된 값의 동등 여부 판단은 비교 연산자인 동등 연산자(==)를 사용해서는 안되며, equals() 메소드를 사용해야만 한다. 래퍼 클래스도 객체이므로 동등 연산자를 사용하게 되면, 두 인스턴스의 값을 비교하는 것이 아니라 두 인스턴스의 주소 값을 비교한다.
public class Wrapper03 {
public static void main(String[] args) {
Integer num1 = new Integer(10);
Integer num2 = new Integer(20);
Integer num3 = new Integer(10);
System.out.println(num1 < num2); // true
System.out.println(num1 == num3); // false
System.out.println(num1.equals(num3)); // true
}
}
Wrapper Class
기본 자료형에 대한 클래스 표현을 래퍼 클래스라고 합니다.
데이터를 전달받아 객체로 사용하며 컬렉션에서 제네릭을 사용하기 위해 사용합니다.
JVM : 자바 가상 머신의 약자를 따서 부르는 용어. (가상 머신이란 프로그램을 실행하기 위해 물리적 머신과 유사한 머신을 소프트웨어로 구현한 것) JVM의 역할은 자바 애플리케이션을 클래스 로더를 통해 읽어 들여 자바 API와 함께 실행하는 것이다. 그리고 JVM은 JAVA와 OS사이에서 중재자 역할을 수행하여 JAVA가 OS에 구애받지 않고 재사용을 가능하게 해준다. 그리고 가장 중요한 메모리 관리, Garbage collection을 수행한다. 그리고 JVM은 스택기반의 가상머신이다.
JVM 구조 중 메모리 구조
Java 소스 파일을 javac로 컴파일하여 class파일(Java 바이트 코드)을 생성 -> 클래스로더가 컴파일된 Java 바이트 코드를 런타임 데이터영역으로 로드함 -> 실행 엔진이 자바 바이트코드를 실행
https://asfirstalways.tistory.com/158
JVM, 실행 과정
JVM 은 자바 가상 머신의 약자로써 자바 애플리케이션을 클래스 로더를 통해 읽어 들여 자바 API와 함께 실행하는 역할을 합니다.
JVM을 사용하여 JAVA가 운영체제에 독립적으로 사용할 수 있게 하며 메모리 관리와 GC를 수행합니다.
JAVA의 실행과정은 자바 컴파일러를 통해 자바 소스코드를 .javac 읽어들여 자바 바이트코드.class를 생성합니다.
클래스 로더를 통해 class파일들을 JVM으로 로딩하여 런타임 데이터 영역에 로드합니다.
실행 엔진을 통해 실행이 됩니다.
가비지 컬렉션은 메모리를 정리하는 과정, 그렇기 때문에 일반적으로 메모리의 사용을 중단한 채로 진행이 되어야 한다, JVM은 GC를 실행하기 위해 애플리케이션의 실행을 멈추는 stop-the-world를 먼저 실행하게 된다. Stop-the-world를 실행하면 GC를 실행하는 쓰레드를 제외한 모든 쓰레드가 작업을 멈춘다, 그리고 GC가 끝나면 다시 작업을 재개, GC의 작업은 Young 영역에 대한 Minor GC와 Old영역에 대한 Major GC로 구분
Young 영역: 새롭게 생성한 객채들이 위치한다. 대부분의 객체는 금방 접근 불가능한 상태가 되기 때문에, 많은 객체가 Young 영역에 생성되었다가 사라진다.
Old 영역: Young 영역에서 계속 사용되어 살아남은 객체가 복사되는 영역, Young 영역보다 크게 할당되며, 더 적은 GC가 발생
가비지 컬렉션 알고리즘 종류(추후)
가비지 컬렉션에 의한 시스템 중단 시간을 줄이는 방법(추후)
https://mangkyu.tistory.com/94
Garbage Collector
C언어는 직접 메모리를 해제해줘야 하지만 자바는 JVM의 가비지 컬렉터가 메모리 자동으로 정리해줍니다
GC의 작업은 Young 영역에 대한 Minor GC와 Old영역에 대한 Major GC로 구분됩니다.
Young 영역은 새롭게 생성한 객체들이 위치하고 Old 영역은 Young 영역에서 계속 사용되어 살아남은 객체가 복사되는 영역입니다.
Annotation
어노테이션은 프로그램 실행과정에서 데이터를 어떻게 처리할 것인지 알려주는 서브 데이터라고 할 수 있습니다.
코드 문법의 에러체크와 코드 자동 생성 정보 제공,
런타임시 특정 기능을 실행하는 정보를 제공하기 위해 사용합니다.
String, StringBuffer,StringBuilder
String은 불변성을 가져서 변하지 않는 문자열을 자주 읽어들이거나, 문자열 연산이 적고 멀티쓰레드 환경일 경우 사용합니다.
StringBuffer와 StringBuilder는 가변성을 가져서 문자열 연산이 많을 때 사용합니다.
그렇지만 StringBuffer는 동기화를 지원하여서 멀티쓰레드 환경일 경우 사용하고
StringBuilder는 동기화를 지원하지 않아서 단일쓰레이거나 동기화를 고려하지 않아도 되는 경우에 사용합니다.
final 키워드
final 키워드는 변수나 메서드 또는 클래스가 변경 불가능하도록 만드는 것입니다.
final 키워드를 사용하면 변수의 값을 변경할 수 없고 메소드는 오버라이드 될 수 없으며 클래스는 상속될 수 없습니다.
예외
예외란 프로그램 실행 중에 발생할 수 있는 개발자가 구현한 로직에서 발생하는 문제입니다.
예외의 종류로는 컴파일 단계에서 확인되는 예외로 개발자가 반드시 명시적으로 처리해야하는 체크 예외가 있고
실행 단계에서 확인 되는 언체크 예외가 있습니다.
예외의 처리 방법으로는 try, catch 블록을 사용하는 것과 throw를 사용하는 것, catch에서 다른예외로 던지는 방법이 있습니다.
synchronized
여러 쓰레드가 사용중인 하나의 자원을 이용하고자 할 때 데이터에 접근할 수 없도록 막는 키워드 입니다.
메소드에서 사용하면 한 시점에 하나의 쓰레드만이 해당 메소드를 실핼할 수 있고
변수에서 사용하면 한 시점에 하나의 쓰레드만이 해당 변수를 참조할 수 있습니다.
java8 특징
함수형 프로그래밍을 위한 stream API 와 Lambda, 함수형 인터페이스와 Optional API가 추가 되었습니다.
Stream API
Java에서 함수형 프로그래밍을 할 수 있도록 해주는 API중 하나로
데이터를 추상화하고 처리하는데 자주 사용되는 함수들을 정의해 둔것입니다.
Stream API는 원본의 데이터를 변경하지 않고 일회용으로 사용하며 내부 반복으로 작업을 처리합니다.
장점으로는 코드를 간결하게 작성하여 가독성을 높일 수 있지만
단점으로 코드들이 추상화되어 있어 실수가 발생할 수 있고 잘못 사용하면 오히려 성능이 떨어질 수 있습니다.
interface MyFunctionalInterface {
String test();
}
public class Lambda {
public static void main(String[] args) throws Throwable {
String str = "This is My String";
// Labmda Expression
MyFunctionalInterface fi = () -> str.replaceAll("\\s+", "");
System.out.println(fi.test()); }
}
람다식
함수를 하나의 식으로 표현한 것으로 익명함수의 한 종류라고 할 수 있습니다.
람다식을 사용하면 코드를 간결하게 작성할 수 있어 가독성이 높아지고 생산성이 높아집니다.
그러나 재사용이 불가하고 디버깅이 어려우며 람다식을 너무 남발하여 사용하면
코드가 지저분해질 수 있다는 단점이 있습니다.
Optional
null 또는 실제값을 value로 갖는 wrapper로 감싸서 NPE으로 부터 자유로워지기 위해 나온 래퍼 클래스입니다.
메소드의 결과가 null이 될 수 있으며, 클라이언트가 이 상황을 처리해야 할 때 사용하는 것이 좋습니다.
Optional API의 단말 연산에서는 orElse와 orElseGet함수가 있습니다.
orElse 는 null이든 아든 항상 호출되고 orElseGet은 null일때만 호출된다는 차이점이 있습니다.