Eclipse 프로젝트 생성
new Java project
를 하면 여러 선택지가 나옴.
Project layout
- use project folder as root for sources and class files
- 빌드 전 소스코드와 빌드 후 생성된 결과물이 root에 한번에 생김
- Create separate folders for sources and class files
- 빌드 전 소스코드와 빌드 후 생성된 결과물을 다른 폴더에 저장
- use project folder as root for sources and class files
Module
Create module-info.java file
서로 다른 프로젝트 a,b에 대해 a에서 선언한 클래스를 b에서 불러와 사용할 수 있도록 하는 파일
1 2 3 4
// export module common.widget { exports com.logicbig; // 외부에 노출하고싶은 패키지 }
1 2 3 4 5
// import module data.widget { requires common.widget; // 사용할 패키지 requires java.sql; }
Hello world
src
아래HelloWorldApp.java
파일 생성아래와 같이 작성
1 2 3 4 5
public class HellowWorldApp { public static void main(String[] args) { System.out.println("Hellow World!!"); } }
- 클래스명은 파일명과 같아야함.
- 실행하는 파일에서, 파일명과 같은 클래스명안에, 항상
main
함수는 있어야함.
Run
을 눌러 실행
프로그래밍 구성
자료형
- 원시타입
- 정수형 : int, long
- 소수형 : float, double
- 문자형 : char (‘’ 로 묶음)
- boolean
- 클래스타입
- String : “” 로만 묶어야함. 안에 ““를 입력하고 싶으면 \ 사용
- .length()
- .replace(a, b) : a문자열을 찾아 b로 변경
- .equals() : 같은지 확인
- String : “” 로만 묶어야함. 안에 ““를 입력하고 싶으면 \ 사용
숫자와 연산
- Math 클래스
- 다양한 연산 메소드, 상수 제공
캐스팅
앞에
(자료형)
을 붙여서 함1 2
int e = (int) 1.1; double b = (double) e;
정수 -> String
1
String f = Integer.toString(1);
배열
- 선언
- 리터럴 :
String[] bear = {"kloud", "Cass", "Guiness"};
String[] bear = new String[3];
- 리터럴 :
이차원배열
리터럴
1 2 3 4 5
String[][] users = { {"egoing", "1111"}, {"jinhuck", "2222"}, {"youbin", "3333"} }
new
1
String[][] users = new String[3][2];
- 동적배열 :
List
사용
반복문
for
- 일반적 사용
1 2 3 4 5
double[] dividendRates = { 0.5, 0.3, 0.2 }; double[] dividend = new double[3]; for (int i = 0; i < dividendRates.length; i++) { dividend[i] = income * dividendRates[i]; }
- 배열에서 가져오기
1 2 3 4 5
int[] score = { 78, 70, 65, 98, 58 }; int sum = 0; for (int i : score) { sum += i; }
while : 다른 언어와 같음.
프로그래밍 시작하기
입력과 출력
입력 다이얼로그
1 2 3
import javax.swing.JOptionPane; ... String id = JOptionPane.showInputDialog("Enter a Id");
Scanner
1 2 3 4 5 6 7 8
import java.util.Scanner; ... Scanner in = new Scanner(System.in); int a = in.nextInt(); // int형 입력 및 리턴 float b = in.nextFloat(); boolean c = in.nextBoolean(); String d = in.next(); // String 형 입력 및 리턴 (공백을 기준) String e = in.nextLine(); // String 형 입력 및 리턴 (개행을 기준)
arguments & parameter
- 가변인자
void sum(String a, String...str)
와 같이 작성하여, 여러개 받을 수 있도록 하는거.- 내부적으로는 배열로 처리한다.
- main 함수의 args 에 값 넣고 실행하는 방법
Run
옆에 화살표 클릭Run configuration
클릭- ` Arguments` 클릭
- “JAVA APT 508” “123.0” 과 같이 넣기. 공백으로 구분.
직접 컴파일
컴파일 하고자하는 파일이 있는 곳으로 이동.
javac [파일이름].java
하면.class
파일 생성클래스 파일 있는 곳으로 이동
java [파일이름]
하면 실행됨.class
확장자를 붙이지 않음또는
.java
파일을 직접 실행시켜도 된다. 이때는 확장자를 붙임
직접 컴파일 : 라이브러리 사용
javac -cp ".;lib" OkJavaGoInHome.java
-cp
:--class-path
라는 의미. 구분자를 통해 컴파일할 폴더를 연결 가능.;lib
:;
는 구분자..
(현재폴더)와lib
를 컴파일 하라는 뜻.
실행도 비슷하게
java -cp ".;lib" OkJavaGoInHome
으로 실행.
직접 컴파일 : arguments
java OkJavaGoInHomeInput "JAVA APT 507" 15.0
자바용어
패키지, 클래스, 메소드, 변수
- 패키지 : 비슷한 성격의 클래스를 모은것
- java.lang : import 없이 사용가능
- 클래스 : 서로 연관된 변수와 메소드를 모아 이름을 붙인 것
- 패키지 : 비슷한 성격의 클래스를 모은것
인스턴스 : 클래스를 컴퓨터 상에서 실체화 한 것
PrintWriter p1 = new PrintWriter("result1.txt")
상속
throws : 메소드 옆에 붙여 어떤 에러를 던질 수 있는지를 표시
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public static void main(String[] args) { Test test = new Test(); try { test.test("1", "r"); } catch(NumberFormatException e) { System.out.println("입력하신 값은 숫자가 아닙니다."); } } class Text { public void test(String a, String b) throws NumberFormatException { try { int sum = Integer.parseInt(a) + Integer.parseInt(b); // 숫자가 아닐시 NumberFormatException 발생 System.out.pringln("합은 " + sum); } catch(NumberFormatException e) { throw e; } } }
클래스
생성자 : public + 클래스이름으로 선언
1 2 3 4 5 6 7 8 9 10 11
public class AccountingMethodApp { public double valueOfSupply; public double vatRate; public double expenseRate; public AccountingMethodApp(double valueOfSupply, double VatRate, double expenseRate) { this.valueOfSupply = valueOfSupply; this.vatRate = VatRate; this.expenseRate = expenseRate; } ...
static : 정적 멤버 선언.(static 변수 : 정적필드, static 메소드 : 정적 메소드)
객체(인스턴스)에 소속된 멤버가 아니라 클래스에 고정된 멤버.
클래스로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 떄, 클래스별로 관리한다.
정적멤버는 heap이 아닌 static 영역에 할당됨. 프로그램이 종료될 때까지 할당된 상태이므로, static을 남발할 시 프로그램 성능에 악영향을 끼침
인스턴스를 생성하지 않아도 호출 가능하다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
public class AccountingMethodApp { public static double valueOfSupply; public static double vatRate; public static double expenseRate; public static void print() { System.out.println("Value of supply : " + valueOfSupply); System.out.println("VAT : " + getVAT()); System.out.println("Total : " + getTotal()); System.out.println("Expense : " + getExpense()); System.out.println("Income : " + getIncome()); } public static double getIncome() { return valueOfSupply - getExpense(); } public static double getExpense() { return valueOfSupply * expenseRate; } public static double getTotal() { return valueOfSupply + getVAT(); } public static double getVAT() { return valueOfSupply * vatRate; } } public class Test { public static void main(String[] args) { AccountingMethodApp.valueOfSupply = 10000.0; AccountingMethodApp.vatRate = 0.5; AccountingMethodApp.expenseRate =0.1; AccountingMethodApp.print(); } }
static 메소드에서는 static 메소드와 변수만 참조가능하다.
제어문
비교
일반적인 상황에서는 == 등의 비교연산자 사용
String은
equals()
메소드 사용.==
로 비교시 메모리 주소를 비교..equals()
로 비교해야 내용을 비교한다.이유
원시데이터 타입일 경우, 변수가 선언되면 stack에 공간이 할당되고, 그 곳에 실제 값이 들어가게 된다. 그래서
==
연산자는 변수가 가리키는 값을 비교한다.하지만 String과 같이
java.lang.Object
에서 파생된 클래스들은 원시 데이터 타입이 아니다.new
로 생성되면heap
에 새로운 공간이 할당되어 값을 저장하고, 변수는 그 값이 저장된 메모리 주소를 가리키게 된다. 따라서 클래스를==
로 비교하면 메모리 주소를 비교하게 되는 것이다.하지만
문자열 리터럴
로 String을 생성한 경우, 이미 같은 문자열을 생성한 적이 있다면 새로 메모리 공간을 할당하지 않고 새로운 변수는 기존 문자열이 저장된 메모리의 주소를 가리키게 된다. 따라서==
연산시 true가 나온다. 그래도 내용을 비교하려면 일단.equals()
로 비교하자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// 결과 : False String a = new String("1234"); String b = new String("1234"); if (a == b) { System.out.println("TRUE"); } else { System.out.println("False"); } // 결과 : TRUE (같은 메모리 주소이기에) String c = "1234"; String d = "1234"; if (c == d) { System.out.println("TRUE"); } else { System.out.println("False"); } // 결과 : False (다른 메모리 주소이기때문) if (a == c) { System.out.println("TRUE"); } else { System.out.println("False"); }
instanceof
객체가 클래스의 인스턴스냐.
a instanceof A
다형성에 따라,
자식 클래스의 객체 instanceof 부모 클래스
하면true
가 나온다. 반대는 false
메소드
접근제어자
- public : 클래스 외부에서 접근 가능
- private : 클래스 외부에서 접근 불가능
- protected : 같은 패키지 내에 있거나, 상속받은 경우에만 접근 가능함.
- package-private : 패키지 내에서만 접근 가능
객체지향프로그래밍
클래스(형식)
- 한 파일에 여러개를 넣을 수 있지만, public 클래스는 파일이름과 같은 클래스에 하나만 생성가능.
- 자바의 소스코드를 실행할 때, 소스코드 파일명과 동일한 public 클래스를 컴파일해서 그 클래스의 main 메소드를 실행하는 걸로 약속 되어있다.
- 소스코드를 컴파일할때 그 안에 들어있는 클래스는 따로따로
.class
파일로 컴파일된다.- 한 파일 안에 여러 개의 클래스가 있으면, 각각 따로
.class
파일이 나오도록 컴파일 된다는 것
- 한 파일 안에 여러 개의 클래스가 있으면, 각각 따로
생성자와 this
생성자 : 리턴형을 없앤 메소드 형식. 접근제어자는 public이어야함.
1 2 3 4 5 6
class Print { public String delimiter = ""; public Print(String delimiter) { this.delimiter = delimiter; } ...
this
- 인스턴스를 가리키는 예약어.
OOP
- https://seongil-shin.github.io/posts/oop/
상속
extends
1
2
3
4
5
6
7
8
9
10
class Cal {
public int sum(int v1, int v2) {
return v1 + v2;
}
}
class Cal3 extends Cal{
public int minus(int v1, int v2) {
return v1 - v2;
}
}
override
1
2
3
4
5
6
7
8
9
10
11
12
class Cal3 extends Cal{
@Override
public int sum(int v1, int v2) {
System.out.println("Cal3!!!");
return v1 + v2;
}
// overloading
public int sum(int v1, int v2, int v3) {
return v1 + v2 + v3;
}
}
- 이름, 매개변수가 같은 메소드의 구현만 다르게 하는 것.
- @Override 어노테이션을 붙이는 것이 좋다.
- vs overload
- 이름은 같으나 매개변수가 다른 메소드.
- 같은 클래스 내에서도 선언가능
- 생성자도 이와 같이 오버로딩 가능
this super
- super : 부모 클래스를 가리키는 키워드.
- 자식클래스에서 super를 이용하여 접근 권한이 부여된 부모클래스의 변수와 메소드에 접근할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
class Cal {
public int sum(int v1, int v2) {
return v1 + v2;
}
}
class Cal3 extends Cal{
@Override
public int sum(int v1, int v2) {
System.out.println("Cal3!!!");
return super.sum(v1, v2);
}
}
super() 를 통해 부모 클래스의 생성자 호출가능
자식 클래스에서 생성자가 없으면 암묵적으로 부모 클래스의 생성자가 호출됨
하지만 아래와 같이 인자를 받는 생성자만 부모클래스에 있다면, 자식 클래스에서도 생성자를 명시적으로 호출하여 부모 클래스의 생성자를 호출해야한다.
- super() 는 인자가 없는 생성자를 호출하는 것이므로.
- 마찬가지로 어떤 클래스에 인자를 받는 생성자만 있는데, 인자를 넣지않고 인스턴스를 생성하면 컴파일 오류가 난다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Cal {
int v1, v2;
public Cal(int v1, int v2) {
this.v1 = v1;
this.v2 = v2;
}
public int sum() {
return this.v1 + this.v2;
}
}
class Cal2 extends Cal {
int v3;
public Cal2(int v1, int v2, int v3) {
super(v1, v2);
this.v3 = v3;
}
@Override
public int sum() {
return super.sum() + this.v3;
}
}
Java 인터페이스
인터페이스
앞으로 만들 클래스의 메소드 규격을 선언할 수 있음
1 2 3 4 5 6 7 8 9
interface Calculable { int sum(int v1, int v2); } class RealCal implements Calculable { @Override public int sum(int v1, int v2) { return v1 + v2; } }
- 이떄도
@Override
어노테이션은 들어간다.
- 이떄도
여러개의 인터페이스를 동시에 적용할 수 있음
1 2 3 4 5 6 7
interface Calculable { int sum(int v1, int v2); } interface Printable { void print(); } class RealCal implements Calculable, Printable {
interface 내부에서 변수를 정의할 수 있음. 다만 이때는 반드시 초기화 되어야함. 인터페이스를 적용한 클래스는 변수를 다시 대입할 수 없음
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
interface Calculable { double PI = 3.14; int sum(int v1, int v2); } class RealCal implements Calculable { public int sum(int v1, int v2) { return v1 + v2; } } public class InterfaceApp { public static void main(String[] args) { RealCal c = new RealCal(); System.out.println(c.sum(2, 1)); System.out.println(c.PI); } }
interface도 상속이 가능
1 2 3 4 5 6 7
interface Calculable { double PI = 3.14; int sum(int v1, int v2); } interface Printable extends Calculable { void print(); }
다형성
클래스의 인스턴스를 변수로 선언할 떄, 해당 클래스의 데이터타입으로 선언하지 않고
부모 클래스나 인터페이스를 데이터 타입으로 선언
할 수 있다. 이러한 특성을 다형성이라고 부른다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
interface Calculable { double PI = 3.14; int sum(int v1, int v2); } interface Printable { void print(); } class RealCal implements Calculable, Printable { public int sum(int v1, int v2) { return v1 + v2; } public void print() { System.out.println("this is RealCal!!!"); } }
- RealCal 인스턴스를 Calculable 타입으로 선언하면, Printable 메소드를 사용할 수 없다. 반대도 마찬가지.
자식 클래스의 객체 instanceof 부모 클래스
하면true
가 나온다.
추상클래스
인터페이스의 일부 메소드를 클래스 내에서 구현시켰을때 사용.
구현하지 않은 메소드의 리턴값 앞과 클래스 앞에
abstract
를 붙여야한다1 2 3 4 5 6 7 8 9 10 11 12 13
interface Calculable { double PI = 3.14; int sum(int v1, int v2); int minus(int v1, int v2); } abstract class RealCal implements Calculable { public int sum(int v1, int v2) { return v1 + v2; } public abstract int minus(int v1, int v2); // 메소드는 없어도 되긴함 }
enum
- 상수의 집합. class 선언시 class 대신에 enum을 적어주면 된다.
- 상수를 적을 땐, 타입이나 값을 지정할 필요없음.
- 상수들의 이름만 콤마로 구분하고 가장 마지막에 세미콜론을 넣어주자.
- Enum의 부모는 무조건
java.lang.Enum
따라서 다른 것을 상속받으면 안됨.
final
- 클래스, 메소드, 변수에 선언할 수 있음.
- 상속, override, 변경할 수 없다는 의미.
const
같은 거. - 변수에서는 더 이상 변경할 수 없다는 의미
- 인스턴스, 클래스 변수에 final를 쓸땐, 선언과 동시에 초기화 해야함.
- 매개변수, 지역변수에 final을 쓸 땐, 굳이 초기화하지 않아도 된다.(지역변수의 경우 첫 초기화시 값이 고정됨.)
예외
예외 처리
try - catch로 가능
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
try { System.out.println(2); System.out.println(scores[3]); //ArrayIndexOutOfBoundsException // 여기까지 실행 -> catch(ArrayIndexOutOfBoundsException e)문으로 이동 System.out.println(3); System.out.println(2/0); //ArithmeticException System.out.println(4); } catch(ArithmeticException e) { System.out.println("잘못된 계산이네요."); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("없는 값을 찾고 계시네요 ^^"); } catch(Exception e) { System.out.println("알수 없는 에러"); } finally { System.out.println("무조건 실행") }
- catch는 위에서부터 먼저 검사하여, 에러의 타입이 처음 맞는 곳에 들어간다.
- 일치하는 곳이 없으면 throw 됨.
- Exception 클래스는 모든 에러클래스의 부모로, 마지막 catch 문에 Exception을 추가하면 그 곳에 들어간다.
- Exception 클래스는
Throwable
클래스를 상속받고 있어, Throwable 클래스의 메소드도 사용가능하다. - finally 로 try가 끝날시, 또는 catch가 끝날 시 실행될 코드를 작성할 수 있다.
uncheked Exception vs checked Exception
- unchecked exception : 컴파일은 되지만, runtime 중에 발생할 수 있는 exception.
RuntimeException
클래스로부터 상속된 예외 - cheked Exception : try-catch로 잡지 않으면 컴파일이 안되는 에러.
Throwable
를 상속받은 클래스 중RuntimeException
을 제외한 모든 에러와 예외들.
try-with-resource
Java SE7 부터 추가된 구문
자원을 잡고, 놓아주는 과정을 try-catch-finally로 하면 복잡하기에 이를 간단히 해주는 구문
아래와 같이 try 문에 괄호를 추가하여 그 안에 사용할 자원을 정의한다.
- 자원은 여러개 넣을 수 있으며, 세미콜론(;)으로 구분한다. 마지막 객체에는 넣지 않음.
- 전체 try문이 종료되면 생성된 인스턴스는 자동으로 종료되기에 명시적으로 close를 이용하지 않아도 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// 전 try { f = new FileWriter("data.txt"); f.write("Hello"); } catch(IOException e) { e.printStackTrace(); } finally { if (f != null) { try { f.close(); } catch (IOException e) { e.printStackTrace(); } } } // 후 try (FileWriter f = new FileWriter("data.txt")) { f.write("Hello"); } catch (IOException e) { e.printStackTrace(); }
throw
예외를 상위로 미루어 처리하는 것.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
public void test(String a, String b) throws NumberFormatException { int sum = Integer.parseInt(a) + Integer.parseInt(b); System.out.println("합 : " + sum); } public void test(String a, String b) throws NumberFormatException { try { int sum = Integer.parseInt(a) + Integer.parseInt(b); System.out.println("합 : " + sum); } catch(NumberFormatException e) { System.out.println("숫자형 문자가 아닙니다.") throw e; } }
예외처리 전략
- 커스텀 예외 클래스를 만들때는, 꼭 try-catch로 묶어줄 필요가 있을 때만 Exception 클래스를 확장한다.
- 일반적으로 실행시 예외를 처리할 수 있는 경우에만 RuntimeException을 확장한다.
- catch 블록을 공백으로 놔두지 않는다.
익명클래스
다음과 같은 경우 사용함
- 프로그램내에서 일시적으로 사용되어야하는 객체
- 재사용성이 없고, 확장성을 활용하는 것이 유지보수에서 더 불리할 때
문법
1
2
3
부모 클래스 [필드|변수] = new 부모클래스(매개값,...) {
};
구현법
- 필드의 초기값
- 로컬변수의 초기값
- 매개변수의 매개
예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Insect {
void attack(){
System.out.println("곤충은 공격을 한다");
}
}
public class Anonymous {
//★★방법 1 : 필드에 익명자식 객체를 생성
Insect spider1 = new Insect(){
String name = "무당거미";
void cobweb(){
System.out.println("사각형으로 거미줄을 친다.");
}
@Override
void attack() {
System.out.println(name + " 독을 발사한다.");
}
};
//★★방법2 : 로컬변수의 초기값으로 대입
void method1(){
Insect spider2 = new Insect(){
String name = "늑대거미";
//거미줄을 치다.
void cobweb(){
System.out.println("육각형으로 거미줄을 친다.");
}
@Override
void attack() {
System.out.println(name + " 앞니로 문다.");
}
};
//로컬변수이기 때문에 메서드에서 바로 사용
spider2.attack();
// 아래 참고. 접근 불가능
spider2.cobweb();
}
//★★방법3 : 익명객체 매개변수로 대입
void method2(Insect spider){
spider.attack();
}
}
참고
- 익명자식객체에서 새롭게 정의된 필드와 메소드는 자식객체 레벨에서만 사용되기 때문에 외부에서는 사용할 수 없음
- 익명객체를 받아준 변수는 부모타입의 클래스이기 때문에 부모레벨에서 정의된 필드나 메서드만 사용이 가능
자바의 신
패키지
- import 문을 통해 패키지 사용 가능
- 자바파일이 컴파일 될 때, import 된 클래스도 같이 컴파일 된다.
- import로 다른 패키지 접근하기.
- import (루트디렉토리제외) 경로.클래스이름; //한 클래스만 참조
- import (루트디렉토리제외) 경로.*; //마지막 폴더 아래 모든 클래스 참조
String
- StringBuffer : Thread safe, 속도 느림, 여러 쓰레드가 그 변수를 접근할 일이 있을때.
- StringBuilder : Thread unsafe, 속도 빠름, 하나의 메소드 안에서 선언하고 더할 경우.
- 문자열을 합칠때, StringBuilder의 append 메소드를 사용하면 String에서
+
연산자를 사용할때보다 속도가 빠르다.
- 문자열을 합칠때, StringBuilder의 append 메소드를 사용하면 String에서
제네릭
클래스, 메소드를 다양한 타입에서 사용할 수 있도록 해주는 것
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// 클래스에서 public class GenericDTO<T> implements Serializable { private T object; public void setObject(T obj) { this.object = obj; } public T getObject() { return object; } } //호출 GenericDTO<String> dto1 = new GenericDTO<String>(); GenericDTO<StringBuffer> dto2 = new GenericDTO<StringBuffer>(); //메소드에서 //제네릭 메소드 public <T> T genericMethod(T c, T addValue) { System.out.println(addValue); System.out.println(c); return c; } //Bounded Generic 메소드 public <T extends Car> void genericMethod(WildcardGeneric<T> c, T addValue) { c.setWildcard(addValue); T value = c.getWildcard(); System.out.println(value); } //두 개이상의 제네릭 메소드 public <S, T extends Car> void genericMethod(WildcardGeneric<T> c, T addValue, S another) { c.setWildcard(addValue); T value = c.getWildcard(); System.out.println(value); }
<?>
: 와일드카드매개변수에서 사용할 때, 어떤 타입이 올지 모르는 경우 사용
1
public void wildcardStringMethod(WillcardGeneric<?> c);
<? extends Car>
- Car나 Car 자손들만 들어갈 수 있음.
<? super T>
- T나 T 조상만 들어갈 수 있음.
자료형
- Collection 인터페이스
- List : 동적으로 변하는 배열. 하위 클래스의 부모
- ArrayList : 확장가능한 배열. Thread safe 하지 않음
- Vector : 확장 가능한 배열. Thread safe 함.
- Stack : LIFO. Vector 확장
- LinkedList : 한 데이터가 자신의 앞 뒤에 무엇이 있는지 알고 있음.
- Set : 중복 방지. 원하는 값이 있는지 확인하는게 주임무
- HashSet : 순서가 전혀 필요없는 데이터를 해쉬 테이블에 저장함. 성능이 가장 좋음
- TreeSet : red-black tree. Hash보단 느림
- LikedHashSet : 연결된 목록 타입으로 구현된 해시테이블에 데이터를 저장. 저장된 순서에 따라 값이 정렬되며 성능이 가장 느림.
- Queue : FIFO
- PriorityQueue
- Deque : 맨앞, 맨뒤에 값을 넣거나 뺄 수 있음
- List : 동적으로 변하는 배열. 하위 클래스의 부모
- Map 인터페이스 : key-value로 이루어져있음.
- HashMap : key-velue로 저장만 함.
- TreeMap : 값을 저장하면서 키를 정렬한다.
- LinkedHashMap
- Hashtable
// 이후로는 키워드만
쓰레드
- 한 코어에 하나의 쓰레드 실행
- Runnable 인터페이스, Thread 클래스로 생성가능
파일 IO
- File, Files
- File 클래스 : 파일 및 파일 경로정보 포함. 심볼릭링크 같이 유닉스계열에서 사용가능한 기능을 제공하지 않음
- Files 클래스 : JDK 7 이상. 모든 메소드가 static이라 별도의 객체 생성이 없어 더 편리하다.
- InputStream, OutputStream
- Stream은 byte를 처리하기 위한 것. 네트워크를 처리할 때 많이 사용한다.
- Reader, Writer
- char 기반의 문자열을 처리하기 위한 클래스.
- 일반적인 텍스트 에디터로 볼 수 있는 파일들을 위한 클래스.
- 텍스트 파일 읽기, 쓰기
- FileReader, BufferedReader : 텍스트 파일 읽기
- FileWriter : 텍스트 파일 쓰기
- Scanner
- 텍스트 기반 기본 자료형이나 문자열 데이터를 처리하기 위한 클래스
- 사용자로부터 입력을 받을 수 있다.
Serializable 인터페이스
- 개발자가 만든 클래스가 파일에 읽거나 쓸 수 있도록 하거나, 다른 서버로 보내거나 받을 수 있도록하려면 반드시 구현해야함.
- 인터페이스를 구현한 다음에 serialVersionUID를 지정하는 걸 권장받음. 해당 클래스의 버전을 명시하는 것.
- UID가 다른 클래스는 이름이 같은 클래스여도 다른 클래스로 인식.
- 별도로 지정하지 않으면 컴파일시 자동 지정됨.
- 객체 저장 : ObjectOutputStream 클래스 사용
- 객체 읽기 : ObjectInputStream 클래스 사
자바 NIO
- 스트림이 아닌 채널과 버퍼를 사용함
- 채널 : 물건을 중간에처 처리하는 도매상
- 버퍼 : 도매상한테 물건을 사고, 소비자에게 파는 소매상
네트워크
- TCP 통신
- Socket 클래스
- 데이터를 보내는 쪽(클라이언트)에서 객체를 생성하여 사용함.
- 데이터를 받는 쪽(서버)에서 클라이언트 요청을 받으면, 요청에 대한 socket 객체를 사용하여 데이터를 처리함.
- Socket 객체를 직접 생성해야함.
- SeverSocket 클래스
- 서버에서 사용하는 클래스. 객체는 클라이언트 요청이 생기면 Socket 객체를 생성하여 전달해줌.
- 생성자와 2개의 메소드만 알아도 네트워크 프로그래밍이 가능하다.
- 클라이언트에서 접속을 하면 Socket 객체를 생성함.
- Socket 클래스
UDP 통신
- DatagramSocket 클래스
- 보내는 역할과 받는 역할 모두 수행할 수 있음.
- DatagramPacket 클래스
- 스트림을 사용하지 않고 데이터를 주고 받음.
- DatagramSocket 클래스
- Http 요청
- URL 클래스 : 아주 간단한 요청 처리가능. 별로 추천하진 않음
- Apache의 HttpComponents : 일반적으로 많이 사용함
자바 버전별
Java 7
숫자표현방법
- 진수
- 2진수 : 0b
- 8진수 : 0
- 16진수 : 0x
- 천단위 언더바 : 1_000_000
- 진수
switch 문에서 String 사용가능
제네릭을 쉽게 사용할 수 있는 Diamond
1
GenericDTO<String> dto1 = new GenericDTO<>();
- 이렇게 뒤는 생략가능하게 하는 거
예외 처리시 다중 처리가능
1 2 3
catch(IllegalArgumentException | FileNotFoundException | NullPointException e){ e.printStackTrace(); }
- 위와 같이 다중으로 에러를 받을 수 있음.
fork/join 관련 클래스
- cpu 멀티코어를 쉽게 사용하기 위해 만들어짐. 여러개로 나누어 계산한 후 결과를 모은다.
- 쓰레드 신경 안써도 JVM이 자동으로 처리하고, worker의 개수는 CPU의 개수만큼 증가한다.
NIO2
- 파일의 속성, 심볼릭 링크까지 처리가능. 어떤 파일이 변경되었는지 확인할 수 있는 WatchService 클래스 제공
- File을 대체하는 클래스 : java.nio.file 에 있음
- Paths
- Files : 기존 File 클래스를 보완.
- FileSystems : 파일시스템에 대한 정보를 처리
- FileStore : 파일을 저장하는 디바이스, 파티션, 볼륨 등에 대한 정보를 처리
- SeekableByteChannel(random access) : 바이트기반 채널을 처리
- NetworkChannel 및 MulticastChannel
- AsynchronousFileChannel : 비동기 처리 파일 채널
JDBC 4.1 : SQL Query를 쉽게 수행할 수 있는 RowSet의 객체를 쉽게 만들어주는 클래스 포함
TransferQueue : 메세지처리에 사용
Objects 클래스 : Object와 같은 static한 메소드 제공. 넘어온 객체가 null이어도 예외가 발생하지 않음
Java8
Lambda 표현식
- 익명클래스의 가독성을 올리기 위해 사용됨.
- 구현해야할 함수가 하나일때만 사용가능. (default, static 제외)
- js 화살표함수처럼 사용.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// 이전 private void calculateClassic() { Calculate claculateAdd = new Calculate() { //Calculate 는 Functional 인터페이스 @Override public int operation(int a, int b) { return a+b; } }; System.out.println(calculateAdd.operation(1,2)); } // 이후 private void calculateLambda() { Calculate calculateAdd = (a,b) -> a+b; System.out.println(calculateAdd.operation(1,2)); } // 이전 new Thread(new Runnable() { @Override public void run() { System.out.println("Thread run"); } }).start(); // 이후 new Thread(()->System.out.println("Thread run")).start(); // Thread 생성자로는 Runnable을 넣어줘야하므로 이렇게 해줘도 알아서 Runnable로 들어감.
Functional 인터페이스 : java.util.function 패키지에 속함. 추상메서드가 오직 하나인 인터페이스를 뜻하므로 람다식과 호흡이 좋음.
- Predicate : test()라는 메소드 존재. 두 개의 객체를 비교할 때 사용하고 boolean을 리턴함.
- Supplier : get() 메소드 존재. 리턴값은 generic으로 선언된 타입을 리턴함
- Consumer : accept()라는 매개변수를 하나 갖는 메소드가 존재. 리턴값은 없음.
- Function : apply()라는 하나의 매개변수를 갖는 메소드 존재. 리턴값 존재.
- UnaryOperator : apply()라는 하나의 매개변수를 갖는 메소드가 있음. 리턴값 존재.
- BinaryOperator : apply()라는 두 개의 매개변수를 갖는 메소드가 있음. 리턴값 존재.
Stream : 연속된 정보를 처리할 때 사용함.
- 배열에는 사용할 수 없지만, 컬렉션에는 사용가능. 따라서 배열을 List로 바꾼다음 사용.
- .stream() : 스트림 생성. 컬렉션을 스트림 객체로 변환함. 변환 후 중개, 중단 연산 사용
- 중개연산 : filter(), map(), flatMap(), sorted()
- 종단연산 : forEach(), toArray(), anyMatch(), allMatch(), nonMatch(), findFirst(), any(), reduce(), collector()
- 메소드 참조. 데이터가 바로 메소드의 매개변수로 들어가도록 하는 법
- ` .forEach(System.out::println)
,
.forEach(ContainingClass::staticMethodName)`
- ` .forEach(System.out::println)
Optional : null이 올 수 있는 값을 감싸기 위해 사용. 값이 null이더라도 NPE이 발생하지않음
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
// Java8 이전 List<String> names = getNames(); List<String> tempNames = names != null ? names : new ArrayList<>(); // Java8 이후 List<String> nameList = Optional.ofNullable(getNames()) .orElseGet(() -> new ArrayList<>()); // Java8 이전 public String findPostCode() { UserVO userVO = getUser(); if (userVO != null) { Address address = user.getAddress(); if (address != null) { String postCode = address.getPostCode(); if (postCode != null) { return postCode; } } } return "우편번호 없음"; } public String findPostCode() { // 위의 코드를 Optional로 펼쳐놓으면 아래와 같다. Optional<UserVO> userVO = Optional.ofNullable(getUser()); Optional<Address> address = userVO.map(UserVO::getAddress); Optional<String> postCode = address.map(Address::getPostCode); String result = postCode.orElse("우편번호 없음"); // 그리고 위의 코드를 다음과 같이 축약해서 쓸 수 있다. String result = user.map(UserVO::getAddress) .map(Address::getPostCode) .orElse("우편번호 없음"); }
- 결과가 null이 될 수 있으며, null에 의해 오류가 발생할 가능성이 매우 높을 때 반환값으로만 사용
인터페이스의 기본 메소드
1 2 3 4 5
public interface Vehicle { public default void doSomething(int n) { System.out.println("doSomething(Vehicle)"); } }
- 위와 같이
default
키워드와 함께 인터페이스의 디폴트메소드 선언가능 - 다중 implements 시 같은 메소드가 default라면,
- 컴파일 오류 발생. override 해줘야힘
- 상속, implements 시 같은 메소드가 구현되어있다면
- 상속 메소드가 사용됨.
- 위와 같이
날짜 관련 클래스 추가
- 불변 클래스 추가 : java.time.ZonedDateTime, java.time.LocalDate
- java.time.format.DateTimeFormatter : thread safe하고 빠른 클래스
병렬배열 정렬
- Arrays 클래스 : 배열을 처리하기에 좋은 여러 static 메소드를 가지고 있음.
- binarySearch(), fill(), sort() 등
- parallelSort() : Fork-Join 프레임웍이 내부적으로 사용됨. 여러 쓰레드로 수행되어 속도는 더 빠르다.
- Arrays 클래스 : 배열을 처리하기에 좋은 여러 static 메소드를 가지고 있음.
StringJoiner : 순차적으로 나열되는 문자열을 처리할 때 사용함.
출처
https://www.boostcourse.org/cs128
자바의 신
https://mangkyu.tistory.com/70
https://limkydev.tistory.com/226