1. 자바를 시작하기 전에
* Java 의 특징
> OS 에 독립적 -> Write once, run anywhere
> Object-Oriented Language
> Garbage Collection
> Multi-Threading
> Dynamic Loading
: 필요한 시점에 클래스를 로딩하여 사용
* Java 의 단점
> 속도가 느리다
: Byte Code -> Machine Language
(이전보다는 JIT Compiler 와 Hot Spot 같은 기술로 인해 많이 향상 되었다)
* Java 프로그램의 실행 과정
> Hello.java -> (javac.exe) -> Hello.class -> (java.exe) -> 실행
* JDK/bin 에 있는 실행 파일들
> javac.exe
: 자바 컴파일러 (src -> byte code)
> java.exe
: 자바 인터프리터 (byte code 를 해석하고 실행)
> javap.exe
: 자바 역어셈블러 (byte code -> src)
> appletviewer.exe
: HTML 문서에 삽입되어 있는 애플릿을 실행
> javadoc.exe
: src 의 주석을 이용하여 API 문서와 같은 형식의 문서를 자동으로 생성
> jar.exe
: *.class 파일과 실행에 관련된 파일을 하나의 ajr 파일로 압축하거나 해제
* JDK 와 JRE
> JRE (Java Runtime Environment; 자바 실행 환경)
: JVM + Java API (Class Library)
> JDK (Java Development Kit; 자바 개발 도구)
: JRE + 개발에 필요한 파일 (javac.exe 등)
2. 변수
* Java 변수 타입
> Primitive Type
: 실제 data 를 저장
> Reference Type
: Object 의 Address 를 저장
* Auto boxing (>= JDK 1.5 )
> object class 와 wrapper class 간에 type casting 이 가능하다
* 자료형의 크기
> char (2byte)
: Unicode 를 사용
> byte (1byte)
* 문자형과 덧셈연산
> 문자열 + any type => 문자열 + 문자열 => 문자열
> any type + 문자열 => 문자열 + 문자열 => 문자열
* Type Casting
> boolean 을 제외한 7개의 기본형은 서로 Type Casting 이 가능하다
: byte, short, char, int, long, float, double)
> 표현 범위가 작은 자료형에서 큰 자료형으로 변환시에는 값 손실이 없으므로 Cast 연산자 생략이 가능하다
: char <-> short 는 모두 2byte 지만, char 는 unsigned 이므로 cast 연산자가 필요하다)
: 표현 범위 (from -> to)
- Large -> Small : 불가능
- Small -> Large (unsigned) : 불가능
- Same -> Same (unsigned) : 불가능
- Small -> Large : 가능
- Long -> float : 가능
(Long 은 8byte, Float 는 4byte 지만, float 의 표현 범위가 long 보다 크기 때문이다)
> 4byte 이하의 자료형끼리의 연산의 결과는 Integer 가 된다
: e.g. char + char = int
3. 연산자
* 증감 연산자
> ++, -- 등의 연산자를 사용하는 경우 type casting 이 발생하지 않는다
* 2개의 식에 대한 성능 비교 (++i vs i = i + 1)
> 컴파일 된 후에, 전자의 명령어가 훨씬 simple 하다
> ++i
: istore_1 -> iinc 1 1
> i = i + 1
: istore_1 -> iload_1 -> iconst_1 -> iadd -> istore_1
* 비트 전환 연산자 (~)
> char, int 형에만 사용 가능
* 산술 연산자
> 모든 이항 연산자는 연산을 수행하기 전에
- 크기가 4byte 이하인 자료형 (byte, char, short)을 int 형으로 변환한다 (But, literal & 상수 간의 연산에서는 값이 casting 되지 않는다)
- 피연산자들의 타입을 서로 일치시킨다
* 하루를 초로 나타내기 (86,400 vs 60 * 60 * 24)
> 2가지 식 모두 컴파일 시, 86,400 으로 변환되기 때문에 가독성 측면에서 후자가 더 좋다
* 쉬프트 연산자
- "<<"
: 빈칸을 0으로 채움
- ">>"
: 빈칸을 1로 채움 (부호 유지를 위해)
- ">>>"
: 빈칸을 0으로 채움
* 논리 연산자
> && 이 || 보다 우선순위가 높으므로 주의하여야 한다
4. 조건문과 반복문
* Label 붙은 반복문
Loop1 : for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
System.out.println( i + " " + j);
if (i * j == 16) {
break Loop1;
}
}
}
5. 배열
* 배열 선언
int[] arr1 = {1, 2, 3, };
int[] arr2 = new int[] {1, 2, 3, 4, 5}; // 크기 지정 불가
int[] arr3; // 크기 지정 불가
int[] arr4[]; // 2차원 배열
int[] arr5[] = new int[3][]; // 2차원 배열
* 가변 배열
int[][] score = new int[5][];
score[0] = new int[4];
score[1] = new int[3];
score[2] = new int[2];
6. 객체지향 프로그래밍1
* 객체 지향 언어
> 가장 큰 장점은 '코드의 재사용성이 높고 유지보수가 용이'하다는 것이다
- 재 사용성
- 유지보수
- 중복 제거
* Class Variable (Static)
> Program 이 실행되어 Class 가 Memory에 올라가면 할당되어 종료될 때 같이 소멸됨
* Return
> return 문을 여러 번 쓰는 것보다 method 마지막에 한 번만 사용하는 것이 좋다
* Member Variable 의 3가지 초기화 방법
1. Explicit initialization (기본적인 초기화 방법)
2. Constructor
3. Initialization Block (초기화 블럭)
public class Initialization {
static {
// 클래스 초기화 블럭 - 복잡한 초기화에 사용
}
{
// 인스턴스 초기화 블럭 - 복잡한 초기화에 사용
}
}
* this()
> 다른 생성자에서 호출할 때는 반드시 첫 줄에서만 호출 가능하다
: 다른 생성자를 호출하게 되면 변수들을 초기화하는 작업이 꼬이는 것을 방지하기 위해 막아둠
* this
> 참조 변수로 자기 자신을 가리킴
> 생성자를 포함한 모든 인스턴스 메소드에는 this 가 지역변수로 숨겨진 채 존재한다
7. 객체지향 프로그래밍2
* 상속
> 생성자와 초기화 블럭은 상속되지 않는다
> 자손의 접근 제어자는 부모의 접근제어자보다 범위가 좁을 수 없다
: public > protected > package private (=default) > private
> 자손에서 Overriding 된 메소드 예외처리의 범위는 조상 메소드보다 좁아야 한다
: Exception > XXXException
- Parent 로 대체되어도 정상 동작되어야 하기 때문에
> Instance Method <-> Static Method 간 변경이 불가능하다
* super & this
> 조상에서 상속받은 변수는 2개다 사용가능하다
* import 문
> import aaa.bbb.*; 해도 성능상에서 차이는 없다. 다만, 명시적으로 지정했을 때와 비교해서 컴파일러가 해당 패키지에서 특정 클래스를 찾기 위한
수고가 필요하다
> 아래와 같은 패키지 구조가 있을 때, aaa.*; 한다고 해서 하위 패키지의 class들까지 import 하는 것은 아니다
import aaa.bbb.*;
import aaa.*;
* final 변수
> 명시적 초기화, 즉 선언과 동시에 대입이 가능하다
> 생성자에서 대입이 가능하다
> 초기화 블럭에서 대입이 가능하다
- {}
* Access Modifier (접근 제어자)
> abstract + static = 불가능
> abstract + final = 불가능
> abstract + private = 불가능
> private + final = 불가능
* Class Type Casting
> Up-Casting - 생략 가능
> Down-Casting - 생략 불가능
* interface
> 추상화 정도가 높아서 일반 메소드 및 멤버 변수를 가질 수 없는 추상 클래스
> Class 와 달리 다중 상속이 가능
> public static final 변수 + public abstract method 만 가질 수 있다
> 장점
: 개발 시간 단축
: 표준화 가능
: 독립적인 프로그래밍
8. 예외처리
* Error
> 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
* Exception
> 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
* RuntimeException
> try-catch 를 이용하기 보다는 예외가 발생하지 않도록 처리
* 에러 로그 출력
> Default 로 화면에 로그를 출력
: System.out();
: System.err();
> 파일에 로그를 출력
PrintStream ps = new PrintStream("error.log");
//파일에 출력1
ps.println("error occurs!!!!");
// 파일에 출력2 (System.err() 실행 시, printStream에 정의된 파일에 로그 출력)
System.setErr(ps);
* void method() throws Exception
> 이 메소드를 호출하는 경우에는 exception 처리가 필요하다는 것을 의미
> 일반적으로 RuntimeException 인 경우에는 적지 않는다
* try-catch-finally 실행 과정
> 예외가 발생하지 않은 경우
: try -> finally
> 예외가 발생한 경우
: try -> catch -> finally
> System.exit(0) 가 호출되는 경우
: 이 경우에는 바로 종료된다
> try or catch 에 return 이 있는 경우
: try/catch 에 return 문이 있더라도 finally 블럭을 수행한 후에 return 문을 실행
> catch 블럭에서 새로운 Exception 발생하는 경우
: 기존 try-catch 의 finally 블록은 그대로 수행
> catch (Exception e) 블럭의 경우, catch 블럭 중 가장 마지막에 위치하여야 한다 (그렇지 않으면, Compiler Error 가 발생)
9. java.lang 패키지
* java.lang 패키지
> 가장 기본 패키지로써 import 없이도 사용가능하다
* Object
> hashCode()
: 주소값을 hash 로 반환
> clone()
: instance, array 변수 등을 제외한 member 값만 복제
- 같은 array 주소를 갖게 되면 src 객체의 배열값에 영향을 미치게 된다
: cloneable 인터페이스를 implements 한 class 에서 사용 가능
> finalize()
: GC 에 의해 자동적으로 호출된다
* Wrapper
Integer.parseInt("100", 2); // 100 값을 2진수로 변환 (=4)
Integer.parseInt("100", 8); // 100 값을 8진수로 변환 (=64)
Integer.parseInt("100", 16); // 100 값을 16진수로 변환 (=256)
Integer.parseInt("FF", 16); // FF 값을 16진수로 변환 (=255)
10. 내부 클래스
* Inner Class
> Inner Class 에서 Outer Class 에 쉽게 접근 가능하다
> 외부에 불필요한 class 를 감춰 code 의 복잡성을 줄일 수 있다 (캡슐화)
: 외부에서 사용하지 않는 경우, inner class 를 사용한다
* 클래스 파일 생성 경로
public class Outer {
void method1() {
class LocalInner {}
}
void method2() {
class LocalInner {}
}
void method3() {
new LocalAnnonymous() {
void annonymousMethod1() {}
};
}
void method4() {
new LocalAnnonymous() {
void annonymousMethod2() {}
};
}
}
> Outer.class
> Outer$1LocalInner.class
> Outer$2LocalInner.class
> Outer$1.class
> Outer$2.class
11. 컬렉션 프레임웤과 유용한 클래스
* Shallow Copy (얉은 복사)
> 배열이나 객체를 복사할 때, 단순히 참조만 복사
* Deep Copy (깊은 복사)
> 원본과 같은 데이터를 저장하고 있는 새로운 객체나 배열을 생성하는 것
12. 지네릭스, 열거형, 애너테이션
*
13. Thread
14. 람다와 스트림
15. 입출력 I/O
* 표준입출력
> System.in : InputStream (BufferedInputStream)
> System.out,err : PrintStream (BufferdOutputStream)
- 버퍼가 있기 때문에 커서를 통해 Backspace 사용 가능
> setOut(), setErr(), setIn()
- Argument로 I/O Stream을 변경
* File
> Canonical Path
- 기호나 링크 등을 포함하지 않는 Unique Path
: /root/file.dat
> Absolute Path
- Root부터 시작하는 파일의 Full Path
: /root/file.dat
: /root/./file.dat
16. 네트워킹
* Server-based Model
> 네트워크를 구성할 때 전용서버를 둠
* P2P (Peer-to-Peer) Model
> 서버와 클라이언트 역할을 동시에 수행
* URL (Uniform Resource Location)
> Protocal://hostName:portNumber/path/filename?query#anchor
> Protocal : 자원에 접근하기 위해 서버와 통신하는데 사용되는 통신규약
> Host Name : 자원을 제공하는 서버의 이름
> Port Number : 통신에 사용되는 서버의 포트번호
> Path : 접근하려는 자원이 저장된 서버상의 위치
> File Name : 접근하려는 자원의 이름
> Query : URL에서 '?' 이후의 부분
> Anchor : URL에서 '#' 이후의 부분
* Socket
> Process 간 통신에 사용되는 양쪽 End Point
> I/O Stream 을 가지고 있다
* Server Socket
> Port 와 Bind 되어, 외부 연결을 기다리다가 연결 요청이 들어오면 Socket을 새성해서 Socket 간 통신이 이루어진다
> 한 Port에 하나의 Server Socket만 연결 가능 (Protocol 이 다르면 같은 Port 공유 가능)
'SW > SW 서적' 카테고리의 다른 글
///C# 프로그래밍 입문 / 강상진, 장현태 / 한빛미디어 (0) | 2022.12.31 |
---|---|
조엘 온 소프트웨어 / 조엘 스포스키 / 에이콘출판 (0) | 2022.07.04 |
자바 성능 튜닝 / 스캇오크스 / 비제이퍼블릭 (0) | 2020.09.06 |
★ 안드로이드 앱 성능 최적화 / 더그 실라스 / 로드북 (0) | 2020.03.08 |
완벽한 IT 인프라 구축을 위한 Docker / Asa Shiho / 정보문화사 (0) | 2020.01.13 |