Java
Start
public class Filename {
// 모든 코드는 클래스 내부에 작성
}
Filename.java파일 생성 시 기본 설정되는 클래스 형태psvm(public static void main) 또는main+ 엔터 키 입력 시 자동으로 main 메서드 완성
↓
public class Filename {
public static void main(String[] args) {
System.out.print("Hello"); // print: 줄바꿈 x, println: 줄바꿈 o
System.out.println(" World"); // [sout + 엔터 키] → System.out.println(); 완성
}
}
Hello World
- 모든 실행 코드는 반드시 main 메서드 내부에서 시작
public: JVM이 어디서든 접근 가능하도록 설정static: 객체를 생성하지 않고도 실행되도록 설정 (Python의if __name__ == "__main__":과 비슷)void: 반환값 없음String[] args: 모든 인자는 문자열로 전달됨
Data types
public class Variables {
public static void main(String[] args) {
// ===== 정수형 =====
int i = 3; // 기본 타입은 int (32bit)
long l = 1000000000000L; // long (64bit) → 리터럴 뒤에 L 또는 l 필요
l = 1_000_000_000_000L; // 언더바(_)는 가독성용으로, 컴파일 시 무시됨
byte b = 127; // -128 ~ 127
short s = 32000; // -32768 ~ 32767
// ===== 실수형 =====
double d = 3.14123456789; // 기본 타입은 double (64bit)
float f = 3.14123456789F; // float (32bit) → 리터럴 뒤에 F 또는 f 필요
// ===== 문자 / 문자열 =====
char c1 = 'A'; // 단일 문자 (UTF-16 기반 유니코드)
char c2 = 65; // 'A' (Unicode 코드 포인트)
// ===== 불리언 =====
boolean isTrue = true; // 참고: Python과 달리 truthy / falsy 개념 없음
boolean isFalse = false;
// ===== 상수 =====
final double PI = 3.141592; // final → 재할당 불가 (컴파일 에러)
}
}
public class TypeCasting {
public static void main(String[] args) {
// 작은 범위 → 큰 범위 : 자동 형변환 (int → long → float → double)
// 큰 범위 → 작은 범위 : 명시적 형변환 필요
// ===== 정수 → 실수 =====
int score = 3;
float score_r2 = score; // 3.0 (캐스팅 불필요)
// ===== 실수 → 정수 =====
float score_f = 3.14F;
double score_d = 3.1415;
System.out.println((int) score_f); // 3
System.out.println((int) score_d); // 3
// ===== 연산 =====
score_d = 3 + 3.1415; // 3 → 3.0 (자동 승격)
score = 3 + (int) 3.14f; // 3.14f → 3 (캐스팅 필요)
// ===== 숫자 → 문자열 =====
String s;
s = String.valueOf(3); // 방법1: String 클래스 사용 (권장)
s = Integer.toString(3); // 방법2: Integer, Double 클래스 사용
s = Double.toString(3.1415);
// ===== 문자열 → 숫자 =====
int i = Integer.parseInt("3");
double d = Double.parseDouble("3.1415");
}
}
enum Resolution {
HD(1280), FHD(1920), UHD(3840); // 각 상수 값이 width 값을 갖는 형태
private final int width;
Resolution(int width) { // 생성자로 width 지정
this.width = width;
}
public int getWidth() { // getter
return width;
}
}
public class Type_Enum {
public static void main(String[] args) {
Resolution resolution = Resolution.HD; // 생성된 객체(resolution)에 값(HD) 지정
resolution = Resolution.valueOf("UHD"); // 값을 FHD으로 변경(문자열로부터 값 가져오는 경우)
System.out.print("동영상 녹화 품질 : ");
switch (resolution) {
case HD:
System.out.println("일반화질");
break;
case FHD:
System.out.println("고화질");
break;
case UHD:
System.out.println("초고화질");
break;
}
for (Resolution myRes : Resolution.values()) { // name: 값 이름, ordinal: 값 입력 순서
System.out.println(myRes.name() + " : " + myRes.ordinal());
}
System.out.println("-------------------");
for (Resolution myRes : Resolution.values()) {
System.out.println(myRes.name() + " : " + myRes.getWidth());
}
}
}
Operator
public class Operator {
public static void main(String[] args) {
// ===== 산술 연산자 =====
System.out.println(5 + 2); // 7
System.out.println(5 - 2); // 3
System.out.println(5 * 2); // 10
System.out.println(5 / 2); // 2 (파이썬의 정수 // 정수 와 동일)
System.out.println(5 % 2); // 1
// ===== 증감 연산자 (++, --) =====
int val;
val = 10;
System.out.println(val); // 10
System.out.println(++val); // 11 (val+1 먼저 적용 후 문장 실행)
System.out.println(val); // 11
val = 10;
System.out.println(val); // 10
System.out.println(val++); // 10 (문장 먼저 실행 후 val+1 적용)
System.out.println(val); // 11
// ===== 대입 연산자 =====
int num = 10;
num += 2; // num = num + 2
System.out.println(num); // 12
num -= 2; // num = num - 2
System.out.println(num); // 10
num *= 2; // num = num * 2
System.out.println(num); // 20
num /= 2; // num = num / 2
System.out.println(num); // 10
num %= 2; // num = num % 2;
System.out.println(num); // 0
// ===== 비교 연산자 =====
System.out.println(5 > 5); // false
System.out.println(5 >= 5); // true
System.out.println(5 < 7); // true
System.out.println(5 <= 3); // false
System.out.println(5 == 5); // true
System.out.println(5 != 5); // false
// ===== 논리 연산자 =====
boolean a = true;
boolean b = false;
boolean c = 5 > 3; // true
System.out.println(a || b || c); // or 연산 (true가 하나 이상 있으므로 true)
System.out.println(a && b && c); // and 연산 (b가 false이므로 false)
System.out.println(!a); // not 연산 (!true -> false)
System.out.println(!b); // not 연산 (!false -> true)
// ===== 삼항 연산자 =====
// 결과 = (조건) ? (true일 때 결과값) : (false일 때 결과값)
int x = 3;
int y = 5;
int max = (x > y) ? x : y;
System.out.println(max); // 5
String result = (x == y) ? "same" : "different";
System.out.println(x + " and " + y + " are " + result); // 3 and 5 are different
}
}
String
public class test {
public static void main(String[] args) {
// String은 immutable(불변)이므로 원본은 변경되지 않음
String s = "I like Java and Python and C.";
// 문자열의 길이
int len = s.length(); // (29)
// 대소문자 변환
String upper = s.toUpperCase(); // 모두 대문자
String lower = s.toLowerCase(); // 모두 소문자
// 포함 관계
boolean isIn = s.contains("C#"); // 해당 문자열 포함 여부 (false)
int whereIdx = s.indexOf("C#"); // 발견되지 않는다면 -1
int firstIdx = s.indexOf("Java"); // 처음 발견되는 위치 (7)
int lastIdx = s.lastIndexOf("and"); // 마지막 발견되는 위치 (23)
boolean start = s.startsWith("I"); // 이 문자열로 시작하면 true
boolean end = s.endsWith("."); // 이 문자열로 끝나면 true
// 문자열 변환
String newS = s.replace(" and", ","); // " and" 를 "," 로 변환
String subS1 = s.substring(s.indexOf("Java")); // "Java"가 발견되는 위치부터 끝까지
String subS2 = s.substring(7, s.indexOf(".")); // 인덱스 7부터 "." 앞까지 (마지막 포함 x)
// 공백 제거
s = " I love Java. ";
String trimmedS = s.trim(); // 앞뒤 공백문자 제거(중간 공백은 제거 x)
// 문자열 결합
String s1 = "Java";
String s2 = "Python";
String mergedS1 = s1 + ", " + s2; // Java, Python
String mergedS2 = s1.concat(", ").concat(s2); // Java, Python
// 문자열 비교
boolean isAllSame = s1.equals("Java");
// 문자열 비교 (대소문자 구분 x)
boolean isCaseSame = s2.equalsIgnoreCase("python");
// equals() vs ==
s1 = "1234"; // 문자열 리터럴 "1234"이 String Constant Pool에 저장됨
s2 = "1234"; // 같은 리터럴은 하나만 생성되기 때문에 s1과 같은 객체를 가리킴
System.out.println(s1.equals(s2)); // true (같은 내용)
System.out.println(s1 == s2); // true (같은 객체)
s1 = new String("1234"); // new String()은 무조건 새 객체 생성
s2 = new String("1234"); // s1과 다른 객체
System.out.println(s1.equals(s2)); // true (같은 내용)
System.out.println(s1 == s2); // false (다른 객체)
// 특수문자, 이스케이프 문자
System.out.println("I\nLove\nJava."); // \n : 줄바꿈
System.out.println("1234\t5678"); // \t : 탭
System.out.println("C:\\Program Files\\Java"); // \\ : 역슬래시
System.out.println("I \"love\" Java."); // \" : 큰따옴표
char c = '\''; // \' : 작은따옴표
System.out.println(c);
}
}
Condition
public class Condition {
public static void main(String[] args) {
// ===== if, else if, else =====
int a = 10;
int b = 20;
int c = 30;
if (a < b)
System.out.println("b is greater than a"); // 하나의 문장은 { } 생략 가능
if (a > b) {
System.out.println("a is greater than b");
} else if (a > c) {
System.out.println("a is greater than c");
} else if (a == b) {
System.out.println("a equals b");
} else {
System.out.println("a is the smallest");
}
// ===== Switch Case =====
int rank = 2;
switch (rank) {
case 1: // 1등은 전액
System.out.println("전액 장학금");
break;
case 2: // 2, 3등은 반액(break 생략으로 통합)
case 3:
System.out.println("반액 장학금");
break;
default: // 그 외 등수는 장학금 대상 아님
System.out.println("장학금 없음");
}
// ===== For =====
int sum = 0;
for (int i = 1; i <= 10; i++) { // 초기식; 조건식; 증감식
sum += i;
}
System.out.println("1부터 10까지의 총합은 " + sum + "입니다.");
// ===== While =====
sum = 0;
int idx = 1; // 초기식
while (idx <= 10) { // 조건식
sum += idx;
idx++; // 증감식
}
System.out.println("1부터 10까지의 총합은 " + sum + "입니다.");
// ===== Do While =====
idx = 100;
do {
System.out.println("do-while"); // 조건이 처음부터 false여도 1번은 실행됨
} while (idx <= 10);
// ===== Continue =====
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; // 이번 반복만 스킵
}
System.out.print(i + " "); // 1 2 4 5
}
// ===== Break =====
for (int i = 1; i <= 5; i++) {
if (i == 3) {
break; // 반복문 즉시 종료
}
System.out.print(i + " "); // 1 2
}
}
}
Array
public class Arr {
public static void main(String[] args) {
// ===== 배열 선언 =====
// 방법 1
String[] fruits1 = new String[4];
// 방법 2
String fruits2[] = new String[4];
// 방법 3
String[] fruits3 = new String[] { "Apple", "Banana", "Cherry", "Durian" };
// 방법 4
String[] fruits4 = { "Apple", "Banana", "Cherry", "Durian" };
// ===== 배열 루프 =====
for (int i = 0; i < fruits4.length; i++) { // 배열 길이 이용
System.out.println(fruits4[i]);
}
for (String f : fruits4) { // for each 반복문
System.out.println(f);
}
// ===== 2차원 배열 =====
String[][] arr2d = {
{"A0", "A1", "A2", "A3", "A4"},
{"B0", "B1", "B2", "B3", "B4"},
{"C0", "C1", "C2", "C3", "C4"}
};
}
}
Method
public class Method {
// ===== 메소드 정의(main 영역 밖) =====
public static void callMethod() { // 1. Parameter x, Return x
System.out.println("기본 메소드");
}
public static void power(int number) { // 2. Parameter
int result = number * number;
System.out.println(number + " ** 2 = " + result);
}
public static String getNumber() { // 3. Return (반환값 타입 정의 필요)
String phoneNumber = "02-1234-5678";
return phoneNumber;
}
public static int getPower(int number) { // 4. Parameter + Return
int result = number * number;
return result;
}
public static String printStr(String s) { // 5. Overloading (이름이 같은 메소드 여러 개)
return s;
}
public static String printStr(int number) {
return String.valueOf(number);
}
public static String printStr(String s, int n) {
return s + String.valueOf(n);
}
public static String printStr(int n, String s) {
return s + String.valueOf(n);
}
// ===== 메소드 호출(main 영역 안) =====
public static void main(String[] args) {
callMethod(); // 1
power(3); // 2 (3을 Argument로 전달)
String contact = getNumber(); // 3 (반환값을 받을 변수 선언 필요)
int retVal = getPower(2); // 4
System.out.println(printStr("123")); // 5 (문자열 타입 매개변수 1개)
System.out.println(printStr(123)); // (매개변수 타입 다름)
System.out.println(printStr("ben", 6)); // (매개변수 개수 다름)
System.out.println(printStr(7, "will")); // (매개변수 순서 다름)
}
}
Class
custom package 1
package dashcam;
public class BlackBox {
// ===== 인스턴스 변수(서로 다른 객체에서 서로 다른 값) 정의 =====
String modelName;
String resolution;
int price;
String color;
int serialNumber;
// ===== 클래스 변수(모든 객체에 똑같이 적용) 정의 =====
static int serialCounter = 0;
static boolean canAutoReport = false;
// ===== 생성자(객체 생성 시 자동 호출) =====
BlackBox() {
System.out.println("기본 생성자 호출");
this.serialNumber = ++serialCounter; // 생성자에서 인스턴스 변수 업데이트
}
BlackBox(String modelName, String resolution, int price, String color) {
this(); // this와 괄호로 다른 생성자 호출 가능
System.out.println("사용자 정의 생성자 호출");
this.modelName = modelName;
this.resolution = resolution;
this.price = price;
this.color = color;
}
// ===== 메소드(객체가 사용할 기능) 정의 =====
void autoReport() {
if (canAutoReport) {
System.out.println("충돌 감지 자동 신고 실행");
}
else {
System.out.println("자동 신고 기능 미지원");
}
}
void appendModelName(String modelName) {
this.modelName += modelName; // this로 클래스의 인스턴스 변수임을 명시
}
int getVideoFileCount(int type) {
if (type == 1) {
return 9;
}
else if (type == 2) {
return 1;
}
return 10;
}
// ===== 메소드 오버로딩 =====
void record(boolean showDateTime, boolean showSpeed, int min) {
System.out.println("영상 녹화 시작");
if (showDateTime) {
System.out.println("녹화 영상에 날짜정보 표시");
}
if (showSpeed) {
System.out.println("녹화 영상에 속도정보 표시");
}
System.out.println("영상은 " + min + "분 단위로 기록");
}
void record() {
record(true, true, 5); // 파라미터 입력 안 하면 원하는 기본값으로 호출
}
// ===== 클래스 메소드 =====
static void callServiceCenter() {
System.out.println("1588-1234로 연결");
canAutoReport = true; // static 메소드에서 클래스 변수 접근 가능
}
}
package dashcam;
public class BlackBoxRefurbish {
public String modelName; // public : 모든 클래스에서 접근 가능
String resolution; // default : 같은 패키지 내에서만 접근 가능(접근 제어자 명시x)
private int price; // private : 해당 클래스 내에서만 접근 가능
protected String color; // protected : 1. 같은 패키지 내에서 접근 가능
// 2. 다른 패키지인 경우 자식 클래스에서 접근 가능
// ===== getter & setter =====
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public String getResolution() {
if (resolution == null || resolution.isEmpty()) { // 값을 미입력하는 실수 대비
return "판매자에게 문의하세요.";
}
return resolution;
}
public void setResolution(String resolution) {
this.resolution = resolution;
}
public int getPrice() {
return price;
}
public void setPrice(int price) { // 값을 적게 입력하는 실수 대비
if (price < 100000) {
this.price = 100000;
}
else {
this.price = price;
}
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
custom package 2
package camera;
public class Camera { // 부모 클래스(기능 물려주기)
public String name;
public Camera() { // 생성자 1(같은 클래스의 생성자 2 호출)
this("카메라");
}
protected Camera(String name) { // 생성자 2(실제 초기화 담당)
this.name = name;
}
public void takePicture() { // 사진 촬영(모든 종류 카메라의 기본 기능)
System.out.println(this.name + " : 사진을 촬영합니다.");
}
public void recordVideo() { // 동영상 녹화(모든 종류 카메라의 기본 기능)
System.out.println(this.name + " : 동영상을 녹화합니다.");
}
public void showMainFeature() { // 자식 클래스에서 오버라이드 할 메소드
System.out.println(this.name + "의 주요 기능 : 사진 촬영, 동영상 녹화");
}
}
package camera;
// FactoryCam IS A Camera (o) | Camera IS A FactoryCam (x)
public class FactoryCam extends Camera { // 자식 클래스(기능 물려받기)
public FactoryCam() {
super("공장 카메라"); // super() 으로 부모 클래스의 생성자에 접근
}
public void recordVideo() { // 동영상 녹화
super.recordVideo(); // super. 으로 부모 클래스의 메소드에 접근
detectFire();
}
public void detectFire() { // 화재 감지
System.out.println("화재를 감지합니다.");
}
public void showMainFeature() { // 부모 클래스의 메소드 오버라이딩(재정의)
System.out.println(this.name + "의 주요 기능 : 화재 감지");
}
}
package camera;
// SpeedCam IS A Camera (o) | Camera IS A SpeedCam (x)
public class SpeedCam extends Camera { // 자식 클래스(기능 물려받기)
public SpeedCam() {
super("과속단속 카메라"); // super() 으로 부모 클래스의 생성자에 접근
}
public void takePicture() { // 사진 촬영
super.takePicture(); // super. 으로 부모 클래스의 메소드에 접근
checkSpeed();
recognizeLicensePlate();
}
public void checkSpeed() { // 속도 측정
System.out.println("속도를 측정합니다.");
}
public void recognizeLicensePlate() { // 번호 인식
System.out.println("차량 번호를 인식합니다.");
}
@Override // annotation(오버라이드 불가능한 경우 에러 발생)
public void showMainFeature() { // 부모 클래스의 메소드 오버라이딩(재정의)
System.out.println(this.name + "의 주요 기능 : 속도 측정, 번호 인식");
}
}
package camera;
public final class ActionCam extends Camera { // final로 클래스 상속 금지
public final String lens; // final로 값 수정 금지(초기화는 바로 or 생성자)
public ActionCam() {
super("액션 카메라");
lens = "광각렌즈";
}
public final void makeVideo() { // final로 메소드 오버라이딩 금지
System.out.println(this.name + " : " + this.lens + "로 촬영한 영상을 통해 비디오를 제작합니다.");
}
}
package camera;
public class SlowActionCam { // ActionCam 상속 불가
public String name;
public SlowActionCam() {
this.name = "슬로우 액션 카메라";
}
public void makeVideo() {
System.out.println("자체 개발한 비디오 제작 기능");
}
}
main class
package learnClass; // 해당 패키지(연관된 클래스들의 묶음) 명시
import dashcam.BlackBox; // 다른 패키지의 특정 클래스 사용
import dashcam.BlackBoxRefurbish;
import camera.*; // 다른 패키지의 모든 클래스 사용
public class OOP {
public static void main(String[] args) {
// ============== BlackBox 클래스의 인스턴스(객체) ==============
BlackBox bbox1 = new BlackBox(); // 기본 생성자 사용
bbox1.modelName = "g1"; // 인스턴스 변수 업데이트
bbox1.resolution = "FHD";
bbox1.price = 200000;
bbox1.color = "black";
BlackBox bbox2 = new BlackBox("g2", "UHD", 300000, "white"); // 사용자 정의 생성자 사용
BlackBox.canAutoReport = true; // 클래스 변수 업데이트
System.out.println("전 제품 자동 신고: " + BlackBox.canAutoReport); // 클래스 변수 접근
bbox1.autoReport(); // 메소드 호출
bbox1.appendModelName("(latest)");
int fileCount = bbox1.getVideoFileCount(1);
fileCount = bbox1.getVideoFileCount(2);
bbox1.record(false, false, 10); // 메소드 오버로딩 예시
bbox1.record();
BlackBox.callServiceCenter(); // 클래스 메소드 접근
// ============== BlackBoxRefurbish 클래스의 인스턴스(객체) ==============
BlackBoxRefurbish bbox3 = new BlackBoxRefurbish();
bbox3.modelName = "g3";
// bbox3.price = -5000; // price는 private이기 때문에 직접 접근 불가
bbox3.setPrice(-5000); // setter를 통해서만 price에 접근 가능
bbox3.color = "red";
System.out.println("해상도 : " + bbox3.getResolution()); // getter로 null값 출력 방지
// ============== Camera 패키지 클래스들의 인스턴스(객체) ==============
Camera camera = new Camera(); // 부모 클래스
Camera factoryCam = new FactoryCam(); // 자식 클래스(다형성, 부모 클래스로 서로 다른 객체 생성)
SpeedCam speedCam = new SpeedCam(); // 자식 클래스
if (factoryCam instanceof FactoryCam) { // 부모 클래스로 정의한 객체로 자식 클래스 메소드 접근 방법
((FactoryCam)factoryCam).detectFire(); // FactoryCam 클래스 타입으로 변환 후 호출
}
// --------------- 참조 ---------------
int a = 10; // 기본 자료형(int, float, double, long, boolean 등)
int b = 20;
b = a; // 값 복사(복사본을 변경해도 원본에 영향 x)
System.out.println(a); // 10
System.out.println(b); // 20
b = 30;
System.out.println(a); // 10
System.out.println(b); // 30
Camera c1 = new Camera(); // 참조 자료형(String, 사용자 정의 클래스)
Camera c2 = new Camera();
c1.name = "카메라1";
c2.name = "카메라2";
System.out.println(c1.name); // 카메라1
System.out.println(c2.name); // 카메라2
c2 = c1; // 참조 복사(주소값을 복사하므로 2개의 변수가 동일한 객체 가리킴)
System.out.println(c1.name); // 카메라1
System.out.println(c2.name); // 카메라1
c2.name = "고장난 카메라";
System.out.println(c1.name); // 고장난 카메라
System.out.println(c2.name); // 고장난 카메라
c2 = null; // 참조 관계 끊는 방법
// --------------- final ---------------
ActionCam actionCam = new ActionCam();
actionCam.makeVideo();
SlowActionCam slowActionCam = new SlowActionCam();
slowActionCam.makeVideo(); // 메소드 오버라이딩 아님
}
}
Abstract Class
custom package 1
package learnAbstractClass.camera;
public abstract class Camera { // 추상 클래스(미완성된 클래스)
public void takePicture() {
System.out.println("사진을 촬영합니다.");
}
public void recordVideo() {
System.out.println("동영상을 녹화합니다.");
}
public abstract void showMainFeature(); // 추상 메소드(선언만 하고 나중에 구현 필요)
}
package learnAbstractClass.camera;
import learnAbstractClass.detector.Detectable;
import learnAbstractClass.reporter.Reportable;
// Camera 클래스를 상속하고 Detectable과 Reportable 인터페이스의 기능을 사용하는 클래스
public class FactoryCam extends Camera implements Detectable, Reportable {
private Detectable detector; // 외부에서 전달받은 인터페이스 변수
private Reportable reporter;
public void setDetector(Detectable detector) { // setter로 원하는 기능 받아오기
this.detector = detector;
}
public void setReporter(Reportable reporter) {
this.reporter = reporter;
}
@Override
public void showMainFeature() { // 추상 메소드를 오버라이드로 구현
System.out.println("화재 감지");
}
@Override
public void detect() { // 인터페이스의 메소드 구현(실제 동작은 해당 객체에 위임)
detector.detect();
}
@Override
public void report() {
reporter.report();
}
}
custom package 2
package learnAbstractClass.reporter;
public interface Reportable {
void report(); // 인터페이스에서 메소드 선언
}
package learnAbstractClass.reporter;
public class NormalReporter implements Reportable { // 인터페이스를 구현하여 기능을 정의하는 클래스
@Override
public void report() {
System.out.println("일반 화재 신고를 진행합니다.");
}
}
package learnAbstractClass.reporter;
public class VideoReporter implements Reportable {
@Override
public void report() {
System.out.println("직전 30초 영상과 함께 신고를 진행합니다.");
}
}
custom package 3
package learnAbstractClass.detector;
public interface Detectable {
void detect(); // 인터페이스에서 메소드 선언
}
package learnAbstractClass.detector;
public class FireDetector implements Detectable { // 인터페이스를 구현하여 기능을 정의하는 클래스
@Override
public void detect() {
System.out.println("일반 성능으로 화재를 감지합니다.");
}
}
package learnAbstractClass.detector;
public class AdvancedFireDetector implements Detectable{
@Override
public void detect() {
System.out.println("향상된 성능으로 화재를 감지합니다.");
}
}
main class
package learnAbstractClass;
import learnAbstractClass.camera.*;
import learnAbstractClass.reporter.*;
import learnAbstractClass.detector.*;
public class _01_AbstractClass {
public static void main(String[] args) {
// ============== 추상 클래스와 자식 클래스 ==============
// Camera camera = new Camera(); // 추상 클래스 객체는 생성 불가
FactoryCam factoryCam = new FactoryCam(); // 추상 클래스의 자식 클래스 객체는 생성 가능
factoryCam.showMainFeature();
// ============== 인터페이스 ==============
// ---------- 신고 기능 ----------
Reportable normalReporter = new NormalReporter();
normalReporter.report();
Reportable videoReporter = new VideoReporter();
videoReporter.report();
// ---------- 감지 기능 ----------
Detectable fireDetector = new FireDetector();
fireDetector.detect();
Detectable advancedFireDetector = new AdvancedFireDetector();
advancedFireDetector.detect();
// ---------- 객체에 원하는 기능 장착 및 실행 ----------
factoryCam.setDetector(advancedFireDetector); // setter를 통해서 외부에서 기능 주입
factoryCam.setReporter(videoReporter);
factoryCam.detect(); // 주입된 객체의 메소드 호출
factoryCam.report();
}
}
Generics
custom package 1
package generics.coffee;
public class CoffeeByNumber {
public int waitingNumber;
public CoffeeByNumber(int waitingNumber) {
this.waitingNumber = waitingNumber;
}
public void ready() {
System.out.println("커피 준비 완료 : " + waitingNumber);
}
}
package generics.coffee;
public class CoffeeByNickname {
public String nickname;
public CoffeeByNickname(String nickname) {
this.nickname = nickname;
}
public void ready() {
System.out.println("커피 준비 완료 : " + nickname);
}
}
package generics.coffee;
public class CoffeeByName {
public Object name; // Integer, Double, String, 사용자 정의 클래스 모두 가능
public CoffeeByName(Object name) {
this.name = name;
}
public void ready() {
System.out.println("커피 준비 완료 : " + name);
}
}
package generics.coffee;
public class Coffee <T>{ // 제네릭 클래스
public T name; // 타입 미상
public Coffee(T name) {
this.name = name;
}
public void ready() {
System.out.println("커피 준비 완료 : " + name);
}
}
package generics.coffee;
import generics.user.User;
public class CoffeeByUser <T extends User>{ // 반드시 User 클래스를 상속하는 타입만 사용
public T user;
public CoffeeByUser(T user) {
this.user = user;
}
public void ready() {
System.out.println("커피 준비 완료 : " + user.name);
user.addPoint();
}
}
custom package 2
package generics.user;
public class User {
public String name;
public User(String name) {
this.name = name;
}
public void addPoint() {
System.out.println(this.name + "님, 포인트 적립되었습니다.");
}
}
package generics.user;
public class VIPUser extends User { // User 클래스 상속
public VIPUser(String name) {
super("특별한 " + name);
}
}
main class
package generics;
import generics.coffee.*;
import generics.user.*;
public class Generics {
public static void main(String[] args) {
// ============== 제네릭스 ==============
// 기본 자료형은 Wrapper 클래스 타입으로 변환 필요
Integer[] iArray = {1, 2, 3, 4, 5}; // int → Integer
Double[] dArray = {1.0, 2.0, 3.0, 4.0, 5.0}; // double → Double
Character[] cArray = {'a', 'b', 'c', 'd', 'e'}; // char → Character
String[] sArray = {"A", "B", "C", "D", "E"}; // 참조형은 그대로 사용
printAnyArray(iArray);
printAnyArray(dArray);
printAnyArray(cArray);
printAnyArray(sArray);
// ============== 제네릭 클래스 ==============
// -------- 방법1(타입별 클래스 모두 생성) --------
CoffeeByNumber c1 = new CoffeeByNumber(33); // 정수형만 가능
c1.ready();
CoffeeByNickname c2 = new CoffeeByNickname("유재석"); // 문자열만 가능
c2.ready();
// -------- 방법2(Object로 모든 타입에 적용) --------
CoffeeByName c3 = new CoffeeByName(34);
c3.ready();
int c3Name = (int) c3.name; // Object 타입이라서 형변환 필요
CoffeeByName c4 = new CoffeeByName("박명수");
c4.ready();
// String c4Name = (String) c3.name; // 정수->문자열 변환 에러
// -------- 방법3(제네릭 클래스로 모든 타입에 적용) --------
Coffee<Integer> c5 = new Coffee<>(35); // 자료형 정의
c5.ready();
int c5Name = c5.name;
Coffee<String> c6 = new Coffee<>("조세호");
c6.ready();
String c6Name = c6.name;
// -------- 방법4(제한된 클래스만 받도록 설정) --------
CoffeeByUser<User> c7 = new CoffeeByUser<>(new User("강호동"));
c7.ready();
CoffeeByUser<User> c8 = new CoffeeByUser<>(new VIPUser("서장훈"));
c8.ready();
// -------- 방법5(여러 값 동시에 전달) --------
orderCoffee("김영철");
orderCoffee(36);
orderCoffee("김희철", "아메리카노");
orderCoffee(37, "라떼");
// ============== Wrapper Class ==============
Integer x = 10; // Integer 객체
String y = x.toString(); // toString() 메서드 호출 가능
Double a = 1.0; // Double 객체
int b = a.intValue(); // intValue() 메서드 호출 가능
}
//------------------------------------------------
private static <T> void printAnyArray(T[] array) { // T : Type, V : Value...
for (T t : array) {
System.out.print(t + " ");
}
System.out.println();
}
//------------------------------------------
public static <T> void orderCoffee(T name) { // 값 1개 전달
System.out.println("커피 준비 완료 : " + name);
}
public static <T, V> void orderCoffee(T name, V coffee) { // 값 2개 전달
System.out.println(coffee + " 준비 완료 : " + name);
}
}
(Collection Framework)
ArrayList
import java.util.ArrayList;
import java.util.Collections;
public class ArrayList {
public static void main(String[] args) {
// ===== 어레이 리스트 생성 =====
ArrayList<String> list = new ArrayList<>();
// ===== 데이터 추가 =====
list.add("유재석"); // 인덱스 0
list.add("조세호"); // 인덱스 1
list.add("김종국"); // 인덱스 2
list.add("박명수"); // 인덱스 3
list.add("강호동"); // 인덱스 4
// ===== 데이터 조회 =====
String firstIn = list.get(0); // 인덱스 0 값 조회
// ===== 데이터 삭제 =====
System.out.println("신청 학생 수 : " + list.size()); // 5
list.remove("박명수"); // 인덱스 3 삭제
System.out.println(list.get(3)); // 인덱스 4의 값이 3 자리로 이동
list.remove(list.size() - 1); // 마지막 인덱스 삭제
System.out.println("남은 학생 수 : " + list.size()); // 3
// ===== 데이터 순회 =====
for (String s : list) {
System.out.print(s + " "); // "유재석 조세호 김종국 "
}
// ===== 데이터 정렬 =====
Collections.sort(list); // 사전 순 정렬
for (String s : list) {
System.out.print(s + " "); // "김종국 유재석 조세호 "
}
// ===== 데이터 변경 =====
list.set(0, "이수근"); // 인덱스 0 값 변경
// ===== 데이터 확인 =====
System.out.println(list.indexOf("김종국")); // 방법1. 해당 데이터의 인덱스값 확인
if (list.contains("김종국")) { // 방법2. 리스트 내에 포함 여부를 bool로 반환
System.out.println("수강 신청 성공");
} else {
System.out.println("수강 신청 실패");
}
// ===== 전체 삭제 =====
list.clear();
if (list.isEmpty()) {
System.out.println("리스트가 비었습니다.");
}
}
}
LinkedList
import java.util.Collections;
import java.util.LinkedList;
public class LinkedList {
public static void main(String[] args) {
// ===== 링크드 리스트 생성 =====
LinkedList<String> list = new LinkedList<>();
// ===== 데이터 추가 (마지막 위치) =====
list.add("유재석");
list.add("조세호");
list.add("김종국");
list.add("박명수");
list.add("강호동");
// ===== 데이터 추가 (위치 지정) =====
list.add(1, "김영철"); // 원하는 위치에 데이터 추가
list.addFirst("서장훈"); // 맨 앞에 데이터 추가
list.addLast("김희철"); // 맨 뒤에 데이터 추가
// ===== 데이터 조회 =====
System.out.println(list.get(2)); // 해당 인덱스의 데이터
System.out.println(list.getFirst()); // 첫번째 데이터
System.out.println(list.getLast()); // 마지막 데이터
// ===== 데이터 삭제 =====
list.remove(list.size() - 1); // 해당 인덱스의 데이터
list.removeFirst(); // 첫번째 데이터
list.removeLast(); // 마지막 데이터
// ===== 데이터 정렬 =====
Collections.sort(list);
for (String s : list) {
System.out.println(s);
}
// ===== 데이터 변경 =====
list.set(0, "이수근");
// ===== 데이터 확인 =====
System.out.println(list.indexOf("김종국"));
boolean isIn = list.contains("김종국");
// ===== 전체 삭제 =====
list.clear();
boolean isZero = list.isEmpty()
}
}
HashSet
import java.util.HashSet; // 중복 허용 x, 순서 보장 x
import java.util.LinkedHashSet; // 중복 허용 x, 순서 보장 o
public class HashSet {
public static void main(String[] args) {
// ===== 세트 생성 =====
HashSet<String> set = new HashSet<>();
// ===== 데이터 추가 =====
set.add("삼겹살");
set.add("쌈장");
set.add("소금");
set.add("후추");
set.add("삼겹살");
set.add("깻잎");
set.add("상추");
set.add("삼겹살"); // 8번 추가
System.out.println("총 상품 가지 수 : " + set.size()); // 6
// ===== 데이터 순회 =====
for (String s : set) {
System.out.println(s);
}
// ===== 데이터 확인 =====
if (!set.contains("삼겹살")) {
System.out.println("정육 코너 방문");
}
// ===== 삭제 =====
set.remove("삼겹살");
// ===== 전체 삭제 =====
set.clear();
if (set.isEmpty()) {
System.out.println("집으로 출발");
}
// ===== 링크드 세트 생성 =====
HashSet<Integer> intSet = new LinkedHashSet<>();
intSet.add(1);
intSet.add(13);
intSet.add(5);
for (int i : intSet) {
System.out.println(i); // 1 13 5
}
}
}
HashMap
import java.util.HashMap; // 중복 허용 x, 순서 보장 x
import java.util.LinkedHashMap; // 중복 허용 x, 순서 보장 x
public class HashMap {
public static void main(String[] args) {
// ===== 맵 생성 (Key, Value) =====
HashMap<String, Integer> map = new HashMap<>();
// ===== 데이터 추가 =====
map.put("유재석", 10);
map.put("박명수", 5);
map.put("김종국", 3);
map.put("김종국", 30);
map.put("김종국", 50); // 김종국 -> 마지막 값 50으로 저장됨
System.out.println("총 고객 수 : " + map.size()); // 3
// ===== 데이터 조회 =====
System.out.println("유재석님의 포인트 : " + map.get("유재석")); // 10 (값)
// ===== 데이터 확인 =====
if (map.containsKey("서장훈")) { // 키가 있는지 확인
int point = map.get("서장훈");
map.put("서장훈", ++point);
System.out.println("서장훈님의 누적 포인트 : " + map.get("서장훈"));
} else {
map.put("서장훈", 1);
System.out.println("서장훈님 신규 등록 (포인트 1)");
}
// ----- Key 순회 -----
for (String key : map.keySet()) {
System.out.println(key);
}
// ----- Value 순회 -----
for (int value : map.values()) {
System.out.println(value);
}
// ----- Key & Value 순회 -----
for (String key : map.keySet()) {
System.out.println("고객 이름 : " + key + "\t포인트 : " + map.get(key));
}
// ===== 데이터 삭제 =====
map.remove("유재석");
// ===== 전체 삭제 =====
map.clear();
if (map.isEmpty()) {
System.out.println("남은 고객 수 : " + map.size());
}
// ===== 링크드 맵 생성 =====
HashMap<String, Integer> map = new LinkedHashMap<>();
}
}
Iterator
import java.util.*;
public class Iterator {
public static void main(String[] args) {
// ===== 어레이 리스트에서 이터레이터 사용 =====
List<String> list = new ArrayList<>(); // List 인터페이스로 객체 생성
list.add("유재석");
list.add("(알 수 없음)");
list.add("김종국");
list.add("(알 수 없음)");
list.add("강호동");
list.add("(알 수 없음)");
// ----- 1. for문으로 순회 -----
for (String s : list) {
System.out.println(s);
}
// ----- 2. 이터레이터로 순회 -----
Iterator<String> it = list.iterator(); // 이터레이터 타입으로 받기(Ctrl+Alt+V)
System.out.println(it.next()); // 커서 위치: 0
System.out.println(it.next()); // 커서 위치: 1
it = list.iterator(); // 커서 위치: 0 (처음으로 복원)
while (it.hasNext()) { // 다음에 가져올 데이터가 있으면 true 반환
System.out.println(it.next());
}
it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.contains("(알 수 없음)")) { // 해당 문자열이 포함되어 있으면 true 반환
it.remove(); // 데이터 삭제
}
}
// ===== 세트에서 이터레이터 사용 =====
HashSet<String> set = new HashSet<>();
set.add("유재석");
set.add("박명수");
Iterator<String> itSet = set.iterator();
while (itSet.hasNext()) {
System.out.println(itSet.next());
}
// ===== 맵에서 이터레이터 사용 =====
HashMap<String, Integer> map = new HashMap<>();
map.put("유재석", 10);
map.put("박명수", 5);
// map.iterator() // 키나 값 중 하나를 선택해야 하므로 바로 사용 불가
// ----- Key 순회 -----
Iterator<String> itMapKey = map.keySet().iterator();
while (itMapKey.hasNext()) {
System.out.println(itMapKey.next());
}
// ----- Value 순회 -----
Iterator<Integer> itMapValue = map.values().iterator();
while (itMapValue.hasNext()) {
System.out.println(itMapValue.next());
}
// ----- Key & Value 순회 -----
Iterator<Map.Entry<String, Integer>> itMap = map.entrySet().iterator();
while (itMap.hasNext()) {
System.out.println(itMap.next());
}
}
}
Anonymous Class
custom package
package learnAnonymousClass.converter;
@FunctionalInterface // 함수형 인터페이스 사용을 알리는 에노테이션
public interface Convertible {
void convert(int USD);
}
package learnAnonymousClass.converter;
public class KRWConverter implements Convertible { // Convertible 인터페이스를 클래스로 구현
@Override
public void convert(int USD) {
System.out.println(USD + " 달러 = " + (USD * 1500) + " 원");
}
}
package learnAnonymousClass.converter;
@FunctionalInterface
public interface ConvertibleWithNoParams { // 전달값이 없는 함수형 인터페이스
void convert();
}
package learnAnonymousClass.converter;
@FunctionalInterface
public interface ConvertibleWithTwoParams { // 전달값이 2개인 함수형 인터페이스
void convert(int USD, int KRW);
}
package learnAnonymousClass.converter;
@FunctionalInterface
public interface ConvertibleWithReturn { // 반환값이 있는 함수형 인터페이스
int convert(int USD, int KRW);
}
main class
package learnAnonymousClass;
import learnAnonymousClass.converter.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class AnonymousClass {
public static void main(String[] args) {
// ======== 기본 클래스 ========
Coffee c1 = new Coffee();
c1.order("아메리카노");
// ======== 익명 클래스로 클래스 상속 없이 메소드 재정의 =========
Coffee specialCoffee = new Coffee() { // 해당 객체만 사용하는 일회성 구현
@Override
public void order(String coffee) {
super.order(coffee);
System.out.println("(귓속말) 딸기 케이크는 서비스예요.");
}
@Override
public void returnTray() {
System.out.println("(귓속말) 자리에 두시면 제가 치울게요.");
}
};
specialCoffee.order("바닐라 라떼");
specialCoffee.returnTray();
// ======== 익명 클래스로 추상 클래스 상속 없이 정의 ========
HomeMadeBurger momMadeBurger = getMomMadeBurger();
momMadeBurger.cook();
HomeMadeBurger broMadeBurger = getBroMadeBurger();
broMadeBurger.cook();
// ======== 람다(접근 제어자, 이름, 파라미터 자료형, 반환타입 x) ========
// (반드시 함수형 인터페이스와 사용되어야 하기 때문에 예시만 나열)
() -> { // 전달값 x, 반환값 x
String s = "test";
System.out.println(s);
}
s -> System.out.println(s) // 전달값 o(1개는 괄호 생략), 반환값 x
(x, y) -> x + y // 전달값 o(두 개 이상), 반환값 o
// ======== 함수형 인터페이스(1개의 추상 메소드를 갖는 인터페이스) ========
// ----- KRWConverter 객체로 클래스에서 구현한 convert() 실행 -----
KRWConverter converter = new KRWConverter();
converter.convert(2); // 방법 1
convertUSD(converter, 2); // 방법 2
// ----- Convertible 인터페이스 구현 객체를 람다로 생성 -----
// 직접 전달
convertUSD((USD) -> System.out.println(USD + " 달러 = " + (USD * 1500) + " 원"), 1);
// 변수에 담아서 전달
Convertible convertible = (USD) -> System.out.println(USD + " 달러 = " + (USD * 1500) + " 원");
convertUSD(convertible, 2);
// ----- 전달값이 하나도 없는 경우 -----
ConvertibleWithNoParams c1 = () -> System.out.println("1 달러 = 1500원");
c1.convert();
// ----- 두 줄 이상의 코드가 있는 경우 -----
c1 = () -> {
int USD = 5;
int KRW = 1500;
System.out.println(USD + " 달러 = " + (USD * KRW) + " 원");
};
c1.convert();
// ----- 전달값이 2개인 경우 -----
ConvertibleWithTwoParams c2 = (d, w) -> System.out.println(d + " 달러 = " + (d * w) + " 원");
c2.convert(10, 1400);
// ----- 반환값이 있는 경우 -----
ConvertibleWithReturn c3 = (d, w) -> d * w; // {return d * w}; 를 생략
int result = c3.convert(20, 1400);
System.out.println("20 달러 = " + result + " 원");
// ======== 스트림 생성(일회성 동작, 원본 손상 x)========
// ----- Arrays.stream -----
int[] scores = {100, 95, 90, 85, 80};
IntStream scoreStream = Arrays.stream(scores);
String[] langs = {"python", "java", "javascript", "c", "c++", "c#"};
Stream<String> langStream = Arrays.stream(langs);
// ----- Collection.stream() -----
// 생성 방법 1 (리스트 생성 후 값 하나씩 추가)
List<String> langList = new ArrayList<>();
langList.add("python");
langList.add("java");
// 생성 방법 2 (리스트 생성과 동시에 값 정의)
langList = Arrays.asList("python", "java", "javascript", "c", "c++", "c#");
Stream<String> langListStream = langList.stream();
// ----- Stream.of() -----
Stream<String> langListOfStream = Stream.of("python", "java", "javascript", "c", "c++", "c#");
// ======== 스트림 사용 예제 ========
// 중간 연산 (Intermediate Operation) : filter, map, sorted, distinct, skip , ...
// 최종 연산 (Terminal Operation) : count, min, max, sum, forEach, anyMatch, allMatch, ...
// 90점 이상인 점수만 출력
Arrays.stream(scores).filter(x -> x >= 90).forEach(x -> System.out.println(x));
// Arrays.stream(scores).filter(x -> x >= 90).forEach(System.out::println); 위와 동일
// 90점 이상인 사람의 수
int count = (int) Arrays.stream(scores).filter(x -> x >= 90).count(); // long으로 반환
System.out.println(count);
// 90점 이상인 점수들의 합
int sum = Arrays.stream(scores).filter(x -> x >= 90).sum();
System.out.println(sum);
// 90점 이상인 점수들을 정렬 후 출력
Arrays.stream(scores).filter(x -> x >= 90).sorted().forEach(System.out::println);
// c 로 시작하는 프로그래밍 언어만 출력
Arrays.stream(langs).filter(x -> x.startsWith("c")).forEach(System.out::println);
// java 라는 글자를 포함하는 언어만 출력
Arrays.stream(langs).filter(x -> x.contains("java")).forEach(System.out::println);
// 4글자 이하의 언어를 정렬해서 출력
langList.stream().filter(x -> x.length() <= 4).sorted().forEach(System.out::println);
// 4글자 이하의 언어 중에서 c 라는 글자를 포함하는 언어만 출력
langList.stream()
.filter(x -> x.length() <= 4)
.filter(x -> x.contains("c"))
.forEach(System.out::println);
// 4글자 이하의 언어 중에서 c 라는 글자를 포함하는 언어가 하나라도 있는지 여부
boolean anyMatch = langList.stream()
.filter(x -> x.length() <= 4)
.anyMatch(x -> x.contains("c"));
System.out.println(anyMatch);
// 3글자 이하의 언어들은 모두 c 라는 글자를 포함하는지 여부
boolean allMatch = langList.stream()
.filter(x -> x.length() <= 3)
.allMatch(x -> x.contains("c"));
System.out.println(allMatch);
// 4글자 이하의 언어 중에서 c 라는 글자를 포함하는 언어 뒤에 (어려워요) 라는 글자를 함께 출력
langList.stream()
.filter(x -> x.length() <= 4)
.filter(x -> x.contains("c"))
.map(x -> x + " (어려워요)") // map()으로 데이터 가공
.forEach(System.out::println);
// c 라는 글자를 포함하는 언어를 대문자로 출력
langList.stream()
.filter(x -> x.contains("c"))
.map(String::toUpperCase)
.forEach(System.out::println);
// c 라는 글자를 포함하는 언어를 대문자로 변경하여 새 리스트로 저장, 출력
List<String> langListStartsWithC = langList.stream()
.filter(x -> x.contains("c"))
.map(String::toUpperCase)
.collect(Collectors.toList());
langListStartsWithC.stream().forEach(System.out::println);
}
//-----------------------------------------------
public static HomeMadeBurger getMomMadeBurger() {
return new HomeMadeBurger() {
@Override
public void cook() {
System.out.println("집에서 만드는 엄마표 수제 버거");
System.out.println("재료: 빵, 소고기패티, 해시브라운, 양상추, 마요네즈, 피클");
}
};
}
private static HomeMadeBurger getBroMadeBurger() {
return new HomeMadeBurger() {
@Override
public void cook() {
System.out.println("집에서 만드는 동생표 군대리아");
System.out.println("재료: 빵, 치킨패티, 양배추 샐러드, 딸기잼, 치즈, 삶은 계란");
}
};
}
//-------------------------------------------------------------
public static void convertUSD(Convertible converter, int USD) {
converter.convert(USD); // 추상 메소드
}
}
//----------------------------------------------------------
class Coffee {
public void order(String coffee) {
System.out.println("주문하신 " + coffee + " 나왔습니다.");
}
public void returnTray() {
System.out.println("컵 반납이 완료되었습니다.");
}
}
//----------------------------------------------------------
abstract class HomeMadeBurger { // 추상 클래스
public abstract void cook();
}
Exception Handling
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class ExceptionHandling {
public static void main(String[] args) {
// 오류: 컴파일 오류, 런타임 오류(에러 error, 예외 exception)
// ========= Try Catch(예외 처리) =========
try {
// ArithmeticException
System.out.println(3 / 0);
// ArrayIndexOutOfBoundsException
int[] arr = new int[3];
arr[5] = 100;
// ClassCastException
Object obj = "test";
System.out.println((int) obj);
// NullPointerException
String s = null;
System.out.println(s.toLowerCase());
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) { // 특정 에러 처리
System.out.println("숫자를 확인하세요.");
} catch (ClassCastException e) { // 특정 에러 처리
System.out.println("잘못된 형 변환입니다.");
} catch (Exception e) { // 나머지 에러 일괄처리
System.out.println("에러: " + e.getMessage()); // 예외발생 이유 문자열 출력
e.printStackTrace(); // 예외발생 이유 상세 정보 출력
}
System.out.println("프로그램 정상 종료");
// ========= Throw(예외 발생시키기) =========
int age = 17;
try {
if (age < 19) {
throw new Exception("만 19세 미만에게는 판매하지 않습니다.");
} else {
System.out.println("주문하신 상품 여기 있습니다.");
}
} catch (Exception e) {
e.printStackTrace();
}
// ========= Finally =========
try {
System.out.println("택시의 문을 연다.");
throw new Exception("휴무 택시");
// System.out.println("택시에 탑승한다.");
} catch (Exception e) {
System.out.println("문제 발생 : " + e.getMessage());
} finally {
System.out.println("택시의 문을 닫는다.");
}
try {
System.out.println(3 / 0);
} finally {
System.out.println("프로그램 정상 종료");
}
// ========= Try with resources =========
// bw.close() 직접 호출
MyFileWriter writer1 = null;
try {
writer1 = new MyFileWriter();
writer1.write("아이스크림이 먹고 싶어요");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
writer1.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// bw.close() 자동으로 호출
try (MyFileWriter writer2 = new MyFileWriter()) { // try 구문 괄호에서 객체 정의
writer2.write("빵이 먹고 싶어요");
} catch (Exception e) {
e.printStackTrace();
}
// ========= 사용자 정의 예외 =========
int age = 17; // 만 17세
try {
if (age < 19) {
throw new AgeLessThan19Exception("만 19세 미만에게는 판매하지 않습니다.");
} else {
System.out.println("주문하신 상품 여기 있습니다.");
}
} catch (AgeLessThan19Exception e) {
System.out.println("조금 더 성장한 뒤에 오세요.");
} catch (Exception e) {
System.out.println("모든 예외를 처리합니다.");
}
// ========= Throws(예외 처리 미루기) =========
try { // 메인 메소드에서 writeFile() 호출 후 예외 해결
writeFile();
} catch (IOException e) {
e.printStackTrace();
System.out.println("메인 메소드에서 해결할게요.");
}
}
// 예외를 호출한 곳으로 넘기는 메소드(throws IOException 없으면 내부에서 Try Catch문으로 자체 해결)
public static void writeFile() throws IOException {
FileWriter writer = new FileWriter("test.txt");
throw new IOException("파일 쓰기에 실패했어요!!");
}
}
//-------------------------------------------
class MyFileWriter implements AutoCloseable { // java.lang 패키지의 AutoCloseable 인터페이스
@Override
public void close() throws Exception { // 인터페이스 구현
System.out.println("파일을 정상적으로 닫습니다.");
}
public void write(String line) {
System.out.println("파일에 내용을 입력합니다.");
System.out.println("입력 내용 : " + line);
}
}
//----------------------------------------------
class AgeLessThan19Exception extends Exception { // 사용자 정의 예외(Exception 클래스 상속)
public AgeLessThan19Exception(String message) {
super(message);
}
}
Thread
custom package
package LearnThread.clean;
public class CleanThread extends Thread { // 쓰레드 클래스 상속(다중 상속 불가)
public void run() {
System.out.println("-- 직원 청소 시작 (Thread) --");
for (int i = 2; i <= 10; i += 2) {
System.out.println("(직원) " + i + "번방 청소 중 (Thread)");
}
System.out.println("-- 직원 청소 끝 (Thread) --");
}
}
package LearnThread.clean;
public class CleanRunnable implements Runnable { // 러너블 인터페이스 구현(다른 부모 클래스 상속 가능)
@Override
public void run() {
System.out.println("-- 직원 청소 시작 (Runnable) --");
for (int i = 2; i <= 10; i += 2) {
System.out.println("(직원) " + i + "번방 청소 중 (Runnable)");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("-- 직원 청소 끝 (Runnable) --");
}
}
package chapLearnThread.clean;
public class Room {
public int number = 1;
synchronized public void clean(String name) { // 동기화(한 쓰레드가 점유하는 동안 다른 쓰레드는 대기)
System.out.println(name + " : " + number + "번방 청소 중"); // 직원1 or 직원2 + 방 번호
number++;
}
}
main class
package LearnThread;
import LearnThread.clean.*;
public class Thread {
public static void main(String[] args) {
// =========== Thread ===========
// 1. 하나의 프로세스가 1개의 쓰레드 사용
cleanBySelf(); // 1 2 3 4 5 6 7 8 9 10 청소(직원)
// 2. 하나의 프로세스가 동시에 2개의 쓰레드 사용
CleanThread cleanThread = new CleanThread();
// cleanThread.run(); (메소드를 직접 입력하면 1개의 쓰레드에서 순차 처리됨)
cleanThread.start(); // 1 3 5 7 9 청소(직원)
cleanByBoss(); // 2 4 6 8 10 청소(사장)
// =========== Runnable ===========
CleanRunnable cleanRunnable = new CleanRunnable();
Thread thread = new Thread(cleanRunnable);
thread.start();
cleanByBoss();
// =========== Join ===========
thread.start();
try {
thread.join(2500); // 쓰레드 동작이 끝날 때까지 정해진 시간동안 대기 후 넘어감
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
cleanByBoss();
// =========== Multi Thread ===========
Runnable cleaner1 = new Runnable() {
@Override
public void run() {
System.out.println("-- 직원1 청소 시작 --");
for (int i = 1; i <= 10; i += 2) {
System.out.println("(직원1) " + i + "번방 청소 중");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("-- 직원1 청소 끝 --");
}
};
Runnable cleaner2 = () -> {
System.out.println("-- 직원2 청소 시작 --");
for (int i = 2; i <= 10; i += 2) {
System.out.println("(직원2) " + i + "번방 청소 중");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("-- 직원2 청소 끝 --");
};
Thread cleanerThread1 = new Thread(cleaner1);
Thread cleanerThread2 = new Thread(cleaner2);
cleanerThread1.start();
cleanerThread2.start();
// =========== Synchronization ===========
Room room = new Room();
Runnable cleaner1 = new Runnable() {
@Override
public void run() {
System.out.println("-- 직원1 청소 시작 --");
for (int i = 1; i <= 5; i++) {
room.clean("직원1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (i == 2) { // 예외 발생 시에는 해당 쓰레드만 종료되고 다른 쓰레드에는 영향 x
throw new RuntimeException("못해먹겠다!!");
}
}
System.out.println("-- 직원1 청소 끝 --");
}
};
Runnable cleaner2 = () -> {
System.out.println("-- 직원2 청소 시작 --");
for (int i = 1; i <= 5; i++) {
room.clean("직원2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("-- 직원2 청소 끝 --");
};
Thread cleanerThread1 = new Thread(cleaner1);
Thread cleanerThread2 = new Thread(cleaner2);
cleanerThread1.start(); // 두 직원이 1~10번 순으로 돌아가며 각각 5개 방을 청소
cleanerThread2.start();
}
//--------------------------------
public static void cleanBySelf() {
System.out.println("-- 혼자 청소 시작 --");
for (int i = 1; i <= 10; i++) {
System.out.println("(혼자) " + i + "번방 청소 중");
}
System.out.println("-- 혼자 청소 끝 --");
}
public static void cleanByBoss() {
System.out.println("-- 사장 청소 시작 --");
for (int i = 1; i <= 10; i += 2) {
System.out.println("(사장) " + i + "번방 청소 중");
try { // join()으로 대기할 경우 사용
Thread.sleep(1000); // 지정한 시간 동안 멈춤
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("-- 사장 청소 끝 --");
}
}
I/O, File
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class IOAndFile {
public static void main(String[] args) {
// ========== Input ==========
Scanner sc = new Scanner(System.in);
System.out.println("이름을 입력하세요");
String name = sc.next(); // 입력받은 값을 띄어쓰기로 한 단어씩 받음
System.out.println("혈액형을 입력하세요");
String bloodType = sc.nextLine(); // 입력받은 값을 하나의 문장으로 모두 받음
System.out.println("키를 입력하세요");
int height = sc.nextInt(); // 입력된 값(문자열)을 정수형으로 변경
System.out.println("몸무게를 입력하세요");
double weight = sc.nextDouble();
// ========== Output ==========
// 방법 1. System.out.format();
// 방법 2. System.out.printf(); (souf 입력하면 자동으로 완성)
// 정수
System.out.printf("%d%n", 1); // 1
System.out.printf("%d %d %d%n", 1, 2, 3); // 1 2 3
System.out.printf("%d%n", 1234); // 1234
System.out.printf("%6d%n", 1234); // __1234 (공간 6자리 확보 후 출력)
System.out.printf("%06d%n", 1234); // 001234 (공간 6자리 확보 후 공백을 0으로 채우기)
System.out.printf("%6d%n", -1234); // _-1234
System.out.printf("%+6d%n", 1234); // _+1234 (항상 +- 기호 표시)
System.out.printf("%-6d%n", 1234); // 1234__ (공간 6자리 확보 후 왼쪽 정렬 출력)
System.out.printf("%,15d%n", 1000000000); // __1,000,000,000 (세자리마다 콤마로 구분)
// 실수
System.out.printf("%f%n", Math.PI); // 3.141593 (일반 출력)
System.out.printf("%.2f%n", Math.PI); // 3.14 (소수점 둘째자리까지 반올림)
System.out.printf("%6.2f%n", Math.PI); // __3.14 (공간 6자리 확보 후 소수점 둘째자리)
System.out.printf("%06.2f%n", Math.PI); // 003.14 (공간 6자리 확보 후 공백을 0으로 채우기)
System.out.printf("%-6.2f%n", Math.PI); // 3.14__ (왼쪽 정렬)
System.out.printf("%+6.2f%n", Math.PI); // _+3.14 (항상 +- 기호 표시)
// 문자열
System.out.printf("%s%n", "Java"); // Java (일반 출력)
System.out.printf("%6s%n", "Java"); // __Java (공간 6자리 확보 후 우측 정렬)
System.out.printf("%-6s%n", "Java"); // Java__ (공간 6자리 확보 후 좌측 정렬)
System.out.printf("%6.2s%n", "Java"); // ____Ja (공간 6자리 확보 후 우측 정렬해서 2글자 출력)
System.out.printf("%-6.2s%n", "Java"); // Ja____ (공간 6자리 확보 후 왼쪽 정렬해서 2글자 출력)
// 응용(공백으로 가독성 있게 정렬)
System.out.println("이름 영어 수학 평균");
System.out.printf("%-6s %4d %4d %6.1f%n", "강백호", 90, 80, 85.0);
System.out.printf("%-6s %4d %4d %6.1f%n", "서태웅", 100, 100, 100.0);
System.out.printf("%-6s %4d %4d %6.1f%n", "채치수", 95, 100, 97.5);
// ========== File ==========
String fileName = "test.txt"; // 파일명 정의
File file = new File(fileName); // 파일 객체 생성
try {
file.createNewFile(); // (파일이 없는 경우에만) 생성
if (file.exists()) { // 파일 존재 여부 확인
System.out.println("파일 이름 : " + file.getName());
System.out.println("파일 절대 경로 : " + file.getAbsolutePath());
System.out.println("파일 크기(Byte) : " + file.length());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
// ========== Folder ==========
// 단일 폴더 생성
String folderName = "A";
File folder = new File(folderName);
folder.mkdir(); // 단일 폴더 생성
if (folder.exists()) {
System.out.println("폴더가 존재합니다: " + folder.getAbsolutePath());
}
// 하위 구조의 폴더 여러개 생성
// 윈도우 : C:\\Users\\Nadocoding\\Desktop
// 맥 : /Users/Nadocoding/Desktop
// 모든OS : "A" + File.separator + "B" + File.separator + "C"
folder = new File(folderName);
folderName = "A/B/C";
folder.mkdirs(); // 부모 폴더가 존재하지 않는 경우 사용
if (folder.exists()) {
System.out.println("폴더가 존재합니다: " + folder.getAbsolutePath());
}
// ========== File & Folder ==========
// 현재 위치(상대 경로): "."
// 현재 위치(절대 경로): "C:\\Users\\Nadocoding\\Desktop\\JavaWorkspace\\src\\IOAndFile";
String folder = "src/IOAndFile"; // 상대 경로
File filesAndFolders = new File(folder);
System.out.println("현재 폴더 경로: " + filesAndFolders.getAbsolutePath());
for (File file : filesAndFolders.listFiles()) { // 모든 폴더와 파일 정보
if (file.isFile()) {
System.out.println("(파일) " + file.getName());
} else if (file.isDirectory()) {
System.out.println("(폴더) " + file.getName());
}
}
// ========== Read & Write File ==========
// BufferedWriter로 쓰기 (FileWriter에 append=true 설정 시 덮어쓰지 않고 그대로 이어씀)
try(BufferedWriter bw = new BufferedWriter(new FileWriter("goodjob.txt", true))) {
bw.write("1. 이제 거의 끝이 보여요."); // 작성
bw.newLine(); // 줄바꿈
bw.write("2. 여기까지 오신 여러분들 정말 대단해요!");
bw.newLine();
bw.write("3. 조금만 더 힘내요!");
} catch (IOException e) {
throw new RuntimeException(e);
}
// BufferedReader로 읽기
try (BufferedReader br = new BufferedReader(new FileReader("goodjob.txt"))) {
String line;
while((line = br.readLine()) != null) { // 한 줄씩 읽어와서 출력
System.out.println(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
// ========== Delete File & Folder ==========
// 파일 삭제
File file = new File("goodjob.txt");
if (file.exists()) {
if (file.delete()) {
System.out.println("파일 삭제 성공: " + file.getName());
} else {
System.out.println("파일 삭제 실패: " + file.getName());
}
}
// 단일 폴더 삭제(하위 폴더가 없을 때만 가능)
File folder = new File("A"); // "A/B/C" 의 경우 가장 하위 폴더 C만 삭제
if (folder.exists()) {
if (folder.delete()) {
System.out.println("폴더 삭제 성공: " + folder.getAbsolutePath());
} else {
System.out.println("폴더 삭제 실패: " + folder.getAbsolutePath());
}
}
// 해당 폴더의 모든 하위 폴더까지 함께 삭제
if (deleteFolder(folder)) {
System.out.println("*폴더 삭제 성공: " + folder.getAbsolutePath());
} else {
System.out.println("*폴더 삭제 실패: " + folder.getAbsolutePath());
}
}
//-----------------------------------------------
public static boolean deleteFolder(File folder) {
if (folder.isDirectory()) { // 폴더만 확인
for (File file : folder.listFiles()) { // 해당 폴더 내 모든 하위 목록들 하나씩 확인
deleteFolder(file); // 재귀 호출
}
}
System.out.println("삭제 대상: " + folder.getAbsolutePath());
return folder.delete();
}
}
『나도코딩의 자바 기본편 - 풀코스 (20시간)』, https://www.inflearn.com/course/%EB%82%98%EB%8F%84%EC%BD%94%EB%94%A9-%EC%9E%90%EB%B0%94-%EA%B8%B0%EB%B3%B8/dashboard?cid=329986
Leave a comment