오늘의 코드
package edu.java.inner01;
// 변수 선언 :
// 1. 멤버 변수(필드) : 클래스에서 선언된 변수
// - 클래스 내부 어느 곳에서나 사용할 수 있는 변수
// - 수식어(public, private, static, ...)를 사용할 수 있음
// 2. 지역 변수 : 메소드 안에서 선언하는 변수
// - 지역 변수가 선언된 곳에서 변수가 속한 블록({})이
// 끝나는 곳까지 사용할 수 있는 변수
// - 접근 수식어(public, private, static, ...)를 사용할 수 없음
// - final은 가능
// 내부 클래스(Inner Class) : 다른 클래스 내부에서 정의된 클래스
// 1. 멤버 내부 클래스(member inner class)
// - 멤버 변수를 선언하는 위치에서 정의하는 내부 클래스
// - 외부 클래스의 인스턴스가 생성되어야만 객체 생성이 가능함
// 2. static 내부 클래스(static inner class), 중첩 클래스(nested class)
// - 멤버 변수를 선언하는 위치에서 static으로 정의한 내부 클래스
// - 외부 클래스의 인스턴스를 생성하지 않아도 객체 생성이 가능함
// - 외부 클래스와 상관이 없는 클래스라고 생각해도 됨
// 3. 지역 내부 클래스(local inner class) : 메소드 안에서 정의하는 클래스
// 4. 익명 클래스(Anonymous class) : 이름이 없는 내부 클래스
// -> 람다 표현식 사용 가능
public class InnerMain01 {
public static void main(String[] args) {
// 외부 클래스 OuterClass의 인스턴스를 생성
OuterClass out1 = new OuterClass(100);
out1.display();
// 내부 클래스의 인스턴스 생성:
// (외부 클래스 이름).(내부 클래스 이름) 변수이름 =
// (외부 클래스의 참조변수).new (내부 클래스 생성자)();
OuterClass.InnerClass inner1 = out1.new InnerClass(200); // 사람을 만들고 심장을 이식하는 형태
inner1.printValues();
System.out.println();
// 내부 클래스의 인스턴스를 통한 외부 클래스 멤버 변수 변경
inner1.setOuterValue(300);
inner1.printValues();
out1.display();
} // end main()
} // end InnerMain01
package edu.java.inner01;
public class OuterClass {
// 멤버 변수
private int value1;
// 생성자
public OuterClass(int v) {
this.value1 = v;
}
// 메소드
public void display() {
System.out.println("value1 = " + value1);
}
class InnerClass {
private int value2;
public InnerClass(int v) {
this.value2 = v;
}
// 외부 클래스의 멤버 변수는 내부 클래스에서 직접 사용이 가능
public void setOuterValue(int value) {
value1 = value;
}
public void printValues() {
// 외부 클래스의 멤버 변수 출력
System.out.println("outer value : " + value1);
// 내부 클래스의 멤버 변수 출력
System.out.println("inner value : " + value2);
}
} // end InnerClass
} // end OuterClass
package edu.java.inner02;
// 멤버 내부 클래스(member inner class)를 사용하는 경우
// 상속관계로는 묶을 수 없지만,
// A라는 객체가 생성된 이후에만 존재할 수 있는 B라는 객체가 있다면
// B를 A의 내부 클래스로 정의
// (예) 자동차 - 타이어, PC- CPU/RAM 등
public class Car {
private String name;
public Car(String name) {
this.name = name;
}
// 멤버 내부 클래스(member inner class)
public class Tire {
private int size;
public Tire(int size) {
this.size = size;
}
public void display() {
System.out.println("--- 자동차 정보 ---");
System.out.println("자동차 이름 : " + name);
System.out.println("타이어 크기 : " + size);
} // end display()
} // end Tire
} // end Car
package edu.java.inner02;
public class InnerMain02 {
public static void main(String[] args) {
Car car1 = new Car("롤스로이스 보트 테일");
Car.Tire tire = car1.new Tire(20);
tire.display();
System.out.println();
Car car2 = new Car("제네시스");
Car.Tire tire2 = car2.new Tire(15);
tire2.display();
} // end main()
} // end InnerMain02
package edu.java.inner03;
// 외부 클래스
class OuterTest {
private int value;
public OuterTest(int value) {
this.value = value;
}
public void printValue() {
System.out.println("value = " + value);
}
// 멤버 내부 클래스
class InnerTest {
private int value;
public InnerTest(int value) {
this.value = value;
}
// 외부 클래스의 멤버 변수 이름과
// 내부 클래스의 멤버 변수 이름이 같을때
// 외부 클래스의 멤버 변수를 참조하는 방법
public void displayValues() {
System.out.println("value = " + value);
System.out.println("this.value = " + this.value);
System.out.println("OuterTest.this.value = "
+ OuterTest.this.value );
}
} // end InnerTest
} // end OuterTest
public class InnerMain03 {
public static void main(String[] args) {
OuterTest out = new OuterTest(100);
out.printValue();
System.out.println();
OuterTest.InnerTest inner = out.new InnerTest(200);
inner.displayValues();
} // end main()
} // end InnerMain03
package edu.java.inner04;
// 외부 클래스
class OuterClass {
int value;
static int count = 0;
public OuterClass(int value) {
this.value = value;
}
// static 내부 클래스(중첩 클래스, nested class)
static class NestedClass {
private String name;
public NestedClass(String name) {
this.name = name;
}
public void display() {
// System.out.println("value = " + value);
// 외부 클래스의 static이 아닌 변수는 참조할 수 없음!
System.out.println("count = " + count);
// 외부 클래스에서 static으로 선언된 변수는 참조 가능
System.out.println("name = " + name);
} // end display()
} // end NestedClass
} // end OuterClass
public class InnerMain04 {
public static void main(String[] args) {
// static 멤버 변수 사용 : (클래스이름).(변수이름)
OuterClass.count = 100;
System.out.println(OuterClass.count);
// 중첩 클래스(static 클래스)
// (외부클래스 이름).(중첩클래스 이름) 변수이름 =
// new (외부클래스 이름).(내부클래스 이름)();
OuterClass.NestedClass nest =
new OuterClass.NestedClass("Peter");
nest.display();
} // end main()
} // end InnerMain04
package edu.java.inner05;
class OuterClass {
private int value;
public OuterClass(int value) {
this.value = value;
} // end OuterClass
public void test() { // 지역 변수또한 이 안에서 만 사용
int x = 123; // 지역 변수(local variable)
// 지역 변수를 선언하는 위치에서 정의하는 클래스 : 지역 클래스
// 여기서 생성하고 여기서 부를려고 만든 것
class LocalClass {
private int value2; // 지역클래스의 멤버 변수
// 지역 클래스의 생성자
public LocalClass(int value2) {
this.value2 = value2;
}
// 지역 클래스의 메소드
public void display() {
// 외부 클래스의 멤버 변수를 참조 가능
System.out.println("value = " + value);
// 메소드의 지역 변수 사용 가능
System.out.println("x = " + x);
// 지역 클래스의 멤버 변수를 참조 가능
System.out.println("value2 = " + value2);
} // end display()
} // end LocalClass
// 지역 클래스의 인스턴스 생성 - 메소드 안에서만 가능(필수!!!)
LocalClass local = new LocalClass(1234);
// 일회용품 사용하고 버리는 형식이다.
local.display();
} // end test()
} // end OuterClass
public class InnerMain05 {
public static void main(String[] args) {
OuterClass outer = new OuterClass(100);
outer.test();
} // end main()
} // end InnerMain05
package edu.java.inner06;
interface PersonInterface {
public abstract void showInfo();
public abstract void hello();
}
class Person {
private String name; // 멤버 변수
// 생성자
public Person(String name) {
this.name = name;
}
// 메소드
public PersonInterface setAge(int age) { // 리턴 타입 : PersonInterface
// 지역클래스
class PersonWithAge implements PersonInterface {
private int age; // 지역 클래스의 멤버 변수
public PersonWithAge(int age) {
this.age = age;
}
@Override
public void showInfo() {
System.out.println("이름 : " + name);
System.out.println("나이 : " + age);
}
@Override
public void hello() {
System.out.println("안녕하세요!");
}
} // end PersonWithAge
// 지역 클래스 객체(내용)을 모두 저장
PersonWithAge instance = new PersonWithAge(age);
// 지역 클래스 객체(내용)을 리턴
return instance;
} // end setAge()
} // end Person
public class InnerMain06 {
public static void main(String[] args) {
// 지역 클래스의 메소드들을 외부에서 사용하는 사용하는 방법 :
// 1. 지역 클래스의 메소드들을 선언한 인터페이스를 정의
// 2. 지역 클래스가 인터페이스를 구현하도록 정의
// 3. 다형성 사용하여 메소드의 리턴타입으로 인터페이스를 사용할 수 있음
Person p = new Person("목쌤");
PersonInterface instance = p.setAge(24);
instance.showInfo();
instance.hello();
} // end main()
} // end InnerMain06
package edu.java.inner07;
interface Hello {
public abstract void hello();
} // end Hello
class Person implements Hello {
@Override
public void hello() {
System.out.println("안녕?");
}
} // end Person
class Dog implements Hello {
@Override
public void hello() {
System.out.println("멍멍?");
}
} // end Dog
public class InnerMain07 {
public static void main(String[] args) {
Person p1 = new Person(); // 원래 형태1
p1.hello();
Hello p2 = new Person(); // 원래 형태2 (다형성)
p2.hello();
Hello dog = new Dog(); // 원래 형태3
dog.hello();
// 코드가 길다! (인터페이스는 인스턴스 생성이 불가능)
// 하지만 상속받아서 사용은 가능하다(뭔이런)
// - 여기서 바로 implements 처리를 한 것(이것이 익명 클래스)
Hello cat = new Hello() {
@Override
public void hello() {
System.out.println("야옹?");
}
};
cat.hello();
// new Hello() { 본체 }
// 본체 : Hello interface를 구현하는 클래스의 내용(객체)
// ******************* 익명 클래스를 사용하는 이유 *****************************
// - 인터페이스의 메소드가 한 개인 경우,
// 클래스 외부에서 선언하여 implements하지 않고 사용하기 위해
// - 익명 클래스를 사용하면 클래스를 외부에서 생성할 필요가 없음
// - 객체를 한 번 생성하고 더 이상 생성하지 않을 경우 사용
} // end main()
} // end InnerMain07
package edu.java.inner08;
public class Button {
// 내부 인터페이스
public interface OnClickListener {
public abstract void onClick();
}
private OnClickListener listener;
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
public void click() {
listener.onClick();
}
}
package edu.java.inner08;
class OkListener implements Button.OnClickListener{
@Override
public void onClick() {
System.out.println("<<< 확인 >>>");
}
} // end OkListener
class CancelListener implements Button.OnClickListener {
@Override
public void onClick() {
System.out.println("<<< 취소 >>>");
}
} // end CancelListener
public class InnerMain08 {
public static void main(String[] args) {
Button btnOk = new Button();
Button.OnClickListener okListener = new OkListener();
btnOk.setOnClickListener(okListener);
btnOk.click();
System.out.println();
Button btnCancel = new Button();
btnCancel.setOnClickListener(new CancelListener());
btnCancel.click();
System.out.println();
Button btn = new Button();
Button.OnClickListener l = new Button.OnClickListener() {
@Override
public void onClick() {
System.out.println("테스트 클릭");
}
};
btn.setOnClickListener(l);
btn.click();
btn.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick() {
System.out.println("테스트 클릭2");
}
});
btn.click();
} // end main()
} // InnerMain08
람다
package edu.java.lambda01;
// FunctionalInterface : 추상 메소드가 하나뿐인 메소드
// 람다(lambda) 표현식은 function interface만 사용 가능
@FunctionalInterface
public interface Adder {
public abstract double add(double x, double y);
}
package edu.java.lambda01;
class AdderImple implements Adder {
@Override
public double add(double x, double y) {
System.out.println(x + ", " + y);
return x + y;
} // end add()
} // end AdderImple
public class LambdaMain01 {
public static void main(String[] args) {
System.out.println("[1] 인터페이스를 구현하는 클래스 사용");
AdderImple adder1 = new AdderImple();
double result = adder1.add(2.0, 4.0);
System.out.println("result = " + result);
System.out.println("[2] 다형성 사용");
Adder adder2 = new AdderImple();
result = adder2.add(1.1, 2.2);
System.out.println("result = " + result);
System.out.println("[3] 익명 클래스 사용");
Adder adder3 = new Adder() {
@Override
public double add(double x, double y) {
return x + y;
}
}; // end Adder()
result = adder3.add(2.0, 1.0);
System.out.println("result = " + result);
System.out.println("[4] 람다 클래스 사용");
Adder adder4 = (x, y) -> x + y;
result = adder4.add(1.1, 2.2);
System.out.println("result = " + result);
} // end main()
} // end LambdaMain01
package edu.java.lambda02;
@FunctionalInterface
interface Test1 {
public abstract void testPrint();
}
@FunctionalInterface
interface Test2 {
public abstract void testPrint(int n);
}
public class LambdaMain02 {
public static void main(String[] args) {
System.out.println("- 익명 클래스, 람다 표현식 연습 -");
// 람다(Lambda) 표현식
// (매개변수1, 매개변수2, ..) -> { 실행문; 리턴; }
// 매개변수와 리턴타입 형태는 인터페이스의 추상메소드에 따라 결정됨
// 인터페이스 변수이름 = 람다 표현식
// 1. "익명 클래스 연습!"을 출력하는 익명 클래스 생성 및 출력하기
Test1 test1 = new Test1() {
@Override
public void testPrint() {
System.out.println("익명 클래스 연습!");
}
};
test1.testPrint();
// 2. "람다 표현식 연습!"을 출력하는 람다 표현식 생성 및 출력하기
Test1 test2 = () -> {
System.out.println("람다 표현식 연습!");
};
test2.testPrint();
// 3. 정수 하나를 입력받아서 "입력한 숫자는 : 100"을 출력하는
// 익명 클래스 생성 및 출력하기
Test2 test3 = new Test2() {
@Override
public void testPrint(int n) {
System.out.println("입력한 숫자는 : " + n);
}
};
test3.testPrint(100);
// 4. 정수 하나를 입력받아서 "입력한 숫자는 : 200"을 출력하는
// 람다 표현식 생성 및 출력하기
Test2 test4 = (n) -> {
System.out.println("입력한 숫자는 : " + n);
};
test4.testPrint(200);
} // end main()
} // end LambdaMain02
package edu.java.lambda03;
@FunctionalInterface
interface Test1 {
public abstract void printMax(int x, int y);
} // end Test1
@FunctionalInterface
interface Test2 {
public abstract int findMax(int x, int y);
} // end Test2
public class LambdaMain03 {
public static void main(String[] args) {
// 람다 표현식을 이용하여 구현
Test1 test1 = (x, y) -> {
int max;
if(x > y) {
max = x;
} else {
max = y;
}
System.out.println("최대값 : " + max);
};
test1.printMax(100, 101);
Test2 test2 = (x, y) -> (x > y) ? x : y;
System.out.println("최대값 : " + test2.findMax(10, 5));
} // end main()
} // end LambdaMain03
package edu.java.exception01;
// 컴파일 에러 : 소스코드 빌드 시 발생하는 에러
// -> 실행 파일이 만들어지지 않기 때문에 실행할 수 없음
// 예외(Exception) :
// -> 소스코드를 빌드할 때는 에러가 없지만,
// 프로그램을 수행할 때 발생하는 오류
// 논리적 오류 :
// -> 컴파일 에러도 없고, 실행할 때 예외도 발생하지 않지만
// 논리적인 문제 때문에 원하는 실행 결과가 나오지 않는 경우
public class ExceptionMain01 {
public static void main(String[] args) {
// int 123; // 컴파일 에러
// int n = 123 / 0; 예외
int result = findMax(20, 1);
System.out.println(result);
} // end main()
public static int findMax(int x, int y) {
if(x > y) {
return x;
} else {
return y;
}
}
} // end ExceptionMain01
package edu.java.exception02;
import java.util.Scanner;
public class ExceptionMain02 {
public static void main(String[] args) {
System.out.println("예외 사례");
Scanner sc = new Scanner(System.in);
// int n1 = sc.nextInt();
// int n2 = sc.nextInt();
//
// if(n2 != 0) {
// int result = n1 / n2;
// System.out.println("result = " + result);
// } else {
// System.out.println("n2의 값이 0이 아닌 값을 입력하세요.");
// }
// 예외 처리 : try-catch 구문
// - 예외 발생 상황에 대해 처리해주는 기능
// try {
// 정상적인 실행 문장들;
// } catch (예외클래스 변수이름) {
// 예외 상황일 때 실행할 문장들;
// }
try {
System.out.println("try 내부");
System.out.println("n3 입력>");
int n3 = sc.nextInt();
System.out.println("n4 입력>");
int n4 = sc.nextInt();
int result = n3 / n4;
System.out.println("result = " + result);
} catch (Exception e) {
System.out.println("예외 발생 : " + e.toString());
}
System.out.println("프로그램 종료");
sc.close();
} // end main()
} // end ExceptionMain02
package edu.java.exception03;
public class ExceptionMain03 {
public static void main(String[] args) {
try {
System.out.println("try 내부");
int[] array = new int[10];
array[13] = 100;
System.out.println(array[10]);
} catch (Exception e) { // 모든 예외 처리
System.out.println("예외 메시지 : " + e.toString());
}
System.out.println("프로그램 종료");
} // end main()
} // end ExceptionMain03
package edu.java.exception04;
public class ExceptionMain04 {
public static void main(String[] args) {
// Exception : 예외 처리를 위한 클래스
// |_ ArithmeticException
// |_ NullPointerException
// |_ ...
System.out.println("예외 메시지 출력");
try {
System.out.println("try 내부");
String name = null;
System.out.println("문자열 길이 : " + name.length());
} catch (NullPointerException e) {
System.out.println("예외 메시지 : " + e.toString());
}
System.out.println("프로그램 종료");
} // end main()
} // end ExceptionMain04
package edu.java.exception05;
public class ExceptionMain05 {
public static void main(String[] args) {
// 하나의 try-catch 구문에서 여러 개의 catch를 사용하는 방법 1
try {
int x = 12345;
int y = 0;
int result = x / y;
System.out.println("result = " + result);
int[] array = new int[10];
array[11] = 10;
System.out.println("array[11] = " + array[11]);
String name = null;
System.out.println("문자열 길이 : " + name.length());
} catch (ArithmeticException e) { // e 변수에 예외에 대한 정보가 저장됨
System.out.println("산술연산 예외 : " + e.toString());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("배열 인덱스 예외 : " + e.toString());
} catch (Exception e) {
System.out.println("NullPointer 예외 : " + e.toString());
}
// 하나의 try 구문에서 여러 개의 catch를 사용하는 경우,
// 자식 클래스의 Exception을 먼저 catch 구문에서 사용하고
// 가장 마지막에 최상위 부모 클래스인 Exception을 사용해야함
} // end main()
} // end ExceptionMain05
package edu.java.exception06;
public class ExceptionMain06 {
public static void main(String[] args) {
// 하나의 try 구문에서 여러 개의 catch를 사용하는 방법2 : Java 7 버전부터
// try {
// 정상 상황일 때 사용할 코드;
// } catch ( Ex1 | Ex2 | Ex3 | ... e) {
// 예외 상황일 때 실행할 코드
// } catch (Exception e) { ... }
try {
System.out.println("try 시작");
int result = 123 / 0;
int[] array = new int[10];
array[10] = 10;
System.out.println("try 끝");
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("예외 : " + e.toString());
} catch (Exception e) {
System.out.println("예외 : " + e.toString());
}
} // end main()
} // end ExcetionMain06
package edu.java.exception07;
import java.util.Scanner;
public class ExceptionMain07 {
public static void main(String[] args) {
System.out.println("try-catch-finally");
// try {
// 정상적인 경우에 실행할 코드들;
// } catch (Exception e) {
// 예외 상황일 때 실행할 코드;
// } finally {
// 정상적인 경우든, 예외 상황이든 상관없이 항상 실행할 코드
// }
Scanner sc = null;
try {
sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
int result = a / b;
System.out.println("try 끝 : result = " + result);
} catch (Exception e) {
System.out.println("예외 : " + e.toString());
} finally {
System.out.println("finally : 언제 실행될까요?");
sc.close();
}
System.out.println("프로그램 종료");
} // end main()
} // end ExceptionMain07
package edu.java.exception08;
import java.util.Scanner;
public class ExceptionMain08 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(true) {
try {
System.out.println("메뉴 선택");
int choice = Integer.parseInt(sc.next());
System.out.println("choice : " + choice);
break;
} catch (Exception e) {
System.out.println("숫자가 아닙니다. : ");
}
}
} // end main()
} // ExceptionMain08
Thread사용
package edu.java.thread01;
// OS(운영체제) : 사용자의 하드웨어, 시스템 리소스를 제어하고
// 프로그램에 대한 서비스를 지원하는 시스템 소프트웨어
// 운영체제 종류 : Windows, Linux, Unix, MacOS
// 프로세서 : 운영체제 내에서 연속적으로 실행되고 있는 프로그램
// 쓰레드(Thread) : 하나의 작업을 순차적으로 진행하는 실행 코드
// 멀티 쓰레드 프로그램 :
// - 하나의 프로그램(프로세스)에서 여러 개의 쓰레드를 동작하는 프로그램
// - 예) 채팅 프로그램 : 채팅 + 파일 전송
//자바에서 쓰레드를 생성하고 사용하는 방법1 :
//1. Thread 클래스를 상속받는 새로운 클래스 정의(extends Thread)
//2. 정의한 새로운 클래스 안에서 run() 메소드를 override
//-> run() : 쓰레드가 해야 할 기능 구현
//3. 정의한 클래스의 인스턴스를 생성
//4. 생성된 인스턴스에서 start() 메소드를 호출
//-> 쓰레드가 가져야 할 메모리 공간을 확보, 스케쥴링을 위해 쓰레드 등록, 초기화
//-> 쓰레드의 run() 메소드가 자동으로 실행됨
//1. Thread 클래스를 상속받는 새로운 클래스 정의(extends Thread)
class MyThread extends Thread {
// 멤버 변수
private String msg;
// 생성자
public MyThread(String msg) {
this.msg = msg;
}
// 2. 정의한 새로운 클래스 안에서 run() 메소드를 override
// -> run() : 쓰레드가 해야 할 기능 구현
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i + " : " + msg);
try {
sleep(100); // 0.1초 동안 일을 멈춤(delay)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} // end MyThread
// 독립적인 존재가 같이 가기 때문에 순차적으로 출력되지 않는다.
public class ThreadMain01 {
// 메인 함수도 쓰레드에서 동작 : 메인 쓰레드
public static void main(String[] args) {
// 3. Thread를 상속받는 클래스(MyThread)의 인스턴스 생성
MyThread th1 = new MyThread("안녕");
// 4. 생성된 인스턴스에서 start() 메소드를 호출 -> 쓰레드 실행
th1.start();
MyThread th2 = new MyThread("Hello");
th2.start();
System.out.println("<< 메인 쓰레드 종료 >>");
} // end main()
} // end ThreadMain01