개발 지식 기록/JAVA

[자바의 정석] 개인적인 정리글 (2주차)

엉망진창좌충우돌 2023. 8. 6. 19:17

지난 주에 공부했던 부분은 앞부분이라 아는 내용이 많았기에 수월하게 할 수 있었다.

그러나 이번주에 들어가는 부분은 처음 보는 내용도 많았고, 이해가 힘든 부분도 있었다. 지금도 잘 모르는 내용이 많다.

다회독 하기 위해 모르더라도 일단 끝까지 다 보긴 했으나 앞으로 계속해서 반복해서 읽어봐야 할 것 같다.

이번 주차 내용에는 여러 클래스와 그와 관련된 메서드가 많았는데 해당 내용은 다 적기엔 너무 많아서 제외하려고 한다.

(현재 따로 코딩테스트 공부 목적으로 메서드 정리하는 글을 쭉 올리려고 한다.)


Chapter 07

 

◎ 상속 : 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것.

새로 작성하고자 하는 클래스의 이름 뒤에 상속받고자 하는 클래스의 이름을 'extends'와 함께 작성

 

조상 클래스 :  부모(parent)클래스, 상위(super)클래스, 기반(base)클래스

자손 클래스 :  자식(child)클래스, 하위(sub)클래스, 파생된(derived) 클래스

 

생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.

자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.

(접근제어자가 private 또는 default인 멤버들은 상속되지 않는다기보다 상속은 받지만 자손 클래스로부터의 접근이 제한되는 것)

 

◎ 자손 클래스의 인스턴트를 생성하면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성된다.

 

◎ 상속 외에도 클래스를 재사용하는 방법

포함관계 : 한 클래스의 멤버 변수로 다른 클래스 타입의 참조변수를 선언하는 것.

 

◎ 상속 vs 포함관계

~은 ~이다. -> 상속관계

~은 ~을 가지고 있다. -> 포함관계

 

◎ 자바는 오직 단일 상속만을 허용

 

◎ Object 클래스는 모든 클래스의 조상

 

◎오버라이딩(overriding)

조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것.

오버라이딩 조선

- 이름이 같아야 한다.

- 매개변수가 같아야 한다.

-반환타입이 같아야 한다.

 

◎ 오버라이딩 할 때

1. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.

2. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.

3. 인스턴스메서드를 static 메서드로 또는 그 반대로 변경할 수 없다.

 

◎ 오버로딩 vs 오버라이딩

오버로딩 : 기존에 없는 새로운 메서드를 정의.

오버라이딩 : 상속받은 메서드의 내용을 변경하는 것.

 

◎ super / super()

super : 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수

사용법은 this와 유사

super() : this() 와 마찬가지로 생성자. 조상 클래스의 생성자를 호출하는데 사용. 

자손 클래스의 인스턴스를 생성할 때, 조상 클래스 멤버의 초기화 작업이 수행되어야 하기 때문에 자손 클래스의 생성자에서 조상 클래스의 생성자가 호출되어야 한다. 생성자의 첫 줄에서 조상 클래스의 생성자가 호출 되어야 하는데, 자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수도 있으므로 조상의 멤버들이 먼저 초기화 되어 있어야 하기 때문이다.

 

◎ Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에 생성자,this() 또는 super(),를 호출해야 한다. 그렇지 않으면 컴파일러가 자동적으로 super();를 생성자의 첫 줄에 삽입

 

◎ 패키지

클래스의 묶음. 패키지는 물리적으로 하나의 디렉토리이다.

- 하나의 소스 파일에는 첫 번째 문장으로 단 한번의 패키지 선언만을 허용한다.(대소문자 모두 허용하지만 소문자가 원칙)

(소스파일에서 주석과 공백을 제외한 첫 번째 문자이어야 한다.)

- 모든 클래스는 반드시 하나의 패키지에 속해야 한다.

- 패키지는 점(.)을 구분자로 하여 계층구조로 구성할 수 있다.

- 패키지는 물리적으로 클래스 파일(.class)을 포함하는 하나의 디렉토리이다.

 

◎ import 문

사용할 클래스가 속한 패키지를 지정하는데 사용. import 문을 사용하면 클래스를 사용할 때 패키지명을 생략할 수 있음.

 

◎ import 시 클래스 이름 대신 '*' 사용하는 것은 컴파일에 영향은 있으나 실행 시 성능상의 차이는 없다.

 

◎ static import 문을 사용하면 static 멤버를 호출할 때 클래스 이름 생략할 수 있음

ex) import static java.lang.Math.random; 을 쓰면 System.out.println(Math.random()); 대신 out.println(random());으로 사용가능

 

◎ 제어자(modifier)

- 클래스, 변수, 메서드의 선언부에 사용

- 제어자는 크게 접근 제어자와 그외의 제어자로 나뉜다.

접근 제어자 : public, protected, default, private

그 외 :  static, final, abstract, native, transient, sychronized, volatile, strictfp

- 하나의 대상에 여러 개의 제어자를 조합해서 사용할 수 있으나, 접근제어자는 단 하나만 사용할 수 있다.

 

◎ static

- '클래스의' ,' 공통적인'

- static이 사용될 수 있는 곳 : 멤버변수, 메서드, 초기화 블럭

제어자 대상 의미
static 멤버변수 - 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다.
- 클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다.
- 클래스가 메모리에 로드될 때 생성된다.
메서드 - 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
- static메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다.

 

◎ final

- final이 사용될 수 있는 곳 : 클래스, 메서드, 멤버변수, 지역변수

제어자 대상 의미
final 클래스 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.
그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
메서드 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
멤버변수 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.
지역변수

 

◎ final이 붙은 변수는 상수이므로 보통은 선언과 초기화를 동시에 한다.

인스턴스마다 고정값을 갖는 인스턴스 변수의 경우 생성자에서 초기화 한다.

 

◎ abstract

- abstract가 사용될 수 있는 곳 : 클래스, 메서드

제어자 대상 의미
abstract 클래스 클래스 내에 추상메서드가 선언되어 있음을 의미한다.
메서드 선언부만 작성하고 구현부는 작성하지 않은 추상메서드임을 알린다.

 

◎ 접근 제어자

- 접근 제어자가 사용될 수 있는 곳 : 클래스, 멤버변수, 메서드, 생성자

private - 같은 클래스 내에서만 접근 가능

default - 같은 패키지 내에서만 접근 가능

protected - 같은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근 가능

public - 접근 제한 없음

 

◎ 접근 제어자 사용 이유

- 외부로부터 데이터 보호

- 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해

 

◎ 하나의 소스파일에는 public 클래스가 단 하나만 존재할 수 있으며, 소스파일의 이름은 반드시 public 클래스의 이름과 같아야 한다.

 

◎ 생성자의 접근 제어자를 private으로 생성하면 외부에서 인스턴스를 생성할 수 없게 된다. 대신 인스턴스를 생성해서 반환해주는 public 메서드를 제공하여 외부에서 인스턴스를 사용할 수 있도록 할 수 있다.(인스턴스 생성하지 않고 호출할 수 있어야 하므로 static 이어야 한다.)

 

◎ 제어자의 조합

대상 사용가능한 제어자
클래스 public, (default), final, abstract
메서드 모든 접근 제어자, final, abstract, static
멤버변수 모든 접근 제어자, final, static
지역변수 final

1. 메서드에 static과 abstract를 함께 사용할 수 없다.

- static은 구현부가 있는 메서드에만 사용할 수 있기 때문.

2. 클래스에 abstract와 final을 동시에 사용할 수 없다.

- 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미. abstract는 상속을 통해 완성되어야 하기에 서로 모순

3. abstract 메서드의 접근제어자가 private일 수 없다.

- abstract 메서드는 자손 클래스에서 구현되어야 하는데 접근 제어자가 private이면, 자손 클래스에서 접근할 수 없음

4. 메서드에 private과 final을 같이 사용할 필요는 없다.

- 접근 제어자가 private인 메서드는 오버라이딩 될 수 없음. 둘 중 하나만 사용해도 의미가 충분하다.

 

◎ 다형성

- 여러 가지 형태를 가질 수 있는 능력

- 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 함

 

◎ 조상 타입의 참조변수로 자손 타입의 인스턴스를 참조할 수 있지만, 반대로 자손 타입의 참조변수로 조상 타입의 인스턴스를 참조할 수는 없다.

 

◎ 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.

 

◎ 참조변수의 형변환

- 참조변수도 서로 상속관계에 있는 클래스 사이에서 형변환 가능

자손타입 -> 조상타입 (Up-casting) : 형변환 생략가능

자손타입 <- 조상타입 (Down-casting) : 형변환 생략불가

 

◎ 형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니다. 참조변수의 형변환은 인스턴스에 아무런 영향을 미치지 않는다. 단지 참조변수의 형변환을 통해, 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 범위(개수)를 조절하는 것 뿐.

 

◎ 서로 상속관계에 있는 타입간 형변환은 양방향으로 자유롭게 수행될 수 있으나, 참조변수가 가리키는 인스턴스의 자손타입으로의 형변환은 허용되지 않는다.(참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요)

 

◎ instanceof

- 참조변수가 참조하는 인스턴스의 실제 타입을 체크하는데 사용

- instanceof 왼쪽에는 참조변수를 오른쪽에는 타입(클래스명)이 피연산자로 위치

- true면 해당 타입으로 형변환이 가능

 

◎ 멤버변수가 중복 정의된 경우, 참조변수의 타입에 따라 연결되는 멤버변수가 다르다. (메서드는 참조변수 타입에 관계없이 항상 실제 인스턴스 타입에 정의된 메서드 호출)

- 조상 타입의 참조변수를 사용했을 때는 조상 클래스에 선언된 멤버변수가 사용, 자손 타입의 참조변수를 사용했을 때는 자손 클래스에 선언된 멤버변수가 사용.

 

◎ 매개변수의 다형성

- 참조형 매개변수는 메서드 호출 시, 자신과 같은 타입 또는 자손 타입의 인스턴스를 넘겨줄 수 있다.

 

◎ 조상 타입의 배열에 자손들의 객체를 담을 수 있다.

 

◎ 추상클래스

ex ) abstract class 클래스이름{ };

- 추상 메서드(미완성 메서드)를 포함하고 있는 클래스

- 인스턴스 생성 불가

- 상속을 통해 자손클래스에 의해서만 완성될 수 있음

 

◎ 추상메서드

ex ) abstract 리턴타입 메서드이름( );

- 선언부만 있고 구변부가 없는 메서드

- 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우 사용

- 추상클래스를 상속받는 자손클래스에서 추상메서드의 구현부를 완성해야 한다.

 

◎ 추상클래스의 작성

- 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존클래스의 공통 부분을 뽑아서 추상클래스를 만든다.

 

추상화 : 클래스 간의 공통점을 찾아내서 공통의 조상을 만드는 작업

구체화 : 상속을 통해 클래스를 구현, 확장하는 작업

 

◎ 인터페이스(interface)

- 일종의 추상클래스. 추상클래스보다 추상화 정도가 높아서 몸통을 갖춘 일반메서드 또는 멤버변수를 구성원으로 가질 수 없다.

- 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외의 다른 어떠한 요소도 허용하지 않는다.

- 인스턴스 생성 불가

 

interface 인터페이스 이름{
	public static final 타입 상수이름 = 값;
	public abstract 메서드이름(매개변수목록);
}

-모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.

- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.

 

◎ 인터페이스도 클래스처럼 상속 가능(인터페이스는 다중 상속 허용)

- 인터페이스는 Object 클래스와 같은 최고 조상이 없다.

 

◎인터페이스의 구현

- extends 대신 implements 사용

- 인터페이스에 정의된 추상메서드 완성해야 한다.

- 상속과 구현이 동시에 가능하다.

 

◎ 인터페이스 이름에는 able로 끝나는 것들이 많은데, 어떠한 기능 또는 행위를 하는데 필요한 메서드를 제공한다는 의미 강조. 

 

◎ 인터페이스를 이용한 다중상속(실제로 구현하는 일 거의 없음)

- 인터페이스는 static 상수만 정의할 수 있으므로 조상클래스의 멤버변수와 충돌하는 경우는 거의 없고 충돌된다 하더라도 클래스 이름을 붙여서 구분이 가능하다. 추상메서드는 구현 내용이 전혀 없으므로 조상클래스의 메서드와 선언부가 일치하는 경우에는 당연히 조상 클래스 쪽의 메서드를 상속받으면 되므로 문제되지 않는다.

 

◎ 인터페이스를 이용한 다형성

- 인터페이스 타입의 변수로 인터페이스를 구현한 클래스의 인스턴스를 참조할 수 있다.

- 인터페이스를 메서드의 매개변수 타입으로 지정할 수 있다.

- 인터페이스를 메서드의 리턴타입으로 지정할 수 있다.

 

◎ 인터페이스의 장점

- 개발시간을 단축시킬 수 있다.

- 표준화가 가능하다.

- 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.

- 독립적인 프로그래밍이 가능하다.

 

◎ 인터페이스는

- 두 대상(객체) 간의 '연결, 대화, 소통'을 돕는 '중간역할'을 한다.

- 선언(설계)와 구현을 분리시키는 것을 가능하게 한다.

 

◎ 인터페이스의 이해

- 클래스를 사용하는 쪽(User)와 클래스를 제공하는 쪽(Provider)이 있다.

- 메서드를 사용(호출)하는 쪽(User)에서는 사용하려는 메서드의 선언부만 알면 된다.

 

◎ 디폴트 메서드

- 인터페이스에 새로운 메서드를 추가하려면 이 인터페이스를 구현한 모든 클래스가 이 메서드를 구현해야 한다.

- 그래서 디폴트 메서드를 만들었다.

- 디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드로, 추상 메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.몸통{ }을 가지고 있으며, 앞에 'default'를 붙이고 항상 public 이다.(생략가능)

 

1. 여러 인터페이스의 디폴트 메서드 간의 충돌

- 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 한다.

2. 디폴트 메서드와 조상 클래스의 메서드 간의 충돌

- 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

 

◎ 내부 클래스

- 클래스 안에 선언된 클래스

- 특정 클래스 내에서만 주로 사용되는 클래스를 내부클래스로 선언

장점

1. 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.

2. 코드의 복잡성을 줄일 수 있다.(캡슐화)

 

◎ 내부 클래스의 종류와 특징

내부 클래스 특징
인스턴스 클래스 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 인스턴트멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적으로 선언된다.
static 클래스 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static메서드에서 사용될 목적으로 선언된다.
지역 클래스 외부 클래스의 메서드나 초기화 블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다.
익명 클래스 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용)

 

- 내부 클래스의 접근제어자는 변수에 사용할 수 있는 접근제어자와 동일

- static 클래스만 static 멤버를 정의할 수 있다.

(final과 static이 동시에 붙은 변수는 상수이므로 모든 내부 클래스에서 정의가 가능하다.)

- 내부 클래스도 외부 클래스의 멤버로 간주되며, 동일한 접근성을 갖는다.

- 외부 클래스의 지역변수는 final이 붙은 변수(상수)만 접근 가능하다.

- 지역 클래스의 인스턴스가 소멸된 지역변수를 참조할 수 있기 때문

 

◎ 익명클래스

- 이름 없는 일회용 클래스. 선언과 생성을 동시에. 하나의 객체만 생성가능

 

Chapter 08

◎ 프로그램 오류

- 컴파일 에러 : 컴파일 시에 발생하는 에러

- 런타임 에러 : 실행 시에 발생하는 에러

- 논리적 에러 : 실행은 되지만, 의도와 다르게 동작하는 것

 

- 에러 : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류

- 예외 : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류

 

◎ 예외 클래스는 두 그룹으로 나눌 수 있음

1. Exception 클래스와 그 자손들 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외 - 예외처리 필수

2. RuntimeException 클래스와 그 자손들 : 프로그래머의 실수로 발생하는 예외 - 예외처리 선택

 

◎ 예외처리

- 정의 : 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성하는 것.

- 목적 : 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것.

 

◎ try-catch문 사용 시 일치하는 catch블럭을 찾게 되면, 그 catch블럭 내 문장들을 수행하고 전체 try-catch문을 빠져나가서 그 다음 문장을 계속해서 수행

 

◎ 예외 발생시키기

1. 연산자 new를 이용해 발생시키려는 예외 클래스의 객체를 만든 다음

ex ) Exception e = new Exception("고의 에러");

2. throw를 이용해서 예외를 발생시킨다.

ex ) throw e;

(통합해서 throw new Exception("고의 에러"); 이렇게 가능)

 

◎ 예외의 최고 조상인 Exception을 처리하는 catch블럭은 모든 종류의 예외를 처리할 수 있다. 따라서 반드시 마지막 catch 블럭이어야 한다.

 

- printStackTrace() - 예외 발생 당시의 호출 스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력

- getMessage() - 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있음

 

◎멀티 catch 블럭에 사용되는 '|'는 논리 연산자가 아니라 기호이다.

 

◎ finally 블럭은 try 또는 catch문에서 return문을 만나도 수행된다.

 

◎ 메서드에 예외 선언하기

- 호출한 메서드로 전달해주는 것

- 호출한 메서드에서 예외처리를 해야만 할 때 사용

void method() throws Exception1, Exception2,...ExceptionN{
	//메서드 내용
}

 

◎ 메서드에 예외를 선언할 때 일반적으로 RuntimeException클래스들은 적지 않는다. 보통 반드시 처리해주어야 하는 예외들만 선언

 

◎ 자동 자원 반환 try - with - resources문

try(FileInputStream fis = new FileInputStream("score.dat");//괄호안에 두문장 이상인 경우 ;로 구분
	DataInputStream dis = new DataInpurStream(fis)){


} catch(IOExceptions ie){

}

}
//이런 식으로 괄호 안에 객체를 생성하는 문장을 넣으면 이 객체는 따로 close()하지 않아도 try블럭을
//벗어나는 순간 자동적으로 close() 된다.

 

◎ 예외 되던지기(re-throwing)

- 예외를 처리한 후에 다시 예외를 생성해서 호출한 메서드로 전달하는 것

- 예외가 발생한 메서드와 호출한 메서드, 양쪽에서 예외를 처리해야 하는 경우에 사용

 

◎ 사용자 정의 예외

- 기존 예외 클래스를 상속받아서 새로운 예외 클래스를 정의할 수 있다.

 

◎ 연결된 예외

- 예외 A가 예외 B를 발생시켰을 때, A를 B의 '원인 예외'라고 한다.

Throwable initCause(Throwable cause) 지정한 예외를 원인 예외로 등록

Throwable getCause() 원인 예외를 반환

 

◎ 발생한 예외를 그냥 처리하지 않고 원인 예외로 등록해서 다시 예외를 발생시키는 이유

1. SpaceException, MemoryException은 모두 설치 시 발생하는 예외이므로 InstallException(큰 분류의 예외)로 묶어서 처리하는 것이 편이할 때가 있음.

2. 필수 예외(Exception 자손)를 선택 예외(RuntimeException)로 바꿀 때

 

Chapter 09

◎ Object 클래스

- 모든 클래스의 최고 조상. 오직 11개의 메서드만 가지고 있다.

- notify(), notifyAll(), wait()는 쓰레드와 관련된 메서드

- equals(), hashCode(), toString()은 적절히 오버라이딩해야 한다.

 

◎ Object 클래스에 정의된 equals()는 참조변수 값(객체의 주소)을 비교한다.

 

◎ hashCode()

- 객체의 해시코드(int 타입의 정수)를 반환하는 메서드(해시함수)로 다량의 데이터를 저장&검색하는 해싱기법에 사용

- Object 클래스의 hashCode()는 객체의 내부 주소를 반환한다.

- equals()를 오버라이딩하면, hashCode()도 같이 오버라이딩 해야 한다.(equals()의 결과가 true인 두 객체의 hashCode는 같아야 한다.)

 

◎ toString()

- 객체의 정보를 문자열로 제공할 목적으로 정의된 메서드

 

◎ clone()

- Object 클래스에 정의된 clone()은 단순히 인스턴스변수의 값만 복사하기 때문에 참조타입의 인스턴스변수가 있는 클래스는 완전한 인스턴스 복제가 이루어지지 않는다.(얕은 복사)

 

◎ getClass()

- 자신이 속한 클래스의  Class객체를 반환하는 메서드

- Class객체는 클래스의 모든 정보를 담고 있으며, 클래스당 단 1개만 존재. 클래스파일이 메모리에 로드될 때 생성된다.

 

◎ 클래스 객체를 얻는 방법

Class cObj = new Card().getClass();
Class cObj = Card.class;
Class cObj = Class.forName("Card");

 

◎ String 클래스는 변경 불가능한 클래스

 

◎ 문자열 리터럴을 지정하여 만드는 방법은 기존에 존재하면 재사용한다.

String str1 = "abc";
String str2 = "abc";
//이미 str1 만들면서 abc 문자열 리터럴이 존재하므로 str2는 새로 만들지 않고
//기존 문자열 리터럴을 가리킨다.
//그래서 str1==str2하면 true 나온다.

 

◎ 자바 소스파일에 포함된 모든 문자열 리터럴은 컴파일 시에 클래스 파일에 저장된다. 이 때 같은 내용의 문자열 리터럴은 한번만 저장된다.

 

◎ String은 char형의 배열이지만 빈문자열 저장 가능하다.(길이가 0인 배열) 하지만 char 는 반드시 하나의 문자를 지정해야 한다.

 

◎ join()과 StringJoiner

join()은 여러 문자열 사이에 구분자를 넣어서 결합한다. StringJoiner클래스를 이용해 문자열 결합도 가능하다.

String animals = "dog,cat,bear";
String [] arr = animals.split(",");
String str = String.join("-",arr); // dog-cat-bear

StringJoiner sj = new StringJoinder(",","[","]");
String[] strArr = {"aaa", "bbb", "ccc"};
for(String s : strArr)
	sj.add(s.toUpperCase()); //[AAA,BBB,CCC]

 

◎ String.format()

- 형식화된 문자열 만들어 내는 방법. printf 와 사용법 동일

 

◎ 기본형을 String으로 변환

1. 빈 문자열 "" 더하기

2. valueOf() (이게 더 빠르다)

 

◎ 래퍼클래스는 내부적으로 기본형 변수를 가지고 있다.

 

◎ 값을 비교하도록 equals()가 오버라이딩 되어 있다.

 

◎ 래퍼클래스는 비교연산자 사용 불가. 대신 compareTo() 제공

 

◎ 래퍼클래스는 toString()도 오버라이딩 되어 있어 문자열로 반환 가능

 

◎ Number 클래스의 BigInteger 는 long으로도 다룰 수 없는 큰 범위의 정수를, BigDecimal은 double로도 다룰 수 없는 큰 범위의 부동 소수점수를 처리하기 위한 것.

 

◎ 기본형을 래퍼클래스의 객체로 자동 변환해주는 것을 '오토박싱', 반대로 변환하는 것을 '언박싱'이라 한다.

 

◎ StringTokenizer 클래스는 문자열을 지정된 구분자를 기준으로 토큰이라는 여러 개의 문자열로 잘라내는 데 사용

 

◎ StringTokenizer 메서드

 - countTokens() : 전체 토큰 수 반환

- hasMoreTokens() : 토큰이 남아있는지 알려준다.

- nextToken() : 다음 토큰을 반환한다.

 

Chapter 10

chapter 10은 전체가 날짜&시간&형식화 관련 클래스와 메서드의 소개라 정리글에서는 제외하려고 합니다. 쓰다 보면 책을 거의 다 옮겨야 할 것 같아서...

 

Chapter 11

◎ 컬렉션 프레임워크

- 컬렉션(다수의 객체)을 다루기 위한 표준화된 프로그래밍 방식

- 컬렉션을 쉽고 편리하게 다룰 수 있는 다양한 클래스를 제공

 

◎ 컬렉션 프레임워크의 핵심 인터페이스

인터페이스 특징
List 순서가 있는 데이터의 집합. 데이터의 중복을 허용한다.
구현클래스 : ArrayList, LinkedList, Stack, Vector 등
Set 순서를 유지하지 않는 데이터의 집합, 데이터의 중복을 허용하지 않는다.
구현 클래스 : HashSet, TreeSet 등
Map 키(key)와 값(value)의 쌍(pair)으로 이루어진 데이터의 집합. 순서는 유지되지 않으며, 키는 중복을 허용하지 않고, 값는 중복을 허용한다.
구현 클래스 : HashMap, TreeMap, Hashtable, Properties 등

(Vector나 Hashtable과 같은 기존의 컬렉션 클래스들은 호환을 위해 남아있지만, 가급적 사용하지 않는 것이 좋다. ArrayList와 HashMap을 이용하자)

 

(컬렉션 프레임워크의 메서드는 현재 따로 정리 중인 메서드 정리 글에서 정리할 계획입니다.)

 

◎ ArrayList

- ArrayList 는 Vector를 개선한 것. 구현 원리와 기능적으로 동일. Vector는 자체적으로 동기화처리가 되어있으나 ArrayList는 그렇지 않다.

- List니까 저장순서가 유지되고 중복 허용

- 데이터의 저장공간으로 배열을 사용

 

◎ 삭제 시 아래의 데이터를 한 칸씩 위로 복사해서 삭제할 데이터를 덮어쓴다.

 

◎ ArrayList 의 장단점

장점 :  배열은 구조가 간단하고 데이터를 읽는 데 걸리는 시간이 짧다.

단점 : 1. 크기를 변경할 수 없다. 크기를 변경하는 경우 새로운 배열 생성 후 데이터를 복사해야 함.

          2. 비순차적인 데이터의 추가, 삭제에 시간이 많이 걸린다. ( 순차적인 데이터 추가/삭제(끝에 추가/삭제)는 빠르다.)

 

◎ LinkedList - 배열의 단점을 보완

- 불연속적으로 존재하는 데이터를 연결

- 데이터의 삭제 : 단 한 번의 참조변경으로 가능

- 데이터의 추가 : 한번의 Node 객체 생성과 두 번의 참조변경으로 가능

- 데이터가 많을수록 접근성이 떨어짐

 

◎ 이중 연결 리스트

- Linked List - 연결리스트. 데이터 접근성이 나쁨

- Doubly Linked List - 이중 연결 리스트, 접근성 향상

- Doubly Circular Linked List - 이중 원형 연결리스트

 

◎ ArrayList vs LinkedList

1. 순차적으로 데이터를 추가/삭제 - ArrayList가 빠름

2. 비순차적으로 데이터를 추가/삭제 - LinkedList가 빠름

3. 접근시간(access time) - ArrayList가 빠름

 

◎ Enumeration, Iterator,  ListIterator

- 컬렉션에 저장된 데이터를 접근하는데 사용되는 인터페이스

- Enumeration은 Iterator의 구버전

- ListIterator는 Iterator의 접근성을 향상시킨 것.(단방향 -> 양방향)

 

◎ Arrays

- 배열의 출력 : toString(), deepToString()

- 배열의 비교 : equals(), deepEquals()

- 배열의 복사 : copyOf(), copyOfRange()

- 배열 채우기 : fill(), setAll()

- 배열의 정렬과 검색 : sort(), binarySearch()

- 배열을 List로 변환 : asList()

 

◎ Comparator & Comparable

- 객체를 정렬하는데 필요한 메서드를 정의한 인터페이스(정렬기준을 제공)

Comparable : 기본 정렬기준을 구현하는데 사용

Comparator : 기본 정렬기준 외에 다른 기준으로 정렬하고자할 때 사용

 

◎ 정렬 시 String.CASE_INSENSITIVE_ORDER 는 대소문자 구분없이 정렬

 

◎ Set은 저중 순서 유지 X . 순서 유지하려면 LinkedHashSet클래스 사용

 

◎ TreeSet은 범위 검색과 정렬에 유리. HashSet보다 데이터 추가, 삭제가 오래 걸림

- 이진 검색 트리로 구현

- 모든 노드가 최대 두 개의 하위 노드를 갖음

- 부모보다 작은 값을 왼쪽에, 큰 값은 오른쪽에 저장

 

◎ HashMap 저장 순서 유지X, 순서를 유지하려면 LinkedHashMap클래스 사용

 

◎ TreeMap은 범위 검색과 정렬에 유리, HashMap보다 데이터 추가, 삭제에 시간이 더 걸림

- 이진 검색 트리의 구조로 기와 값의 쌍으로 이루어진 데이터를 저장

- TreeSet처럼 데이터를 정렬해서 저장하기 때문에 저장시간이 길다.

- 다수의 데이터에서 개별적인 검색은 TreeMap보다 HashMap이 빠르다.

- Map이 필요할 때 주로 HashMap을 사용하고, 정렬이나 범위검색이 필요한 경우에 TreeMap 사용

 

◎ Properties

- 내부적으로 Hashtable을 사용. key와 value를 String,String으로 저장.

- 주로 어플리케이션의 환경설정에 관련된 속성을 저장하는데 사용

 

◎ 

컬렉션의 동기화 : sychronized 사용

변경불가 컬렉션 : unmodified 사용

싱글톤 컬렉션 : singleton 사용

한 종류의 객체만 저장하는 컬렉션 : checked 사용

 

Chapter 12

◎ 지네릭스(Generics)

- 컴파일 시 타입을 체크해 주는 기능

- 객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌

 

◎ 지네릭 클래스의 선언

- 클래스를 작성할 때, Object 타입 대신 T와 같은 타입변수를 사용

- 참조변수, 생성자에 T대신 실제 타입을 지정하면 형변환 생략가능

 

◎ 지네릭 클래스 제약사항

- static 멤버에는 타입 변수 T를 사용할 수 없다.

- 지네릭 타입의 배열 T[]를 생성하는 것은 허용되지 않는다.

 

◎ 지네릭 타입에 'extends'를 사용하면 특정 타입의 자손들만 대입할 수 있게 제한할 수 있다.

- 인터페이스의 경우에도 'implement'가 아닌 'extends' 사용

 

◎ 와일드 카드 ?

- 지네릭 타입에 와일드 카드를 쓰면, 여러 타입을 대입 가능

- 단, 와일드 카드에는 <? extends T & E>와 같이 '&' 사용 불가

 

◎ 지네릭 메서드

- 반환타입 앞에 지네릭 타입이 선언된 메서드

- 클래스의 타입 매개변수<T>와 메서드의 타입 매개변수 <T>는 별개

- 지네릭 메서드를 호출할 때, 타입 변수에 타입을 대입해야 한다.(대부분의 경우 추정 가능하므로 생략할 수 있음)

 

◎ 지네릭 타입의 형변환

- 지네릭 타입과 원시 타입간 형변환은 불가능

- 와일드 카드가 사용된 지네릭 타입으로는 형변환 가능

- <? extends Object> 를 줄여서 <?>로 쓸 수 있다.

 

◎ 지네릭 타입의 제거

- 컴파일러는 지네릭 타입을 제거하고 필요한 곳에 형변환을 넣는다.

 

◎ 열거형 (Enum)

- 관련된 상수들을 같이 묶어 놓은 것.

 

◎ 열거형 정의한느 방법

- enum 열거형이름 { 상수명1, 상수명2,...}

 

◎ 열거형 타입의 변수 선언 및 사용법

enum Direction { EAST,SOUTH,WEST,NORTH}
class Unit{
	int x,y
    	Direction dir;
        
    void init() {
    	dir = Direction.EAST;
    }
}

 

◎ 열거형 상수의 비교에 ==와 compareTo() 사용 가능

 

◎ 추가할 때, 불연속적인 열거형 상수의 경우 원하는 값을 괄호() 안에 적는다.

enum Direction {
	EAST(1), SOUTH(5), WEST(-1), NORTH(10);//끝에 ';'추가
	
    private final int value;
	Direction(int value) { this.value = value;}
    
    public int getValue() { return value;}
}

 

◎ 열거형의 생성자는 묵시적으로 private이므로, 외부에서 객체 생성 불가

 

◎ 애너테이션(Annotation)

- 주석처럼 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공

 

◎ @Override

- 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다.

 

◎ @Deprecated

- 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다.

 

◎ @FunctionalInterface

- 함수형 인터페이스에 붙이면, 컴파일러가 올바르게 작성했는지 체크

 

◎ @SuppressWarnings

- 컴파일러의 경고 메시지가 나타나지 않게 억제

- 괄호() 안에 억제하고자 하는 경고의 종류를 문자열로 지정

ex ) @SuppressWarnings({"deprecation","unchecked","varargs"})

 

◎ @SafeVarargs

- 가변인자의 타입이 non-reifiable인 경우 발생하는 uncheck 경고를 억제

- 생성자 또는 static이나 final이 붙은 메서드에만 붙일 수 있음 ( 오버라이딩이 가능한 메서드에 사용 불가)

- @SafeVarargas에 의한 경고의 억제를 위해 @SuppressWarnings 사용

 

◎ @Target

- 애너테이션을 정의할 때, 적용대상이나 유지기간의 지정에 사용

 

◎ @Retention

- 애너테이션이 유지되는 기간을 지정하는데 사용

유지 정책 의미
SOURCE 소스 파일에만 존재. 클래스 파일에는 존재하지 않음.
CLASS 클래스 파일에 존재. 실행시에 사용불가. 기본값
RUNTIME 클래스 파일에 존재. 실행시에 사용가능

 

◎ @Documented, @Inherited

- javadoc으로 작성한 문서 포함시키려면 @Documented 붙인다.

- 애너테이션을 자손 클래스에 상속하고자 할 때, @Inherited 붙인다.

 

◎ @Repeatable

- 반복해서 붙일 수 있는 애너테이션을 정의할 때 사용

 

◎ @Native

- native 메서드에 의해 참조되는 상수에 붙이는 애너테이션

 

◎ 애너테이션 타입 정의하기

- 애너테이션을 직접 만들 수 있음

- 애너테이션의 메서드는 추상메서드이며, 애너테이션을 적용할 때 모두 지정해야 한다.

 

◎ 애너테이션 요소 기본값

- 적용 시 값을 지정하지 않으면, 사용될 수 있는 기본값 지정 가능(null 제외)

- 요소의 이름이 value인 경우 생략할 수 있다.

- 요소의 타입이 배열인 경우, 괄호{} 를 사용해야 한다.

 

◎ java.lang.annotation.Annotation

- Annotation은 모든 애너테이션의 조상이지만 상속 불가

- 인터페이스로 정의되어 있음

 

◎ Marker Annotation

- 요소가 하나도 정의되지 않은 애너테이션

 

◎ 애너테이션 요소의 규칙

- 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용됨

- 괄호() 안에 매개변수를 선언할 수 없다.

- 예외를 선언할 수 없다.

- 요소를 타입 매개변수로 정의할 수 없다.

 

Chapter 13

(쓰레드 코드에 대한 이해가 부족하여 기록할 내용이 부족합니다ㅠㅠ)

 

◎ 쓰레드의 구현

1. Thread 클래스를 상속

2. Runnable 인터페이스를 구현

 

◎ 쓰레드의 우선순위

- 작업 중요도에 따라 쓰레드의 우선순위를 다르게 하여 특정 쓰레드가 더 많은 작업시간을 갖게 할 수 있다.

 

◎ 쓰레드 그룹

- 서로 관련된 쓰레드를 그룹으로 묶어서 다루기 위한 것(보안 상의 이유)

- 모든 쓰레드는 반드시 하나의 쓰레드 그룹에 포함되어 있어야 한다.

- 쓰레드 그룹을 지정하지 않고 생성한 쓰레드는 'main쓰레드 그룹'에 속한다.

- 자신을 생성한 쓰레드(부모 쓰레드)의 그룹과 우선순위를 상속받는다.

 

◎ 데몬쓰레드

- 일반 쓰레드의 작업을 돕는 보조적인 역할 수행

- 일반 쓰레드가 모두 종료되면 자동적으로 종료된다.

- 가비지 컬렉터, 자동저장, 화면자동갱신 등에 사용된다.

- 무한 루프와 조건문을 이용해서 실행 후 대기하다 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성

 

boolean isDaemon() - 쓰레드가 데몬쓰레드인지 확인한다. 데몬쓰레드이면 true를 반환

void setDaemon(boolean on) - 쓰레드를 데몬 쓰레드로 또는 사용자 쓰레드로 변경. 매개변수 on을 true로 지정하면 데몬쓰레드가 된다.

- setDaemon(boolean on)은 반드시 start()를 호출하기 전에 실행되어야 한다.

 

◎ 쓰레드의 실행제어

메서드 설명
static void sleep(long millis)
static void sleep(longmillis, int nanos)
지정된 시간(천분의 일초 단위)동안 쓰레드를 일시정지시킨다. 지정한 시간이 지나고 나면, 자동적으로 다시 실행대기상태가 된다.
void join()
void join(long millis)
void join(long millis, int nanos)
지정된 시간동안 쓰레드가 실행되도록 한다. 지정된 시간이 지나거나 작업이 종료되면 join()을 호출한 쓰레드로 다시 돌아와 실행을 계속한다.
void interrupt() sleep()이나 join()에 의해 일시정지 상태인 쓰레드를 깨워서 실행대기상태로 만든다. 해당 쓰레드에서는 InterruptedException이 발생함으로써 일시정지 상태를 벗어나게 된다.
void stop() 쓰레드를 즉시 종료시킨다.
void suspend() 쓰레드를 일시정지시킨다. resume()을 호출하면 다시 실행대기상태가 된다.
void resume() suspend()에 의해 일시정지상태에 있는 쓰레드를 실행대기상태로 만든다.
static void yield() 실행 중에 자신에게 주어진 실행시간을 다른 쓰레드에게 양보(yield)하고 자신은 실행대기상태가 된다.

 

◎ 쓰레드의 상태

상태 설명
NEW 쓰레드가 생성되고 아직 start()가 호출되지 않은 상태
RUNNABLE 실행 중 또는 실행 가능한 상태
BLOCKED 동기화 블럭에 의해서 일시정지된 상태(lock이 풀릴 때까지 기다리는 상태)
WAITING, TIMED_WAITING 쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은(unrunnable) 일시정지 상태. TIMED_WAITING은 일시정지시간이 지정된 경우를 의미한다.
TERMINATED 쓰레드의 작업이 종료된 상태

 

◎ 쓰레드의 동기화

- 한 번에 하나의 쓰레드만 객체에 접근할 수 있도록 객체에 락(lock)을 걸어서 데이터의 일관성을 유지하는 것

 

◎ wait(), notify(), notifyAll()

- 동기화의 효율을 높이기 위해 wait(), notify() 사용

- Object 클래스에 정의되어 있으며, 동기화 블록 내에서만 사용 가능

- wait() - 객체의 lock을 풀고 쓰레드를 해당 객체의 waiting pool에 넣는다

- notify() - waiting pool 에서 대기중인 쓰레드 중의 하나를 깨운다

- notifyAll() - waiting pool 에서 대기중인 모든 쓰레드를 깨운다.

 

◎ Lock 과 Condition

- ReentrantLock : 재진입이 가능한 lock. 가장 일반적인 배타 lock

- ReentrantReadWriteLock : 읽기에는 공유적이고, 쓰기에는 배타적인 Lock

- StampedLock : ReentrantReadWriteLock에 낙관적인 lock 기능을 추가

 

◎ 낙관적인 잠금 : 일단 무조건 저지르고 나중에 확인

 

◎ volatile - cache와 메모리 간 불일치 해소

- 성능 향상을 위해 변수의 값을 core의 cache에 저장해 놓고 작업

- 여러 쓰레드가 공유하는 변수에는 volatile을 붙여야 항상 메모리에서 읽어온다.

 

◎ join & fork 프레임워크

- 작업을 여러 쓰레드가 나눠서 처리하는 것을 쉽게 해준다.

- RecursiveAction(반환값이 없는 작업을 구현할 때 사용) 또는 RecursiveTask(반환값이 있는 작업을 구현할 때 사용) 를 상속받아서 구현

 

◎ 작업 훔치기(work stealing)

- 작업을 나눠서 다른 쓰레드의 작업 큐에 넣는 것

 

◎ fork()와 join()

- compute()는 작업을 나누고, fork()는 작업을 큐에 넣는다.(반복)

- join()으로 작업의 결과를 합친다.(반복)

fork() : 해당 작업을 쓰레드 풀의 작업 큐에 넣는다. 비동기 메서드

join() : 해당 작업의 수행이 끝날 때까지 기다렸다가, 수행이 끝나면 그 결과를 반환한다. 동기 메서드

 

Chapter 14

◎ 람다식(Lambda Expression)

- 함수를 간단한 식으로 표현하는 방법

- 익명함수

 

◎ 람다식 작성

1. 메서드의 이름과 반환타입 제거하고 ->를 블록{} 앞에 추가한다.

2. 반환값이 있는 경우, 식이나 값만 적고 return문 생략 가능(끝에 ';' 안 붙임)

3. 매개변수의 타입이 추론 가능하면 생략가능(대부분의 경우 생략 가능)

 

◎ 주의사항

1. 매개변수가 하나인 경우, 괄호() 생략가능(타입 없을 경우만)

2. 블록 안의 문장이 하나뿐 일 때, 괄호{} 생략가능(끝에 ';' 안붙임) 단, 하나뿐인 문장이 return문이면 괄호{} 생략불가

 

◎ 람다식은 익명 함수X 익명 객체 O

 

◎ 함수형 인터페이스

- 단 하나의 추상 메서드만 선언된 인터페이스

- 함수형 인터페이스 타입의 참조변수로 람다식을 참조할 수 있음(함수형 인터페이스의 메서드와 람다식의 매개변수 개수와 반환타입이 일치해야 함.)

 

◎ function 타입의 두 람다식을 하나로 합성

- andThen()

- compose()

 

◎ and(), or(), negate()로 두 Predicate를 하나로 결합(default 메서드)

 

◎ 등가비교를 위한 Predicate 작성에는 isEquals()를 사용(static 메서드)

 

◎ 메서드 참조

종류 람다식 메서드 참조
static 메서드 참조 (x) -> ClassName.method(x) ClassName::method
인스턴트 메서드 참조 (obj, x) -> obj.method(x) ClassName::method
특정 객체 인스턴스메서드 참조 (x) -> obj.mehtod(x) obj::method

 

◎ 스트림

- 다양한 데이터 소스를 표준화된 방법으로 다루기 위한 것

- 스트림이 제공하는 기능 : 중간 연산과 최종 연산

 

◎ 스트림의 특징

- 스트림은 데이터 소스로부터 데이터를 읽기만할 뿐 변경하지 않는다.

- 스트림은 Iterator처럼 일회용이다. (필요하면 스트림 재생성 해야함)

- 최종 연산 전까지 중간연산이 수행되지 않는다. (지연된 연산)

- 스트림은 작업을 내부 반복으로 처리한다.

- 스트림의 작업을 병렬로 처리 - 병렬스트림

- 기본형 스트림 : IntStream, LongStream, DoubleStream(오토박싱&언박싱 비효율이 제거됨, 숫자와 관련된 유용한 메서드 제공)

 

Chapter 15

◎ Stream

- 데이터를 운반(입출력)하는데 사용되는 연결통로

- 하나의 스트림으로 입출력을 동시에 수행할 수 없다.(단방향 통신)

- 입출력을 동시에 수행하려면, 2개의 스트림이 필요하다.

 

◎ 바이트 기반 스트림 - InputStream, OutputStream

- 데이터를 바이트(byte)단위로 주고 받는다.

 

◎ 보조스트림

- 스트림의 기능을 향상시키거나 새로운 기능을 추가하기 위해 사용

- 독립적으로 입출력을 수행할 수 없다.

 

◎ 문자기반 스트림 - Reader, Writer

- 입출력 단위가 문자(char, 2byte) 인 스트림. 문자기반 스트림의 최고 조상

 

◎ FileInputStream과 FileOutputStream

- 파일(file)에 데이터를 입출력하는 바이트 기반 스트림

 

◎ FilterInputStream & FilterOutputStream

- 모든 바이트기반 보조스트림의 최고조상

- 보조스트림은 자체적으로 입출력을 수행할 수 없다.

- 상속을 통해 FilterInputStream /FilterOutputStream 의read()와 write()를 원하는 기능대로 오버라이딩 해야 한다.

 

◎ BufferedInputStream & BufferedOutputStream

- 입출력 효율을 높이기 위해 버퍼를 사용하는 보조스트림

- 보조스트림을 닫으면 기반스트림도 닫힌다.

 

◎ DataInputStream & DataOutputStream

- 기본형 단위로 읽고 쓰는 보조스트림

- 각 자료형의 크기가 다르므로 출력할 때와 입력할 때 순서 주의

 

◎ SequenceInputStream

- 여러 입력스트림을 연결해서 하나의 스트림처럼 다룰 수 있게 해준다.

 

◎ PrintStream

- 데이터를 다양한 형식의 문자로 출력하는 기능을 제공하는 보조스트림

- System.out과 System.err이 PrintStream이다.

- PrintStream보다 PrintWriter를 사용이 권장된다.

 

◎ FileReader와 FileWriter

- 문자기반의 파일 입출력. 텍스트 파일의 입출력에 사용

 

◎ PipeReader와 PipeWriter

- 프로세스(쓰레드) 간의 통신(데이터를 주고 받음)에 사용

 

◎ StringReader와 StringWriter

- CharArrayReader, CharArrayWriter처럼 메모리의 입출력에 사용한다

- StringWriter에 출력되는 데이터는 내부의 StringBuffer에 저장된다.

 

◎ BufferedReader와 BufferedWriter

- 입출력 효율을 높이기 위해 버퍼를 사용하는 보조스트림

- 라인 단위의 입출력 편리

 

◎ InputStreamReader와 OutputStreamWriter

- 바이트 기반 스트림을 문자기반스트림처럼 쓸 수 있게 해준다.

- 인코딩을 변환하여 입출력할 수 있게 해준다.

 

◎ 표준입출력 - System.in, System.out, System.err

- 콘솔을 통한 데이터의 입출력

- JVM이 시작되면서 자동적으로 생성되는 스트림

 

◎ RandomAccessFile

- 하나의 스트림으로 파일에 입력과 출력을 모두 수행할 수 있는 스트림

- 다른 스트림들과 달리 Object의 자손이다.

 

◎ 직렬화(Serializable 구현해야 한다.transient가 붙은 인스턴스변수는 직렬화 제외. serializable 구현하지 않은 클래스의 인스턴스도 직렬화 제외)

- 객체를 '연속적인 데이터'로 변환하는 것. 반대는 역직렬화

- 객체의 인스턴스변수들의 값을 일렬로 나열하는 것

- 객체를 저장하기 위해서는 객체를 직렬화해야한다.

- 객체를 저장한다는 것은 객체의 모든 인스턴스 변수의 값을 저장하는 것

 

◎ ObjectInputStream, ObjectOutputStream

- 객체를 직렬화하여 입출력할 수 있게 해주는 보조스트림

 

◎ 직렬화 가능한 클래스의 버전관리

- 직렬화 했을 때와 역직렬화 했을 때 클래스가 같은지 확인 필요

- 직렬화 할 때, 클래스의 버전을 자동계산해서 저장한다.

- 클래스의 버전을 수동으로 관리하려면, 클래스 내에 정의해야 한다.

- serialver.exe 가 클래스의 serialVersionUID를 자동 생성해준다.

 

Chapter 16

◎ 클라이언트/ 서버

- 컴퓨터간의 관계를 역할로 구분

- 서비스 제공 : 서버 ,  제공받는 쪽 : 클라이언트

- 서비스 종류에 따라 메일서버, 파일서버, 웹서버 등이 있다.

- 전용 서버 두는 것을 '서버기반 모델' 각 클라이언트가 서버역할까지 수행하는 것을 'p2p모델'

서버기반 모델 p2p 모델
- 안정적인 서비스의 제공 가능
- 공유 데이터 관리와 보안이 용이
- 서버구축비용과 관리비용이 든다.
- 서버구축 및 운용 비용 절감
- 자원의 활용을 극대화 할 수 있다.
- 자원의 관리가 어렵다.
- 보안이 취약하다.

 

◎ IP주소

- 컴퓨터(host)를 구별하는데 사용되는 고유한 주소값

- 4byte의 정수로 'a.b.c.d' 형식으로 표현(0~255의 정수)

- IP주소는 네트워크주소와 호스트주소로 구성되어 있다.

- 네트워크주소가 같은 두 호스트는 같은 네트워크에 존재한다.

- IP주소와 서브넷 마스크를 & 연산하면 네트워크 주소를 얻는다.

 

◎ URL

- 인터넷에 존재하는 서버들의 자원에 접근할 수 있는 주소

 

◎ 소켓프로그래밍

- 소켓을 이용한 통신 프로그래밍

- 소켓 : 프로세스간의 통신에 사용되는 양쪽 끝단

- 프로세스간의 통신에서도 양쪽에 소켓이 필요

 

◎ TCP / UDP

- TCP/IP프로토콜에 포함된 프로토콜. OSI 7계층의 전송계층에 해당

 

◎ TCP 소켓 프로그래밍

- 클라이언트와 서버간의 1:1 소켓 통신

- 서버가 먼저 실행되어 클라이언트의 연결요청을 기다리고 있어야 한다.

1. 서버는 서버소켓을 사용해서 서버의 특정포트에서 클라이언트의 연결요청을 처리할 준비를 한다.

2. 클라이언트는 접속할 서버의 IP주소와 포트정보로 소켓을 생성해서 서버에 연결을 요청한다.

3. 서버소켓은 클라이언트의 연결요청을 받으면 서버에 새로운 소켓을 생성해서 클라이언트의 소켓과 연결되도록 한다.

4. 클라이언트의 소켓과 새로 생성된 서버의 소켓은 서버소켓과 관계없이 1:1 통신을 한다.

 

◎ 

Socket - 프로세스간의 통신을 담당. InputStream과 OutputStream을 가지고 있다. 이 두 스트림을 통해 프로세스 간의 통신(입출력)이 이루어진다.

ServerSocket - 포트와 연결되어 외부의 연결요청을 기다리다 연결요청이 들어오면, Socket을 생성해서 소켓과 소켓간의 통신이 이루어지도록 한다. 한 포트에 하나의 ServerSocket만 연결할 수 있다.(프로토콜이 다르면 같은 포트 공유 가능)

 

◎ UDP 소켓 프로그래밍

- DatagramSocket과 DatagramPacket을 사용

- UDP는 연결지향적이지 않으므로 연결요청을 받아줄 서버소켓이 필요없다.

- DatagramSocket간에 데이터(DatagramPacket)를 주고 받는다.

 

 

'개발 지식 기록 > JAVA' 카테고리의 다른 글

[메서드 정리] ArrayList  (0) 2023.08.13
[메서드 정리] StringBuffer & StringBuilder  (0) 2023.08.13
[메서드 정리] Math  (0) 2023.08.06
[메서드 정리] String  (0) 2023.08.06
[메서드 정리] Integer  (0) 2023.08.06