https://www.acmicpc.net/problem/1085

 

1085번: 직사각형에서 탈출

한수는 지금 (x, y)에 있다. 직사각형은 각 변이 좌표축에 평행하고, 왼쪽 아래 꼭짓점은 (0, 0), 오른쪽 위 꼭짓점은 (w, h)에 있다. 직사각형의 경계선까지 가는 거리의 최솟값을 구하는 프로그램

www.acmicpc.net

import java.util.Scanner;

public class J1085 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();
        int y = sc.nextInt();
        int w = sc.nextInt();
        int h = sc.nextInt();

        int left = x;
        int right = w-x;
        int up = h-y;
        int down = y;

        int[] arr = {left, right, up, down};
        int min = arr[0];
        for(int num : arr) {
            if(num < min) {
                min = num;
            }
        }
        System.out.print(min);
    }
}

 

- Scanner 객체로 현재 위치(x, y)와 오른쪽 끝 점(w, h)을 입력받음

- 직사각형의 테두리까지의 거리를 각각 left, right, up, down으로 저장

- 각 거리를 배열에 넣고, 반복문을 통해 최소값을 min으로 저장 후 출력

'Software > JAVA' 카테고리의 다른 글

[JAVA] Day14. 멀티 스레딩  (2) 2023.01.18
[JAVA] Day13. 파일 입출력  (0) 2023.01.18
[JAVA] Day12. 제네릭과 컬렉션  (0) 2023.01.11
[JAVA] Day11. 자바 그래픽  (5) 2023.01.10
[JAVA] Day10. 스윙 컴포넌트  (0) 2023.01.09

1. 스레드

- 다중 스레딩 : 하나의 프로그램이 동시에 여러 가지 작업을 할 수 있도록 하는 것

- 스레드 : 각각의 작업, 동일한 데이터를 공유함

- 프로세스 : 자신만의 데이터를 가짐

- 프로그램을 보다 빠르게 실행하기 위해 멀티 스레딩 사용

 

2. 멀티 스레딩의 문제점

- 여러 스레드들이 같은 데이터를 공유하게 되면 '동기화' 문제 발생

 

3. 스레드 생성과 실행

Thread t = new Thread();
t.start();

 

3-1) 스레드 생성: Thread 클래스 상속하는 방법

- Thread 클래스를 상속받은 후에 run() 메소드 재정의

- run 메소드 안에 작업 기술

- Thread 객체 생성하고 start() 호출해서 스레드 시작

class MyThread extends Thread {
    public void run() {
        for (int i = 0; i <= 10; i++)
            System.out.print(i + " ");
        
    }
}

public class MyThreadTest {
    public static void main(String args[]) {
        Thread t = new MyThread();
        t.start();
    }
}

// 0 1 2 3 4 5 6 7 8 9 10

 

3-2) 스레드 생성: Runnable 인터페이스 구현하는 방법

- Runnable 인터페이스를 구현한 클래스 작성

- run() 메소드 작성

- Thread 객체 생성하고 Runnable 객체 인수로 전달

- start() 호출해서 스레드 시작

class MyRunnable implements Runnable {
    public void run() {
        for (int i = 0; i <= 10; i++) 
            System.out.print(i + " ");
    }
}

public class MyRunnableTest {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        t.start();
    }
}

// 0 1 2 3 4 5 6 7 8 9 10

 

- 스레드 2개 예제

class MyThread extends Thread {
	public void run() {
		for (int i = 0; i < 10; i ++) {
			System.out.print(i + " ");
		}
	}
}

class MyRunnable implements Runnable {
	public void run() {
		for (int i = 0; i < 30; i ++) {
			System.out.print("[" + i + "]");
		}
	}
}

public class ThreadTest {

	public static void main(String[] args) throws InterruptedException {
		System.out.println("main start");
		MyThread mt = new MyThread();
		mt.start();
		MyThread mt2 = new MyThread();
		mt2.start();
		Thread t = new Thread(new MyRunnable());  // runnable -바로 스타트 불가.
		t.start();
		// 모든 작업이 끝났을 때 종료 메세지를 출력하고 싶은 경우
		mt.join();
		mt2.join();
		t.join();     // 끝날 때까지 기다리기
		System.out.println("\nmain end");
	}
}

/**
main start
0 1 2 3 4 0 5 6 7 8 9 1 2 3 4 5 6 7 8 9 [0][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]
main end
**/

 

- 람다식 이용한 스레드 작성

public class LambdaTest {
    public static void main(String[] args) {
        Runnable task = () -> {
            for (int i = 0; i <= 10; i++)
                System.out.print(i + " ");
        };
        new Thread(task).start();
    }
}

// 0 1 2 3 4 5 6 7 8 9 10

 

4. 스레드 상태

- New : Thread 클래스의 인스턴스는 생성되었지만, start() 메소드를 호출하기 전

- Runnable : start() 메소드가 호출되어 실행 가능한 상태, 하지만 아직 스케줄러가 선택하지 않았으므로 실행 상태는 아님

- Running : 스레드 스케줄러가 스레드를 선택하면, 실행 중인 상태가 됨

- Blocking : 스레드가 아직 살아있지만, 여러 이유로 현재 실행할 수 없는 상태

- Terminated : 스레드가 종료된 상태, run() 메소드가 종료되면 스레드도 종료됨

 

- 실행 가능 상태 : 스레드가 스케줄링 큐에 넣어지고, 스케줄러에 의해 우선순위에 따라 실행

- 실행 중지 상태 

  - 스레드나 다른 스레드가 suspend()를 호출하는 경우

  - 스레드가 wait() 호출하는 경우

  - 스레드가 sleep() 호출하는 경우

  - 스레드가 입출력 작업을 하기 위해 대기하는 경우

 

5. 스레드 스케줄링

- 대부분 스레드 스케줄러는 선점형 스케줄링과 타임 슬라이싱을 사용해 스레드 스케줄링

- 어떤 스케줄링을 선택하느냐는 JVM에 의해 결정됨

 

6. 스레드 우선순위

- 1 ~ 10 사이의 숫자료 표시됨

- 기본 우선순위 : NORM_PRIORITY(5)

- MIN_PRIORITY(1)

- MAX_PRIORITY(10)

 

- void setPriority(int newPriority) : 현재 스레드의 우선 순위 변경

- getPriority() : 현재 스레드의 우선 순위 반환

 

7. sleep()

- 지정된 시간동안 스레드 재움

- 스레드가 수면 상태로 있는 동안 인터럽트되면 InterruptedException 발생

 

- 4초 간격으로 메시지 출력

public class SleepTest {
    public static void main(String[] args) throws InterruptedException {
        String messages[] = {"Hello.",
        "My name is A.", 
        "I'm majoring in computer science.",
        "I'm taking a JAVA class."};
        
        for (int i = 0; i < messages.length; i++) {
            Thread.sleep(4000);
            System.out.println(messages[i]);
        }
    }
}

/**
Hello.
My name is A.
I'm majoring in computer science.
I'm taking a JAVA class.
**/

 

8. join()

- 스레드가 종료될 때까지 기다리는 메소드

- 특정 스레드가 작업을 완료할 때까지 현재 스레드의 실행을 중지하고 기다리는 것

 

 

9. 인터럽트와 yield()

- 인터럽트 : 하나의 스레드가 실행하고 있는 작업을 중지하도록 하는 메커니즘 -> 대기 상태나 수면 상태가 됨

- yield() : CPU를 다른 스레드에게 양보하는 메소드

 

10. 자바 스레드 풀

- 스레드 풀 : 미리 초기화된 스레드들이 모여 있는 곳

- 스레드 풀의 동일한 스레드를 사용하여 N개의 작업을 쉽게 실행할 수 있음

- 스레드의 개수보다 작업의 개수가 더 많은 경우, 작업은 FIFO 큐에서 기다려야 함

 

- Java5 부터 자바 API는 Executor 프레임워크 제공

-> 개발자는 Runnable 객체를 구현하고 ThreadPoolExecutor로 보내기만 하면 됨

class MyTask implements Runnable {
    private String name;
    
    public MyTask(String name) {
        this.name = name;
    }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    @Override
    public void run() {
        try {
            System.out.println("실행중 : " + name);
            Thread.sleep(long)(Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class ThreadPoolTest {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
        
        for(int i = 0; i <= 5; i++) {
            MyTask task = new MyTask("작업 " + i);
            System.out.println("작업 생성 : " + task.getName());
            executor.execute(task);
        }
        executor.shutdown();
    }
}

 

11. 스레드 사용시 주의해야 할 점

- 동일한 데이터를 공유하기 때문에 매우 효율적으로 작업할 수 있지만, 2가지의 문제가 발생할 수 있음

 

- 문제 예제

class Printer {
    void print(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
            Thread.sleep(100);
        }
    }
}

class MyThread1 extends Thread {
    Printer prn;
    int[] myarr = {10, 20, 30, 40};
    
    MyThread1(Printer prn) { this.prn = prn; }
    public void run() { prn.print(myarr); }
}

class MyThread2 extends Thread {
    Printer prn;
    int[] myarr = {1, 2, 3, 4};
    
    MyThread2(Printer prn) { this.prn = prn; }
    public void run() { prn.print(myarr); }
}

public class TestSynchro {
    pubilc static void main(String args[]) {
        Printer obj = new Printer();
        MyThread1 t1 = new MyThread1(obj);
        MyThread2 t2 = new MyThread2(obj);
        t1.start();
        t2.start();
    }
}

// 1 10 20 2 30 3 4 40 
// 순서는 계속 바뀔 수 있음, 둘이 섞여서 엉망으로 출력됨

 

11-1) 동기화 (Synchronization)

- 한 번에 하나의 스레드만이 공유 데이터를 접근할 수 있도록 제어하는 것이 필요

- 자원에 한 번에 하나의 스레드만이 접근할 수 있고, 하나의 스레드 작업이 끝나면 다음 스레드가 사용할 수 있도록 하여 해결

- 자바에서의 동기화 방법

  - 동기화 메소드

  - 동기화 블록

  - 정적 동기화

  - 락(lock) 또는 모니터(monitor) 사용

// 메소드 앞에 synchronized 키워드 붙이기
class Printer {
    synchronized void print(int[] arr) {
        ....
    }
}

// 10 20 30 40 1 2 3 4



// 부분 코드만 동기화 -> synchronized 블록으로 설정
class Printer {
    void print(int[] arr) throws Exception {
        synchronized(this) {
            for (int i = 0; i < arr.length; i++) {
                System.out.print(arr[i] + " ");
                Thread.sleep(100);
            }
        }
    }
}

 

12. 교착 상태, 기아 상태

- 동일한 자원을 접근하려고 동기화를 기다리면서 대기하는 스레드들이 많아지면 JVM이 느려지거나 일시 중단 되기도 함

 

- 문제 예제

public class DeadLockTest {
    public static void main(String[] args) {
        final String res1 = "Gold";
        final String res2 = "Silver";
        
        Thread t1 = new Thread(() -> {
            synchronized(res1) {
                System.out.println("Thread 1 : 자원 1 획득");
                try { Thread.sleep(100); } catch (Exception e) {}
                synchronized(res2) {
                    systme.out.println("Thread 1 : 자원 2 획득");
                }
        }});
        
        Thread t2 = new Thread(() -> {
            synchronized(res2) {
                System.out.println("Thread 2 : 자원 2 획득");
                try { Thread.sleep(100); } catch (Exception e) {}
                synchronized(res1) {
                    System.out.println("Thread 2 : 자원 1 획득");
                }
        }});
        
        t1.start();
        t2.start();
    }
}

// Thread 1 : 자원 1 획득
// Thread 2 : 자원 2 획득

 

12-1) 방법1 : 잠금 순서 변경

Thread t2 = new Thread(() -> {
    synchronized(res1) {
        System.out.println("Thread 2 : 자원 1 획득");
        try { Thread.sleep(100); } catch (Exception e) {}
        synchronized(res2) {
            System.out.println("Thread 2 : 자원 2 획득");
        }
}});

/**
Thread 1 : 자원 1 획득
Thread 1 : 자원 2 획득
Thread 2 : 자원 1 획득
Thread 2 : 자원 2 획득
**/

 

12-2) 방법2: 스레드 간의 조정

13. wait(), notify()

- 이벤트가 발생하면 알리는 방법

- 생산자/소비자 문제에 적용

 

// buffer 클래스
class Buffer {
    private int data;
    private boolean empty = true;
    public synchronized int get() {
        while (empty) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        empty = true;
        notifyAll();
        return data;
    }
    
    public synchronized void put(int data) {
        while (!empty) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        empty = false;
        this.data = data;
        notifyAll();
    }
}

// 생산자
class Producer implements Runnable {
    private Buffer buffer;
    
    public Producer(Buffer buffer) {
        this.buffer = buffer;
    }
    
    public void run() {
        for (int i = 0; i < 10; i++) {
            buffer.put(i);
            System.out.println("생산자: " + i + "번 케익을 생산하였습니다.");
            try {
                Thread.sleep((int) (Math.random() * 100));
            } catch (InterruptedException e) {
            }
        }
    }
}

// 소비자
class Consumer implements Runnable {
    private Buffer buffer;
    
    public Consumer(Buffer drop) {
        this.buffer = drop;
    }
    
    public void run() {
        for (int i = 0; i < 10; i++) {
            int data = buffer.get();
            System.out.println("소비자: " + data + "번 케익을 소비하였습니다.");
            try {
                Thread.sleep((int) (Math.random() * 100));
            } catch (InterruptedException e) {
            }
        }
    }
}

public class ProducerConsumerTest {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        
        (new Thread(new Producer(buffer))).start();
        (new Thread(new Consumer(buffer))).start();
    }
}

/**
생산자: 0번 케익을 생산하였습니다.
소비자: 0번 케익을 소비하였습니다.
생산자: 1번 케익을 생산하였습니다.
소비자: 1번 케익을 소비하였습니다.
...
생산자: 9번 케익을 생산하였습니다.
소비자: 9번 케익을 소비하였습니다.
**/

'Software > JAVA' 카테고리의 다른 글

[Baekjoon] 1085.직사각형에서 탈출  (0) 2023.04.03
[JAVA] Day13. 파일 입출력  (0) 2023.01.18
[JAVA] Day12. 제네릭과 컬렉션  (0) 2023.01.11
[JAVA] Day11. 자바 그래픽  (5) 2023.01.10
[JAVA] Day10. 스윙 컴포넌트  (0) 2023.01.09

1. 스트림 Stream

- 순서가 있는 데이터의 연속적인 흐름

- 입풀력 단위에 따라 분류

 

바이트 스트림 문자 스트림
바이트 단위로 입출력하는 클래스 문자 단위로 입출력하는 클래스
추상 클래스인 InputStream, OutputStream에서 파생됨 기본 추상 클래스인 Reader, Writer 클래스에서 파생됨
바이트 스트림 클래스 이름에는 InputStream(입력), OutputStream(출력)이 붙음 문자 스트림 클래스 이름에는 Reader(입력), Writer(출력)이 붙음

 

2. 문자 스트림

- 입출력 단위가 문자 (바이트 X)

- 자바는 유니코드 이용하여 문자 저장

 

- 주요 메소드

 

- 파일에서 문자 읽고 쓸 때는 FileReader, FileWriter 사용

- 파일에서 문자 읽는 경우 일반적으로 반복문 사용 

int ch;
while ((ch = fr.read()) != -1)
    System.out.print((char) ch + " ");
import java.io.*;

public class FileReaderTets(String met){ 
    public static void main(String[] args) {
        FileReader fr;
        try {
            fr = new FileReader("test.txt");
            int ch;
            while((ch fr.read() != -1)
                System.out.print((char) ch + " ");
            fr.close();
        } catch (IOException e) {
            e.printSTackTrace();
        }
    }
}

 

3. try-with-resources 사용

- close() 따로 호출하지 않아도 자동으로 호출

import java.io.*;

public class FileReaderTest2 {
    public static void main(String[] args) throws Exception {
        try(FileReader fr = new FileReader("test.txt")) {
            int ch;
            while((ch = fr.read()) != -1 )
                System.out.print((char) ch);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

4. 중간 처리 스트림

 

- 자료형이 다른 몇 개의 데이터 파일에 출력했다가 다시 읽기

import java.io.*;

public class DataStreamTest {
    public static void main(String[] args) throws IOException {
        DataInputStream in = null;
        DataOutputStream out = null;
        try {
            out = new DataOutputStream(new FileOutputStream("data.bin"));
            out.writeInt(123);
            out.writeFloat(123.456F);
            out.close();
            
            in = new DataInputStream(new FileInputStream("data.bin"));
            int aint = in.readInt();
            float afloat = in.readFloat();
            
            System.out.println(aint);
            System.out.println(afloat);
        }
        finally {                 // 예외에 상관없이 실행
            if (in != null)       // in이 생성 되어있다면
                in.close();
            
            if (out != null)
                out.close();
        }
    }
}

// 123
// 123.456

 

5. 버퍼 스트림

- 버퍼 입력 스트림: 입력 장치에서 한번에 많이 읽어서 버퍼에 저장, 입력을 요구하면 버퍼에서 꺼내서 반환함

- 버퍼가 비었을 때만 입력 장치에서 읽음

 

inputStream = new BufferedReader(new FileReader("input.txt"));
outputStream = new BufferedWriter(new FileWriter("output.txt"));

 

- 줄 단위로 복사하기 (BufferedReader, PrintWriter 클래스 사용)

import java.io.*;

public class CopyLines {
    public static void main(String[] args) {
        try (BufferedReader in = new BufferedReader(new FileReader("test.txt"))) {
            PrintWriter out = new PrintWriter(new FileWriter("output.txt"))) {
                String line;
                while ((line = in.readLine()) != null) {
                    out.println(line);
                }
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

 

6. InputStreamReader, OutputStreamWriter 클래스

- 바이트 스트림과 문자 스트림을 연결하는 두 개의 범용 브릿지 스트림

 

6-1) 한글 코드

- ASCII 

- EUC-KR : 한글 완성형, 16비트, 국내 규격

- CP949 (MS949) : 한글 지원을 위해 MS 윈도우 계열에서 등장한 확장 완성형 인코딩 방식, ANSI

- 유니코드 : 전 세계에서 사용하는 수많은 문자들 각각에 부여한 코드들의 집합

- UTF-8 : 1~4byte로 인코딩하는 가변 길이 인코딩 방식, 기본적으로 첫 128개의 문자들은 1byte에 그대로 인코딩

- UTF-16 : 16bit 기반의 인코딩 방식, 한글 2byte, ANSI와 호환이 되지 않는 문제 있음

 

6-2) InputStreamReader

- 바이트 스트림 -> 문자 스트림으로 변환

BufferedReader in = new BufferedReader(new InputStreamReader(
    new FileInputStream(FileDir), "UTF8"));

 

- UTF-8 코딩 파일 읽기

public class CharEncodingTest {
    public static void main(String[] args) throws IOException {
        File FileDir = new File("input.txt");
        BufferedReader in = new BufferedReader(new InputStreamReader(
            new FileInputStream(fileDir), "UTF-8"));
        String str;
        while ((str=in.readLine()) != null) {
            System.out.println(str);
        }
        in.close();
    }
}

 

7. 객체 저장하기 :  객체 직렬화

 

- 객체 직렬화 : 객체가 가진 데이터들을 순차적인 데이터로 변환

- 순차적인 데이터가 되면 파일에 쉽게 저장할 수 있음

- 직렬화 지원 : Serializable 인터페이스 구현

- 역직렬화 : 직렬화된 데이터를 읽어서 자신의 상태를 복구하는 것 

 

- Date 객체 저장하기

public class ObjectStreamTest {
    public static void main(String[] args) throws Exception {
        ObjectInputStream in = null;
        ObjectOutputStream out = null;
        int c;
        
        out = new ObjectOutputStream(new FileOutputStream("object.dat"));
        out.writeObject(new Date());
        out.close();
        
        in = new ObjectInputStream(new FileInputStream("object.dat"));
        Date d = (Date) in.readObject();
        System.out.println(d);
        in.close();
    }
}


// Sat Jan 06 14:46:32 KST 2018

 

8. Path 객체

- 경로를 나타내는 클래스

- "D:\sources\test.txt" 와 같은 경로를 받아서 객체 반환

public class PathTest {
    public static void main(String[] args) {
        Path path = Paths.get("D:\\sources\\test.txt");
        System.out.println("전체 경로: " + path);
        System.out.println("파일 이름: " + path.getFileName());
        System.out.println("부모 이름: " + path.getParent().getFileName());
    }
}

/**
전체 경로: D:\sources\test.txt
파일 이름: test.txt
부모 이름: sources
**/

 

9. File 객체

- 파일을 조작하고 검사하는 코드를 쉽게 작성하게 해주는 클래스

- 파일이 아닌, 파일 이름을 나타내는 객체!

File file = new File("data.txt");

 

10. 스트림 라이브러리로 파일 처리하기

// 현재 디렉터리의 모든 파일을 출력하는 코드
Files.list(Paths.get(".")).forEach(System.out::println);
// 파일 읽어서 각 줄 끝에 있는 불필요한 공백을 제거하고 빈 줄을 필터링한 후에 출력
Files.lines(new File("test.txt").toPath())
     .map(s -> s.trim())
     .filter(s -> !s.isEmpty())
     .forEach(System.out::println);

 

 

'Software > JAVA' 카테고리의 다른 글

[Baekjoon] 1085.직사각형에서 탈출  (0) 2023.04.03
[JAVA] Day14. 멀티 스레딩  (2) 2023.01.18
[JAVA] Day12. 제네릭과 컬렉션  (0) 2023.01.11
[JAVA] Day11. 자바 그래픽  (5) 2023.01.10
[JAVA] Day10. 스윙 컴포넌트  (0) 2023.01.09

1. 제네릭 (generic programming)

    • 다양한 종류의 데이터 를 처리할 수 있는 클래스와 메소드를 작성하는 기법
  • ex)
  • class Box<T> { ... } // T : 타입 매개변수 - String도 될 수 있고, Integer도 될 수 있음

2. 기존의 방법

  • 일반적인 객체를 처리하려면 Object 참조 변수 사용: 어떤 객체이든지 참조 가능
public class Box { 
    private Object data; 
    private void set(Object data) { this.data = data; } 
    public Object get() { return data; } 
}

Box b = new Box();

b.set("Hello World!"); // 문자열 객체 저장  
String s = (String)b.get(); // Object 타입을 String 타입으로 형변환

b.set(new Integer(10)); // 정수 객체 저장  
Integer i = (Integer)b.get(); // Object 타입을 Integer 타입으로 형변환

b.set("Hello World!");  
Integer i = (Integer)b.get(); // 오류! 문자열을 정수 객체로 형변환 (x)

3. 제네릭을 이용한 방법

class Box<T> {
    private T data;
    public void set(T data) { this.data = data; }
    public T get() { return data; }
}

Box<String> b = new Box<String>();
b.set("Hello World!");     // 문자열 저장
String s = b.get();

Box<String> stringBox = new Box<>();   // 뒤에 나오는 타입 <> 생략 가능
stringBox.set(new Integer(10));        // 정수 타입을 저장하려고 하면 컴파일 오류!

4. 제네릭 메소드

  • 일반 클래스의 메소드에서도 타입 매개 변수를 사용해서 제네릭 메소드 정의 가능
  • 이 경우에는 타입 매개 변수의 범위가 메소드 내부로 한정됨
public class MyArray {
    public static <T> T getLast(T[] a) {    // 제네릭 메소드 정의
        return a[a.length - 1];
    }
}

public class MyArrayTest {  
public static void main(String\[\] args) {  
String\[\] language = { "C++", "C#", "JAVA" };  
String last = MyArray.getLast(language); // last는 "JAVA"  
System.out.println(last);  
}  
}

// JAVA
  • 예제2
public class GenericTest {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Integer[] iArray = {10, 20, 30, 40, 50};        // wrapper 클래스
        Double[] dArray = {1.1, 1.2, 1.3, 1.4, 1.5};
        Character[] cArray = {'K', 'O', 'R', 'E', 'A'};

        printArray(iArray);
        printArray(dArray);
        printArray(cArray);
    }
}

/**
10 20 30 40 50 
1.1 1.2 1.3 1.4 1.5
K O R E A
**/
  • 제네릭 메소드에는 기본 data type을 매개 변수로 넘길 수 없음!
  • 객체 데이터 타입을 넘겨야 함 -> wrapper 클래스 이용

1. 컬렉션 collection

  • 자바에서 자료구조를 구현한 클래스
  • list, stack, queue, set, hash table 등
  • 컬렉션 인터페이스컬렉션 클래스로 나누어 제공

collection

  • 컬렉션 인터페이스
인터페이스 설명
Collection 모든 자료구조의 부모 인터페이스로서 객체의 모임 나타냄
Set 집합 (중복된 원소 불가)
List 순서가 있는 자료구조 (중복된 원소 가능)
Map 키와 값들이 연관되어 있는 dictionary와 같은 자료구조
Queue 선입선출 자료구조

2. 컬렉션 특징

  • 제네릭 사용
  • 컬렉션에는 int, double과 같은 기초 자료형 사용 불가. 클래스만 가능!
  • 기초 자료형은 wrapper 클래스로 사용 (Integer, Double 등)
  • 기본 자료형을 저장하면 자동으로 래퍼 클래스의 객체로 변환됨 (오토박싱)

3. 컬렉션 인터페이스 주요 메소드

메소드 설명
boolean isEmpty() boolean contains(Object obj) boolean cotainsAll(Colllection<?> c) 공백 상태이면 true 반환 obj 포함하고 있으면 true 반환
boolean add(E element) boolean addAll(Collection<? extends E> from) 원소 추가
boolean remove(Object obj) boolean removeAll(Collection<?> c) boolean retainAll(Collection<?> c) void clear() 원소 삭제
Iterator iterator() Stream stream() Stream parallelStream() 원소 방문
int size() 원소 개수 반환
Object\[\] toArray() T\[\] toArray(T\[\] a) 컬렉션을 배열로 변환

4. 컬렉션 모든 요소 방문하기

String a[] = new String[] {"A", "B", "C", "D", "E" };
List<String> list = Arrays.asList(a);

// 1. for문
for(int i = 0; i < list.size(); i++) 
    System.out.println(list.get(i));

// 2. for-each문
for(String s : list)
    System.out.println(s);

// 3. Iterator(반복자)
String s;
Iterator e = list.iterator();     
while(e.hasNext()) {
    s = (String) e.next();          // e는 Object 타입 반환
    System.out.println(s);
}

// 4. Stream 라이브러리 - forEach 메소드 & 람다식
list.forEach((n) -> System.out.println(n));

5. Iterator

  • 특별한 타입의 객체로, 컬렉션의 원소들에 접근 하는 것이 목적
  • 모든 컬렉션에 적용
메소드 설명
hasNext() 아직 방문하지 않은 원소가 있으면 true 반환
next() 다음 원소 반환
remove() 최근에 반환된 원소 삭제

6. 람다식

  • 나중에 실행될 목적으로 다른 곳에 전달될 수 있는 코드 블록
  • (int a, int b) -> { return a + b; } // 매개변수 연산자 몸체
  • 0개 이상의 매개 변수 가질 수 있음
  • 화살표 -> 는 람다식에서 매개 변수와 몸체 구분
  • 매개 변수의 형식을 명시적으로 선언할 수 있으며, 문맥에서 추정될 수도 있음
    • (int a) == (a)
    • 빈 괄호는 매개 변수가 없음을 뜻함
      • ex. () -> 23
  • 단일 매개 변수이고 타입이 유추가 가능한 경우에는 괄호 사용할 필요 없음
    • ex. a -> return a*a;
  • 몸체에 하나 이상의 문장이 있으면 { }로 묶어야 함
() -> System.out.println("Hello World");

(String s) -> { System.out.println(s); }

() -> 60

() -> { return 3.141592; }

(String s) -> s.length()

(Car c) -> c.getprice() > 150

(int x, int y) -> {
    System.out.print("결과값: ");
    System.out.println(x+y);
}

(Car c1, Car c2) -> c1.getPrice().compareTo(c2.getPrice())

7. 람다식 활용

  • GUI 코드를 작성할 때 함수 몸체를 전달하고 싶은 경우
// 기존
btn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("button click");
    }
});

// 람다식
btn.addActionListener( (e) -> {
    System.out.println("button click");
});
  • 스레드 작성시 runnable 인터페이스 구현
// 기존
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("thread start");
    }
}).start();

// 람다식
new Thread( () -> System.out.println("thread start") ).start();
  • 배열의 모든 요소 출력
// 기존
List<Integer> list = Arrays.asList( 1, 2, 3, 4, 5 );

for (Integer n : list )
    System.out.println(n);

// 람다식
list.forEach( n -> System.out.println(n) );

<br>

8. 컬렉션 - Vector 클래스

  • 가변 크기의 배열 (dynamic array)
  • vector의 크기는 자동으로 관리됨

vector

import java.util.*;

public class VectorEx {
    public static void main(String[] args) {
        Vector<String> vec = new Vector<String>(2);
        vec.add("Apple");
        vec.add("Orange");
        vec.add("Mango");

        System.out.println("Vector size: " + vec.size());
        Collections.sort(vec);
        for(String s : vec)
            System.out.print(s + " ");
    }
}

// Vector size: 3
// Apple Mango Orange

9. ArrayList

  • 가변 크기의 배열(Array)
  • ArrayList<String> list = new ArrayList<String>();
메소드 설명
list.add() 원소 추가
list.set(2, "GRAPE") 인덱스 2의 원소를 "GRAPE"로 교체
list.remove(3) 인덱스 3의 원소 삭제
class Point {
    int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public String toString() { return "(" + x + ", " + y + ")"); }
}

public class ArrayListTest {
    public static void main(String[] args) {
        ArrayList<Point> list = new ArrayList();

        list.add(new Point(0, 0));
        list.add(new Point(4, 0));
        list.add(new Point(3, 5));
        list.add(new Point(-1, 3));
        list.add(new Point(13, 2));

        System.out.println(list);
    }
}

// [(0, 0), (4, 0), (3, 5), (-1, 3), (13, 2)]

10. Vector vs ArrayList

  • Vector는 스레드 간 동기화 지원
  • ArrayList는 동기화 X - Vector보다 성능은 우수함
    vs

11. LinkedList

  • 빈번하게 삽입과 삭제가 일어나는 경우에 사용
  • 배열 중간 삽입은 원소들의 이동이 발생하지만, 연결 리스트는 링크만 수정하면 됨

linked

import java.util.*;

public class LinkedListTest {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<String>();

        list.add("MILK");
        list.add("BREAD");
        list.add("BUTTER");
        list.add(1, "APPLE");
        list.add(2, "GRAPE");
        list.remove(3);

        for(int i = 0; i < list.size(); i++)
            System.out.println(list.get(i) + " ");
    }
}

// MILK APPLE GRAPE

12. ArrayList vs LinkedList

  • ArrayList는 인덱스를 가지고 원소에 접근할 경우, 항상 일정한 시간만 소요됨
  • ArrayList는 리스트의 각각의 원소를 위해 노드 객체를 할당할 필요 없음
  • 동시에 많은 원소를 이동해야 하는 경우 System.arraycopy() 메소드 사용 가능
  • 리스트의 처음에 빈번하게 원소를 추가하거나, 내부 원소 삭제를 반복하는 경우에는 LinkedList를 사용하는 것이 나음
  • 이들 연산은 LinkedList에서는 일정한 시간만 걸리지만, ArrayList에서는 원소의 개수에 비례하는 시간 소요됨

13. Set

  • 원소의 중복 허용X
  • 순서 없음
  • 인터페이스 구현 방법
    • HashSet : 해쉬 테이블에 원소 저장 -> 성능 면에서 가장 우수, 순서가 일정하지 않다는 단점
    • TreeSet : red-black tree에 원소 저장 -> 값에 따라 순서가 결정됨, HashSet보다는 느림
    • LinkedHashSet : 해쉬 테이블과 연결 리스트를 결합한 것, 원소 순서 = 삽입 순서
import java.util.*;

public class SetTest {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<String>();

        set.add("Milk");
        set.add("Break");
        set.add("Butter");
        set.add("Cheese");
        set.add("Ham");
        set.add("Ham");

        System.out.println(set);

        if(set.contains("Ham"))
            System.out.println("Ham도 포함되어 있음");
    }
}

// [Ham, Butter, Cheese, Milk, Bread]
// Ham도 포함되어 있음

14. set 대량 연산 메소드

메소드 설명
s1.containsAll(s2) s2가 s1의 부분집합이면 true 반환
s1.addAll(s2) s1을 s1과 s2의 합집합으로 만듦
s1.retainAll(s2) s1을 s1과 s2의 교집합으로 만듦
s1.removeAll(s3) s1을 s1과 s2의 차집합으로 만듦

15. Map

  • Dictionary와 같은 자료 구조
  • 많은 데이터 중 원하는 데이터 빠르게 찾을 수 있음

map

import java.util.*;

public class MapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();

        map.put("kim", "1234");
        map.put("lee", "pass");
        map.put("park", "word");

        System.out.println(map.get("lee"));
        for(String key : map.keySet()) {
            String value = map.get(key);
            System.out.println("key: " + key + ", value: " + value);
        }

        map.remove("lee");
        map.put("choi", "password");
        map.put("choi", "pw");          // 대치 
        System.out.println(map);

16. map의 모든 요소 방문

// 1. for-each 구문 & keySet()
String.out.println("key: " + key + ", value" + map.get(set));

//  2. Iterator
Iterator<String> e = map.keySet().iterator();
while (e.hasNext()) {
    String key = e.next();
    System.out.println("key: " + key + ", value: " + map.get(key));
}

// 3. Stream 라이브러리
map.forEach( (key, value) -> {
    System.out.println("key: " + key + ", value: " + value);
});

17. 큐 Queue

  • 선입선출 (tail에 원소 추가, head에서 원소 제거)
  • Queue 인터페이스로 정의
  • 이 인터페이스를 구현한 3개의 클래스
    • ArrayDeque
    • LinkedList
    • PriorityQueue
메소드 설명
add() 새로운 원소 추가가 큐의 용량을 넘어서지 않으면 원소 추가
remove(), poll() 큐의 처음에 있는 원소 제거하거나 가져옴 정확히 어떤 원소인지는 큐의 정렬 정책에 따라 달라짐
import java.util.LinkedList;
import java.util.Queue;

public class QueueTest {
    public static void main(String[] ars) {
        Queue<Integer> q = new LinkedList<>();

        for (int i = 0; i < 5; i++)
            q.add(i);
        System.out.println("큐의 요소: " + q);

        int e = q.remove();
        System.out.println("삭제된 요소: " + e);
        System.out.println(q);
    }
}

// 큐의 요소: [0, 1, 2, 3, 4]
// 삭제된 요소: 0
// [1, 2, 3, 4]

17-1) 우선순위 큐

  • 원소들이 무작위로 삽입되었더라도 정렬된 상태로 추출
  • remove()를 호출할 때마다 가장 작은 원소가 추출됨
import java.util;

public class PriorityQueueTest {
    public static void main(String[] args) {
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
        pq.add(30);
        pq.add(80);
        pq.add(20);

        System.out.println(pq);
        System.out.println("삭제된 원소: " + pq.remove());
    }
}

// [20, 80, 30]
// 삭제된 원소: 20

18. Collection 클래스

  • 여러 유용한 알고리즘을 구현한 메소드들 제공

18-1) 정렬 sorting

List<String> list = new LinkedList<String>();
list.add("철수");
list.add("영희");
Collections.sort(list);     // 리스트 안 문자열이 정렬됨
  • 리스트 안의 문자열 정렬
import java.util.*;

public class Sort {
    public static void main(String[] args) {
        String[] sample = {"i", "walk", "the", "line"};

        List<String> list = Arrays.asList(sample);    // 배열을 리스트로 변경

        Collections.sort(list);
        System.out.println(list);
    }
}

// [i, line, the, walk]
  • 사용자 클래스의 객체 정렬
import java.util.*;

class Student implements Comparable<Student> {
    int number;
    String name;

    public Student(int number, String name) {
        this.number = number;
        this.name = name;
    }

    public String toString() { return name; }

    public int compareTo(Student s) {
        return s.number - number;
    }
}

public class SortTest {
    public static void main(String[] args) {
        Student array[] = {
            new Student(2, "김철수");
            new Student(3, "이철수");
            new Student(1, "박철수");
        };

        List<Student> list = Arrays.asList(array);
        Collections.sort(list);
        System.out.println(list);
    }
}

// [박철수, 김철수, 이철수]

18-2) 섞기 shuffling

  • 정렬의 반대 동작
  • 리스트에 존재하는 정렬을 파괴해서 원소들의 순서를 랜덤하게 만듦
import java.util.*;

public class Shuffle {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        for(int i = 1; i <= 10; i++) 
            list.add(i);
        Collections.shuffle(list);
        System.out.println(list);
    }
}

// [5, 9, 7, 3, 6, 4, 8, 2, 1, 10]

18-3) 탐색 searching

  • 리스트 안에서 원하는 원소를 찾는 것
  • 선형 탐색 : 정렬되어 있지 않은 경우 처음부터 모든 원소를 방문하는 방법
  • 이진 탐색 : 정렬되어 있는 경우 중간에 있는 원소와 먼저 비교하는 방법
import java.util.*;

public class Search {
    public static void main(String[] args) {
        int key = 50;
        List<Integer> list = new ArrayList<Integer>();

        for(int i = 0; i < 100; i++)
            list.add(i);

        int index = Collections.binarySearch(list, key);
        System.out.println("탐색의 반환값: " + index);
    }
}

// 탐색의 반환값: 50

'Software > JAVA' 카테고리의 다른 글

[JAVA] Day14. 멀티 스레딩  (2) 2023.01.18
[JAVA] Day13. 파일 입출력  (0) 2023.01.18
[JAVA] Day11. 자바 그래픽  (5) 2023.01.10
[JAVA] Day10. 스윙 컴포넌트  (0) 2023.01.09
[JAVA] Day9. 이벤트 처리  (2) 2023.01.08

1. 그리는 위치

- JPanel : 그림 그릴 수 있는 화면 갖고 있고, 동시에 컨테이너 역할도 함

class MyPanel extends JPanel {
    ...
}

public class MyFrame extends JFrame {
    public MyFrame() {
        MyPanel panel = new MyPanel();
        add(panel);
    }
}

 

2. paintComponent()

- 컴포넌트가 가지고 있는 메소드
- 모든 컴포넌트가 가지고 있으며, 이 메소드를 재정의함으로써 그림을 그림
- 컴포넌트를 다시 그릴 필요가 있을 때마다 자바 시스템에 의해 호출됨 (ex. 프레임이 가려졌다가 다시 나타나는 경우)
- super.paintComponent(g) 호출
- 전체 구성요소를 전부 그리는 것이 아닌 경우 호출

class MyPanel extends JPanel {
    public void paintComponent(Graphics g) {
        super.paintComponent(g);                 
        // 그림그리는 코드
    }
}

 

3. repaint()

- 사용자가 직접 paintComponent()를 호출할 수 없음. 반드시 자동으로 호출되어야 함
- 사용자가 화면을 다시 그리고 싶은 경우 repaint() 호출
-> repaint()가 적절한 시기에 paintComponent() 호출

4. 색상 변경

Color c = Color.BLUE;  
Color c = new Color(255, 0, 255);

- setBackground(c) : 컴포넌트 객체 배경색 설정
- setColor(c) : 전경색 설정
- Color getColor() : 현재 전경색 반환

5. 폰트 객체 생성

- Font(폰트 이름(Alias, Serif, Gothic ...) , 스타일(Font.PLAIN, BOLD, ITALIC ...), 크기(10, 30, ...))

Font font = new Font("Courier", Font.PLAIN, 10);

public void paint(Graphics g) {
    g.setFont(font);
    ...
}

JLabel lbl = new JLabel("Hello");
lbl.setFont(new Font("Gothic", Font.BOLD, 30));

 

6. Graphics 클래스

- 텍스트 문자열 : drawString();

g.drawString("Hello World!", x, y);   // x, y : 위치 설정


- 기초 도형들
- draw---(); : 선으로 그리기
- fill---(); : 채워서 그리기

drawLine(int x1, int y1, int x2, int y2);  // (x1, y1)에서 (x2, y2)까지 직선
drawRect(int x, int y, int width, int height);  // (x, y)에서 폭 width, 높이 height인 직사각형
drawOval(int x, int y, int width, int height);  
// (x, y)에서 폭 width, 높이 height인 직사각형에 내접하는 타원
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle);
// 좌측 상단 좌표가 (x, y)이며 폭 width, 높이 height인 사각형에 내접하는 타원에서
// startAngle을 시작 각도로 하여 arcAngle의 각도만큼 호를 그림
drawPolygon(int[] x, int y[], length);   // 배열 x[], y[]를 갖고 여러 개의 직선 (전부 이음)
drawPolyline(int[] x, int y[], length);  // 배열 x[], y[]를 갖고 여러 개의 직선 (처음과 끝 잇지 않음)


- 이미지 : drawImage();

ImageIcon icon = new ImageIcon("car.png");
img = icon.getImage();

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(img, x, y, null);
}

 

7. 그래픽 좌표계

 

8. 예제1) 화면 클릭하면 그 위치에 사각형 그리도록

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class MyFrame extends JFrame {
    int x, y;
    class MyPanel extends JPanel {
        public MyPanel() {
            addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent e) {
                    x = e.getX();
                    y = e.getY();
                    repaint();
                }
            });
        }
        
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.ORANGE);
            g.fillRect(x, y, 100, 100);
        }
    }    
   
    public MyFrame() {
        setSize(600, 200);
        add(new MyPanel());
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
   
    public static void main(String[] args) {
        new MyFrame();
    }
}

 

발전 버전) 드래그 한 크기의 사각형 그리고 패널 위에 저장하기

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class Rect {
    int x, y, w, h;
    public Rect(int x, int y, int w, int h) {
        this.x = x; this.y = y; this.w = w; this.h = h;
    }
}

public class GraphicTest extends JFrame {
    int x, y;
    int w = 100, h = 100;
    int x1, y1, x2, y2;
    Vector<Rect> list = new Vector<>();
    
    class MyPanel extends JPanel {
        public MyPanel() {
            addMouseListener(new mouseAdapter() {
                public void mousePressed(MouseEvent e) {   // 눌렀을 때 위치
                    x1 = e.getX();
                    y1 = e.getY(); 
                }
                
                public void mouseReleased(MouseEvent e) {    // 뗄 때 위치
                    x2 = e.getX();
                    y2 = e.getY();
                    x = Math.min(x1, x2);
                    y = Math.min(y1, y2);     // 사각형 시작점
                    w = Math.abs(x1-x2);
                    h = Math.abs(y1-y2);
                    
                    list.add(new Rect(x, y, w, h));    // 사각형 객체 모음
                    repaint();
                }
            });
        }
        
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.orange);
            g.fillRect(x, y, w, h);    // 드래그하는 동안 그려지는 사각형
            for(Rect r : list)
                g.drawRect(r.x, r.y, r.w, r.h);
        }
    }
    
    public GraphicTest() {
        add(new MyPanel());
        setSize(600, 400);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        new GraphicTest();
    }
}

 

 

9. 예제2) 바운싱 볼 애니메이션

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class BounceBall extends JFrame implements ActionListener{
    static final int WIDTH = 600;
    static final int HEIGHT = 200;
    private static final int PERIOD = 10;
    
    class MyPanel extends JPanel {
        int x = 0, y = 0, xInc = 3, yInc = 3, diameter = 60;
        
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if(x < 0 || x > (BounceBall.WIDTH - diameter))
                xInc = -xInc;
            if(y < 0 || y > (BounceBall.HEIGHT - diameter))
                yInc = -yInc;
            
            x += xInc;
            y += yInc;
            g.setColor(Color.RED);
            g.fillOval(x, y, diameter, diameter);
        }
    }
    
    public BounceBall() {
        MyPanel panel = new MyPanel();
        panel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        add(panel);
        pack();
        
        Timer timer = new Timer(PERIOD, this);
        timer.start();
        
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

	@Override
	public void actionPerformed(ActionEvent e) {
		repaint();
	}
    
    public static void main(String[] args) {
        new BounceBall();
    }
}

 

 

 

'Software > JAVA' 카테고리의 다른 글

[JAVA] Day13. 파일 입출력  (0) 2023.01.18
[JAVA] Day12. 제네릭과 컬렉션  (0) 2023.01.11
[JAVA] Day10. 스윙 컴포넌트  (0) 2023.01.09
[JAVA] Day9. 이벤트 처리  (2) 2023.01.08
[JAVA] Day8. 자바 GUI 기초  (2) 2023.01.08

1. 스윙 컴포넌트

- 윈도우 기반 응용 프로그램을 만드는데 사용되는 JFC(Java Foundation Classes) 의 일부

- AWT와 달리 플랫폼 독립적이고 경량 컴포넌트 구조

- JButton, JTextField, JTextArea, JRadioButton, JCheckbox, JMenu, JColorChooser 등

 

2. JComponent 클래스

- 최상위 컨테이너를 제외하고는 거의 모든 컴포넌트가 JComponent를 상속받음

- ex) JPanel, JLabel, JComboBox 등

- 스윙 컴포넌트들이 공통적으로 가져야하는 속성과 메소드 포함

 

- JComponent 메소드

 

3. 예제

- 텍스트 필드로 사용자에게 정수 입력받은 뒤 제곱 반환

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TextTest extends JFrame {
    private JButton button;
    private JTextField text, result;
    public TextTest() {
        setSize(300, 150);
        
        ButtonListener listener = new ButtonListener();
        JPanel panel = new JPanel();
        panel.add(new JLabel("숫자 입력: "));
        
        text = new JTextField(15);
        text.addActionListener(listener);
        panel.add(text);
        
        panel.add(new JLabel("제곱한 값: "));
        result = new JTextField(15);
        result.setEditable(false);    // 출력만 가능
        panel.add(result);
        
        button = new JButton("OK");
        button.addActionListener(listener);
        panel.add(button);
        add(panel);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    // 내부 클래스로서 텍스트 필드와 버튼의 액션 이벤트 처리
    private class ButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if(e.getSource() == button || e.getSource() == text) {
                String name = text.getText();
                int value = Integer.parseInt(name);
                resutl.setText("" + value * value);
                text.requestFocus();         // 텍스트창 선택됨
            }
        }
    }
    
    public static void main(String[] args) { 
        new TextTest();
    }
}

 

4. JTextArea

- 텍스트 필드는 한 줄만 들어갈 수 있는 반면, 텍스트 영역은 여러 줄의 텍스트 들어갈 수 있음

- textArea = new JTextArea(10, 30);     // 10행 30열의 텍스트 영역 생성

 

5. scroll pane 

- 컴포넌트에 스크롤 기능 제공

textArea = new JTextArea(6, 30);
JScrollPane scrollpane = new JScrollPane(textArea);
add(scrollpane, "Center");

 

6. check box

- 체크박스를 클릭하면 ItemEvent 발생

-> ItemListener 구현해야 함 - 익명 클래스 사용하는 것이 편함

JCheckBox check = new JChechBox("CheckBox", false);
check.addItemListener(new ItemListener() {
    public void itemStateChanged(ItemEvent e) {
        System.out.println("체크 상태: " + check.isSelected());
    }
});

 

- 예제

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class CheckBoxTest extends JFrame { 
    public CheckBoxTest() { 
        setLayout(new GridLayout(0, 1));
        JLabel label = new JLabel();
        JCheckBox cbPizza = new JCheckBox("피자");
        JCheckBox cbPasta = new JCheckBox("스파게티");
        add(cbPizza);
        add(cbPasta);
        add(label);
        
        cbPizza.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                label.setText("피자가 " + (e.getStateChange() == 1 ? "선택되었습니다." : "선택해제되었습니다."));
            }
        });
        
        cbPasta.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                label.setText("스파게티가 " + (e.getStateChange() == 1 ? "선택되었습니다." : "선택해제되었습니다."));
            }
        });
        
        setSize(300, 150);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        new CheckBoxTest();
    }
}

 

7. 라디오 버튼

- 체크 박스와 비슷하지만, 라디오 버튼은 하나의 버튼 그룹 안에서는 한 개의 버튼만 선택할 수 있음

JRadioButton radio1 = new JRadioButton("Small Size");
JRadioButton radio2 = new JRadioButton("Medium Size");
JRadioButton radio3 = new JRadioButton("Large Size");

// button group 객체 생성
ButtonGroup group = new ButtonGroup();

// 그룹에 라디오 버튼 객체들 추가
group.add(radio1);
group.add(radio2);
group.add(radio3);

 

8. 콤보 박스

- 여러 항목 중에서 하나 선택

- 텍스트 필드와 리스트의 결합

- 텍스트 직접 입력, 리스트에서 선택 둘 다 가능

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ComboBoxFrame extends JFrame implements ActionListener {
    JLabel lbl;
    
    public ComboBoxFrame() {
        setSize(400, 200);
        
        String[] ani = {"dog", "cat", "bird"};
        JComboBox aniList = new JComboBox(ani);
        aniList.setSelectedIndex(0);
        aniList.addActionListener(this);
        
        lbl = new JLabel();
        lbl.setHorizontalAlignment(JLabel.CENTER);
        changePicture(ani[aniList.getSelectedIndex()]);
        
        add(aniList, "North");
        add(lbl, "Center");
        setVisible(true)
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public void actionPerformed(ActionEvent e) {
        JComboBox cb = (JComboBox) e.getSource();
        String name = (String) cb.getSelectedItem();
        changePicture(name);
    }
    
    protected void changePicture(String name) {
        ImageIcon icon = new ImageIcon(name + ".png");
        lbl.setIcon(icon);
        if(icon != null) 
            lbl.setText(null);
        else
            lbl.setText("이미지가 발견되지 않았습니다.");
    }
    
    public static void main(String[] args) {
        new ComboBoxFrame();
    }
}

 

9. 메뉴 붙이기

- 윈도우 상단에 위치한 메뉴바 생성

- 팝업 메뉴는 팝업이 가능한 컴포넌트 위에서 마우스 오른쪽 버튼을 누르면 그 위치에 등장

- 메뉴 항목은 이미지나 텍스트 가질 수 있음

 

- 메뉴 생성 절차 [메뉴바 - 메뉴 - 메뉴항목]

// 1. 메뉴바 관련 변수 설정
JMenuBar menuBar;
JMenu menu;
JMenuItem menuItem;

// 2. 메뉴바 생성
menuBar = new JMenuBar();

// 3. 메뉴 생성하여 메뉴바에 추가
menu = JMenu("메뉴 1");
menuBar.add(menu);

// 4. 메뉴 항목 생성하여 메뉴에 추가
menuItem = new JMenuItem("메뉴 항목1", KeyEvent.VK_T);
menu.add(menuItem);

// 5. 프레임에 메뉴바 설정
frame.setJMenuBar(mb);

 

- 메뉴 이벤트 처리

// 각각의 메뉴 항목에 대해 액션 이벤트 처리기 등록
menuItem.addActionListener(this);

 

10. 슬라이더

- 사용자가 특정한 범위 안에서 하나의 값을 선택할 수 있는 컴포넌트

- 슬라이더, 이벤트 처리

slider = new JSlider(0, 100, 50);

slider.setMajorTickSpacing(10);     // 큰 눈금 간격
slider.setMinorTickSpacing(1);      // 작은 눈금 간격
slider.setPaintTicks(true);         // 눈금 표시
slider.setPaintLabels(true);        // 값을 레이블로 표시

slider.addChangeListener(this);

public void stateChanged(ChangeEvent e) {
    JSlider source = (JSlider) e.getSource();
    if (!source.getValueIsAdjusting()) {
        int value = (int) source.getValue();
        button.setSize(value * 10, value * 10);
}

'Software > JAVA' 카테고리의 다른 글

[JAVA] Day12. 제네릭과 컬렉션  (0) 2023.01.11
[JAVA] Day11. 자바 그래픽  (5) 2023.01.10
[JAVA] Day9. 이벤트 처리  (2) 2023.01.08
[JAVA] Day8. 자바 GUI 기초  (2) 2023.01.08
[JAVA] Day7. 자바 API 패키지, 예외처리, 모듈  (0) 2023.01.02

1. 이벤트

- 사용자가 버튼을 클릭한다거나, 마우스를 움직이거나, 키를 누르면 발생

- 이벤트 리스너 : 발생된 이벤트 객체에 반응하여 이벤트를 처리하는 객체

 

2. 이벤트 처리 과정

1) 이벤트 리스너 작성

class MyListener implements ActionListener {
    public void actionPerformed (ActionEvent e) {
        // Action event 처리
        // 이벤트 객체가 발생하면 호출됨!
    }
}

 

2) 이벤트 리스너를 컴포넌트에 등록

public class MyFrame extends JFrame {
    JButton button;
    ...
    public MyFrame() {   // 생성자에서 컴포넌트 생성, 추가
        button = new JButton("동작");
        button.addActionListener(new MyListener());   // 이벤트 리스너 객체 생성, 등록
        ...
    }
}

 

3. 이벤트 객체

- 이벤트 객체는 발생된 이벤트에 대한 모든 정보를 리스너로 전달

- 이벤트 객체는 getSource() 액션 이벤트가 발생하면 호출됨

public void actionPerformed(ActionEvent e) {
    button = (JButton)e.getSource();
    ...
}

 

4. 이벤트 처리기 위치

1) 독립적인 클래스로 이벤트 처리기 작성

 

2) 내부 클래스로 이벤트 처리기 작성 

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class EventTest1 extends JFrame {
    private JButton button;
    private JLabel label;
    int counter = 0;
    
    class MyListener implements ActionListener {       // 리스너 클래스
        public void actionPerformed(ActionEvent e) {
            counter++;
            label.setText("현재 카운터값: " + counter);
        }
    }
    
    public EventTest1() {     // 생성자
        setSize(400, 150);
        setLayout(new FlowLayout());
        button = new JButton("증가");
        label = new JLabel("현재 카운터값: " + counter);
        
        button.addActionListener(new MyListener());  // 리스너 컴포넌트에 등록
        add(label);
        add(button);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        new EventTest1();
    }
}

 

3) 프레임 클래스에 이벤트 추리 구현

- JFrame 상속받으면서 동시에 ActionListener 인터페이스 구현

- 리스너 클래스 없이 바로 함수가 나온 것

public class EventTest2 extends JFrame implements ActionListener {
    private JButton button;
    private JLabel label;
    int counter = 0;
    
    public void actionPerformed(ActionEvent e) {
        counter++;
        label.setText("현재 카운터값: " + counter);
    }
    
    public EventTest2() {
        this.setSize(400, 150);
        button = new JButton("증가");
        label = new JLabel("현재 카운터값: " + counter);
        
        button.addActionListener(this);
        add(label);
        add(button);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        new EventTest2();
    }
}

 

4) 익명 클래스 사용

- 한 번만 사용할 때

- 클래스가 정의되면서 바로 사용

- 안드로이드 프로그래밍에서도 자주 사용됨

public class EventTest3 extends JFrame {
    private JButton button;
    private JLabel label;
    int counter = 0;
    
    public EventTest3() {
        this.setSize(400, 150);
        button = new JButton("증가");
        label = new JLabel("현재 카운터값: " + counter);
        
        button.addActionListener(new ActionListener() {      // 익명 클래스 - 바로 정의
            public void actionPerfomed(ActionEvent e) {
                counter++;
                label.setText("현재 카운터값: " + counter);
            }
        });
        
        add(label);
        add(button);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}

 

- 일반 클래스와 익명 클래스 비교

익명 클래스 일반 클래스
ActionListener obj = new ActionListener() {
    ...
};
class MyListener implements ActionListener { 
    ...
}
MyListener obj = new MyListener();

 

5) 람다식 이용

- 람다식 : 이름이 없는 메소드 -> 간결함

(int a, int b)   ->    { return a + b; }
// 메소드 시그니처 람다연산자    메소드 구현
public class EventTest4 extends JFrame {
    private JButton button;
    private JLabel label;
    int counter = 0;
    
    public EventTest4() {
        this.setSize(400, 150);
        button = new JButton("증가");
        label = new JLabel("현재 카운터값: " + counter);
        
        button.addActionListener(e -> {            // 람다식
            counter++;
            label.setText("현재 카운터값: " + counter);
        });
        
        add(label);
        add(button);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}

 

5. 스윙 컴포넌트의 이벤트

1) 저수준 이벤트 : 모든 컴포넌트가 공통적으로 지원

  - Mouse, MouseAction, Key, Component, Container, Focus, Window

 

2) 의미적 이벤트 : 일부 컴포넌트만 지원

  - Action, Adjustment, Document, Item, Text

 

6. 액션 이벤트

- 사용자가 버튼을 클릭하는 경우

- 사용자가 메뉴 항목을 선택하는 경우

- 사용자가 텍스트 필드에서 엔터키를 누르는 경우

 

예제 1) 패널 배경색 바꾸기

// 익명클래스

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ChangeBackground extends JFrame {
    private JButton button1;
    private JButton button2;
    private JPanel panel;
    
    public ChangeBackground() {
        panel = new JPanel();
        button1 = new JButton("노란색");
        button2 = new JButton("분홍색");
        
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                panel.setBackground(Color.yellow);
            }
        });
        
        button2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                panel.setBackground(Color.pink);
            }
        });
    
    	panel.add(button1);
        panel.add(button2);
    	add(panel);
        setSize(500, 400);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    
    
    public static void main(String[] args) {
        new ChangeBackground();
    }
}
// 내부클래스

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ChangeBackground extends JFrame {
    private JButton button1;
    private JButton button2;
    private JPanel panel;
    MyListener listener = new MyListener();
    
    public ChangeBackground() {
        panel = new JPanel();
        button1 = new JButton("노란색");
        button2 = new JButton("분홍색");
 
        button1.addActionListener(listener);
        button2.addActionListener(listener);
    
    	panel.add(button1);
        panel.add(button2);
    	add(panel);
        setSize(500, 400);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    private class MyListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if(e.getSource() == button1)
                panel.setBackground(Color.yellow);
            else if(e.getSource() == button2) 
                panel.setBackground(Color.pink);
        }
    }
    
    public static void main(String[] args) {
        new ChangeBackground();
    }
}

 

예제 2) 키패드 만들기

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class KeyPad extends JFrame implements ActionListener {
    private JTextField txt;
    private JPanel panel;
    
    public KeyPad() {
        txt = new JTextField(20);
        add(txt, "North");
        
        panel = new JPanel();
        panel.setLayout(new GridLayout(3,3));
        add(panel, "Center");
        
        for(int i = 1; i <= 9; i++) {
            JButton btn = new JButton("" + i);
            btn.addActionListener(this);
            btn.setPreferredSize(new Dimension(100, 30));
            panel.add(btn);
        }
        
        pack();
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        String actionCommand = e.getActionCommand();
        txt.setText(txt.getText() + actionCommand);
    }
    
    public static void main(String[] args) {
        new KeyPad();
    }
}

 

예제 3) 가위바위보

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

public class RockPaperScissor extends JFrame implements ActionListener { 
    final int SCISSOR = 0;
    final int ROCK = 1;
    final int PAPER = 2;
    private JPanel panel;
    private JLabel output, information;
    private JButton rock, paper, scissor;
    public RockPaperScissor() {
        setSize(400, 150);
        
        panel = new JPanel();
        panel.setLayout(new GridLayout(0, 3));
        
        information = new JLabel("아래의 버튼 중 하나를 선택하세요.");
        output = new JLabel("Good Luck!");
        
        scissor = new JButton("0: 가위");
        rock = new JButton("1: 바위");
        paper = new JButton("2: 보");
        
        scissor.addActionListener(this);
        rock.addActionListener(this);
        paper.addActionListener(this);
        
        panel.add(scissor);
        panel.add(rock);
        panel.add(paper);
        
        add(information, "North");
        add(panel, "Center");
        add(output, "South");
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        JButton b = (JButton)e.getSource()    // 이벤트 발생 컴포넌트 추출
        int user = Integer.parseInt(""+b.getText().charAt(0)); // 첫번째 글자 추출
        Random random = new Random();
        int computer = random.nextInt(3);
        
        if(user == computer)
            output.setText("비겼음");
        else if(user == (computer + 1) % 3)     // 0은 1한테 진다
            output.setText("인간: " + user + " 컴퓨터: " + computer + " 인간 승리");
        else
            output.setText("인간: " + user + " 컴퓨터: " + computer + " 컴퓨터 승리");
    }
    
    public static void main(String[] args) {
        new RockPaperScissor();
    }
}

 

7. 키 이벤트

- 사용자가 키보드를 이용하여 입력하는 경우

- keyPressed : 키를 누르면 이벤트 발생

- keyReleased : 키에서 손을 떼면 이벤트 발생

- keyTyped : 입력된 유니코드 문자 전송됨

 

8. 포커스

- 컴포넌트가 키 이벤트를 받으려면 반드시 포커스(focus)를 가지고 있어야 함

- 포커스 : 키 입력을 받을 권리

- 일반적으로 오직 한 개의 컴포넌트만 포커스를 가지고 있어 키 입력을 독점하게 됨

panel.setFocusable(true);
panel.requestFocus();

 

9. KeyListener 인터페이스

public class MyListener implements KeyListener {
    public void keyPressed(KeyEvent e) {   }
    public void keyReleased(KeyEvent e) {   }
    public void keyTyped(KeyEvent e) {    }
}

 

10. KeyEvent 클래스

- int getKeyChar() : KeyEvent에 들어있는 글자 (유니코드) 반환

- int getKeyCode() : KeyEvent에 들어있는 keycode 반환 (글자가 아닌, 키보드 자판의 각각의 키를 가리키는 상수)

    - ex) Escape의 키코드 = VK_ESCAPE

- boolean isActionKey() : 이벤트를 발생시킨 키가 액션 키이면 true 반환

    - 액션 키 : Cut, Copy, Paste, Page Up, Caps Lock, 화살표, function 키

 

11. 자동차 움직이기 예제

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class MoveCar extends JFrame {
    int img_x = 150, img_y = 150;
    JButton button;
    
    public MoveCar() {
        setSize(600, 300);
        button = new Button("");       // 이미지 - 버튼으로 출력
        ImageIcon icon = new ImageIcon("car.png");   // 패키지 폴더에 있는 사진 
        button.setIcon(icon);
        
        JPanel panel = new JPanel();
        panel.setLayout(null);
        button.setLocation(img_x, img_y);
        button.setSize(200, 100);
        
        panel.add(button)
        panel.requestFocus();
        
        panel.setFocusable(true);
        panel.addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                int keycode = e.getKeyCode();
                switch(keycode) {
                case KeyEvent.VK_UP: img_y -= 10; break;
                case KeyEvent.VK_DOWN: img_y += 10; break;
                case KeyEvent.VK_LEFT: img_x -= 10; break;
                case KeyEvent.VK_RIGHT: img_x += 10; break;
                }
                button.setLocation(img_x, img_y);
            }
            public void keyReleased(KeyEvent arg0) { }
            public void keyTyped(KeyEvent arg0) { }
        });
        add(panel);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        new MoveCar();
    }
}

 

12. Mouse, MouseMotion 이벤트

1) MouseListener 인터페이스

public class MyListener implements MouseListener {
    public void mousePressed(MouseEvent e) {  }   // 사용자가 컴포넌트 클릭한 경우 
    public void mouseReleased(MouseEvent e) {  }  // 마우스가 컴포넌트에서 떼어진 경우
    public void mouseEntered(MouseEvent e) {  }   // 마우스 커서가 컴포넌트로 들어간 경우
    public void mouseExited(MouseEvent e) {  }    // 커서가 컴포넌트에서 나간 경우
    public void mouseClicked(MouseEvent e) {  }   // 마우스로 컴포넌트를 누른 경우
}

 

2) MouseMotionListener 인터페이스

public class MyClass implements MouseMotionListener {
    public void mouseDragged(MouseEvent e) {  } // 마우스를 드래그 한 경우
    public void mouseMoved(MouseEvent e) {  }   // 마우스를 클릭하지 않고 이동하는 경우
}


13. MouseEvent 객체

 

14. 어댑터 클래스

- 이벤트를 처리하기 위해서는 리스너 인터페이스에서 정의되어 있는 모든 메소드를 (사용하지 않더라도) 구현해야 함 -> 번거로움

- 어댑터 클래스를 이용하면 필요한 메소드만 재정의 가능

- 어댑터 클래스 : 인터페이스를 구현해놓은 클래스 -> 상속받기

public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener {
    public void mouseClicked(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseWheelMoved(MouseWheelEvent e) {}
    public void mouseDragged(MouseEvent e) {}
    public void mouseMoved(MouseEvent e) {}
}
class MyLister extends MouseAdapter {          // 리스너 클래스
    public void mouseCliked(MouseEvent e) {    // 필요한 메소드만 구현 
        if (e.getX > 300) { ... }
    }
}

1. 그래픽 사용자 인터페이스 (GUI)

- 컴포넌트들로 구성

Java AWT Java Swing
플랫폼에 의존적 플랫폼에 독립적
컴포넌트들이 용량이 큼 컴포넌트 용량이 가벼움
교체할 수 있는 룩앤필(look and feel) 지원 X 교체할 수 있는 룩앤필(look and feel) 지원 O
컴포넌트 개수 적음 컴포넌트 개수 많음

 

2. 스윙 패키지 

- java.awt : GUI 컴포넌트를 위한 부모 클래스들 제공 + color, point와 같은 유틸리티 타입의 클래스 포함

- java.awt.event : GUI 컴포넌트로부터 발생되는 이벤트를 처리하기 위한 클래스와 인터페이스 (버튼 클릭, 마우스 움직임 등)

- javax.swing : 버튼, 텍스트 필드, 프레임, 패널과 같은 GUI 컴포넌트들 포함

 

3. 컨테이너와 컴포넌트

- 기본 컴포넌트 : JButton, JLabel, JCheckBox, JChoice, JList, JMenu, JTextField, JScrollbar, JTextArea, JCanvas 등

- 컨테이너 컴포넌트 : 다른 컴포넌트들을 안에 포함할 수 있는 컴포넌트

   : JFrame, JDialog, JApplet, JPanel, JScrollPane 등

 

- 최상위 컨테이너 : 절대 다른 컨테이너 안에 포함될 수 없는 컨테이너 (JFrame, JDialog, JApplet 등)

- 일반 컨테이너 : 다른 컨테이너 안에 포함될 수 있는 컨테이너 (JPanel, JScrollPane 등)

 

4. GUI 작성 절차

- 컨테이너 생성 -> 컴포넌트 추가

 

5. 프레임 생성

#1
import javax.swing.*;

public class FrameTest {
    public static void main(String[] args) {
        JFrame f = new JFrame("Frame Test");
        f.setTitle("MyFrame");
        f.setSize(300, 200);
        f.setVisible(true);
        f.DefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
#2
import javax.swing.*;

public class MyFrame extends JFrame {
    pubic MyFrame() {
        setSize(300, 200);
        setTitle("My Frame");
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        new MyFrame();
    }
}

 

6. 프레임에 버튼 추가

import javax.swing.*;
import java.awt.*;

public class MyFrame extends JFrame {
    public MyFrame() {
        setSize(300, 200);
        setTitle("My Frame");
        
        setLayout(new FlowLayout());
        JButton button = new JButton("버튼");
        add(button);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    public static void main(String[] args) {
        new MyFrame();
    }
}

 

7. 컨테이너 - JFrame

 

- 컨테이너는 컴포넌트들을 트리 형태로 저장

- 최상위 컨테이너는 이 트리의 루트 노드가 됨

- 최상위 컨테이너는 내부에 콘텐트 팬 보유 - 화면에 보이는 컴포넌트 저장

- 최상위 컨테이너에는 메뉴바 추가 가능

 

7-1) 중요 메소드

- add(component) : 프레임에 컴포넌트 추가

- setLocation(x, y), setSize(width, height) : 프레임의 위치와 크기 설정

- setIconImage(IconImage) : 윈도우 시스템에 타이틀 바, 태스크 스위처에 표시할 아이콘

- setTitle() : 타이틀바 제목 변경

- setResizable(boolean) : 사용자가 크기 조절 가능 여부

 

8. JPanel 클래스

- 패널 : 컴포넌트들을 부착할 수 있도록 설계된 컨테이너 중 하나 (최상위 컨테이너는 아님)

- 별도의 패널을 쓰는 것이 유지 보수 및 배치 관리에 유리한 경우가 많음

 

- add(aComponent) : 패널에 컴포넌트 추가

- remove(aComponent) : 패널에 컴포넌트 삭제

- setBackGround(Color c) : 패널의 배경색 변경

 

8-1) 예제

public class MyFrame extends JFrampe {
    public MyFrame() {
        JPanel panel = new JPanel();
        panel.setBackground(Color.orange);
        
        JButton b1 = new JButton("Button 1");
        b1.setBackground(Color.yellow);
        
        JButton b2 = new JButton("Button 2");
        b2.setBackground(Color.green);
        
        panel.add(b1);
        panel.add(b2);
        add(panel);
        
        setSize(300, 150);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    public static void main(String[] args) {
        new MyFrame();
    }
}

 

9. 배치 관리자 (layout manager)

- 컨테이너만 사용 가능

- 컨테이너 안의 각 컴포넌트의 위치와 크기를 결정하는 작업

 

 9-1) 배치관리자 종류

1) FlowLayout

- 컨테이너에 추가되는 순서대로 컴포넌트 배치

- 위에서 아래로, 왼쪽에서 오른쪽으로

- 패널의 기본 배치 관리자

 

2) BorderLayout

- 컨테이너의 영역을 동서남북, 중앙의 5개 영역으로 구분하여 배치

- 한 구역에 한 개의 컴포넌트만 배치 가능

- add(btn, "South");

- 프레임의 기본 배치관리자

 

3) GridLayout

- 컨테이너 공간을 동일한 크기의 격자로 나누고, 이 격자에 컴포넌트 배치

 

4) CardLayout

- 컨테이너에 컴포넌트를 카드처럼 겹치게 쌓아 배치

- 한 번에 하나의 컴포넌트만 볼 수있게 배치

 

9-2) 설정

- 생성자 이용 : JPanel panel = new JPanel(new BorderLayout());

- setLayout() 이용 : panel.setLayout(new FlowLayout());

 

10. 절대 위치로 배치

- 배치 관리자  null로 설정 : setLayout(null);

- add() 메소드로 컴포넌트를 컨테이너에 추가

- 컴포넌트위 위치와 크기 지정

   - setBounds(h, w, a, d);

1. 패키지

- 관련 있는 클래스들을 하나로 묶은 것

- 내장 패키지 & 사용자 정의 패키지

- '이름 공간' - 동일한 이름의 클래스가 각 다른 패키지에 속할 수 있어 이름 충돌을 방지할 수 있음

- 세밀한 접근 제어 구현 가능 

- 파일의 맨 처음에 package 이름;

 

2. 패키지 사용

- 완전한 이름으로 참조하기 (패키지 이름이 클래스 앞에 붙음)

graphics.Rectangle myRect = new graphics.Rectangle();

 - 패키지 안에서 원하는 클래스만 포함하기

import graphics.Rectangle;

Rectangle myRect = new Rectangle();

 

- 패키지 안의 모든 클래스 포함하기

import graphics.*;

Rectangle myRect = new Rectangle();

 

 

3. 계층 구조의 패키지 

- ex) java - awt - font 구조의 패키지들이 있을 때,

java.awt.*를 포함시키면 java.awt.font 패키지는 자동으로 포함되지 않음!

별도로 포함시키기

import java.awt.*;
import java.awt.font.*;

 

4. 클래스 파일 로드

- 자바 소스 파일이 컴파일되면 .class 확장자를 가지는 클래스 파일로 변환되고 파일 시스템에 저장됨

- 클래스 파일은 JVM에 의해 로드됨

 

5. JVM이 클래스를 찾는 순서와 방법

- 부트스트랩 클래스

    - 자바 플랫폼을 구성하는 핵심적인 클래스

    - 디렉터리 jre/lib에 있는 여러 jar 파일들

 

- 확장 클래스

    - 자바 확장 메커니즘 사용하는 클래스

    - 확장 디렉터리에 있는 jar 파일들

 

- 사용자

    - 확장 메커니즘을 활용하지 않는 개발자 및 타사에서 정의한 클래스

 

- 방법

    - 현재 디렉터리 찾음

    - 일반적으로는 환경 변수인 CLASSPATH에 설정된 디렉터리에서 찾음

 

6. 자바 API 패키지

 

7. Object 클래스

- java.lang 패키지에 들어있음

- 자바 클래스 계층 구조에서 맨 위에 위치하는 클래스

- 메소드

 

- getClass() : 객체가 어떤 클래스로 생성되었는지에 대한 정보 반환

class Circle {  }
public class CircleTest {
    public static void main(String[] args) {
        Circle obj = new Circle();
        System.out.println("obj is of type " + obj.getClass().getName());
        System.out.println("obj의 해쉬코드=" + obj.hashCode());
    }
}

// obj is of type test.Circle
// obj의 해쉬코드=1554547125

 

- toString() : 객체의 문자열 표현 반환

- equals() : == 연산자 사용해서 객체의 주소가 동일한지 검사

 

8. Wrapper 클래스

- 정수와 같은 기초 자료형을 객체로 포장하고 싶은 경우 사용

int i = 100;
Integer obj = new Integer(i);

 

- 메소드

- 문자열 "100" -> 정수 100 : Integer.parseInt()

- 정수 100 -> 문자열 "100" : Integer.toString()

 

9. 오토박싱

- intValue() 대신

- 랩퍼 객체와 기초 자료형 사이의 변환을 자동으로 해주는 기능

Integer obj;

obj = 10;                      // 정수 -> Integer 객체
System.out.println(obj + 1);   // Integer 객체 -> 정수

 

10. String 클래스

- 메소드

 

 

11. String 클래스의 문자열 기초 연산

- length() : 문자열 길이 반환

- charAt() : String 객체 안에 들어있는 문자 추출 (문자 번호는 0부터 시작)

String s = "Hello World!"
char c = s.charAt(0);         // 'H' 반환

- 2개의 문자열 붙이는 방법

    - concat()

    - + 연산자   (** 더 편함!)

 

- indexOf() : 문자열 안에서 단어 찾기

String s = "The cat is on the table";
int index = s.indexOf("table");

if(index == -1)
    System.out.println("table은 없습니다.");
else
    System.out.println("table의 위치: " + index);

// table의 위치: 18

    - 같은 단어가 여러 번 있는 경우 가장 처음에 나오는 단어의 인덱스 반환

    - 모두 찾고 싶은 경우 반복문 이용!

 

- split() : 문자열을 단어로 분리

String[] tokens = "I am a boy.".split(" ");
for (String token : tokens)
    System.out.println(token);

/**
I
am
a
boy
**/

 

- boolean contains(charSequence s) : s에 지정된 문자들을 포함하고 있으면 true 리턴

- String replace(Charsequence target, Charsequence replacement) : target이 지정하는 일련의 문자들을 replacement가 지정하는 문자들로 변경한 문자열 객체 리턴

- String subString(int beginIndex) : beginIndex 인덱스부터 시작하는 부분 문자열 반환

- String subString(int beginIndex, int endIndex) : beginIndex부터 endIndex(포함x)까지의 부분 문자열 반환

- String trim() : 문자열 앞뒤의 공백 문자들을 제거한 문자열 객체 반환

 

12. StringBuffer 클래스

- String 클래스의 경우 빈번하게 문자열을 변경할 때 비효율적

∵ 새로운 String 객체를 생성하고 기존의 내용을 복사해야 하기 때문

 

 

- 메소드

    - append()

    - insert()

    - 어떤 타입의 데이터도 받을 수 있도록 중복 정의 되어있음

StringBuffer sb = new StringBuffer("Hello");   // 16바이트 공간 할당
int length = sb.length();        // 5
int capacity = sb.capacity();    // 21

StringBuffer sb = new StringBuffer("10+20=");
sb.append(10+20);
sb.insert(0, "수식 ");
// sb = "수식 10+20=30"

 

13. Math 클래스

- 지수, 로그, 제곱근, 삼각함수와 같은 기본적인 수치 연산을 위한 메소드 제공

 

14. Random 클래스

- 난수 발생

import java.util.*;
public class RandomTest {
    public static void main(String[] args) {
        Random random = new Random();
        for (int i = 0; i < 10; i++) 
            System.out.print(random.nextInt(100) + ", ");
    }
}

// 12, 48, 9, 3, 44, 84, 60, 4, 34, 50,

 

15. Array 클래스

import java.util.*;

public class ArraysTest {
    public static void main(String[] args) {
        int[] array = {9, 4, 5, 6, 2, 1};
        Arrays.sort(array);               // 정렬
        printArray(array);
        System.out.println(Arrays.binarySearch(array, 9));     // 9 탐색
        Arrays.fill(array,8);       // 배열 8로 채움
        printArray(array);
    }
    
    private static void printArray(int[] array) {
        System.out.print("[");
        for(int i = 0; i < array.length; i++)
            System.out.print(array[i] + " ");
        System.out.println("]");
    }
}

/**
[1 2 4 5 6 9 ]
5
[8 8 8 8 8 8 ]

 

16. Calender 클래스

- 추상 클래스, 날짜와 시간에 대한 정보

- 특정 시각을 연도, 월, 일 등으로 변환하는 메소드

 

17. 예외처리

- 오류가 발생했을 때 오류를 사용자에게 알려주고, 모든 데이터를 저장하게 한 후에 사용자가 프로그램을 종료할 수 있도록 하는 것이 바람직!

- 예외: 잘못된 코드, 부정확한 데이터, 예외적인 상황에 의해 발생하는 오류

- ex) 0으로 나누는 연산, 배열의 인덱스가 한계를 넘는 경우, 디스크에서 하드웨어 오류 발생 등

 

public class DivideByZero {
    public static void main(String[] args) {
        int result = 10 / 0;
        System.out.println("나눗셈 결과: " + result);
    }
}

// 오류

 

18. try-catch 블록

try {
    // 예외가 발생할 수 있는 코드
} catch (예외 클래스 변수) {
    // 예외를 처리하는 코드
}
// 아래 구문은 생략 가능
} finally {
    // 여기 있는 코드는 try 블록이 끝나면 무조건 실행됨
}

-ex)

import java.util.Scanner;

public class DivideByZeroOk {
    public static void main(String[] args) {
        try {
            int retult = 10 / 0;   // 예외 발생
        } catch (ArithmeticException e) {
            System.out.println("0으로 나눌 수 없습니다.");
        }
        System.out.println("프로그램은 계속 진행됩니다.");
    }
}

// 0으로 나눌 수 없습니다.
// 프로그램은 계속 진행됩니다.

 

19. 예외의 종류

- Error : 너무 심각해서 할 수 있는 방법이 없음 -> 통과

- RuntimeException : 프로그래밍 버그이므로 스스로 고쳐야 함 -> 통과

- Error나 RuntimeException이 아닌 예외 : 반드시 처리해야 함!! -> 검사

 

 

// 배열 인덱스 예외 처리

public class ArrayError {
    public static void main(String[] args) {
        int [] array = { 1, 2, 3, 4, 5 };
        int i = 0;
        
        try  {
            for (i = 0; i <= array.length; i++)
                System.out.print(array[i] + " ");
        } catch ArrayIndexOutOfBoundsException e) {
            System.out.pritnln("인덱스 " + i + "는 사용할 수 없네요!");
        }
    }
}

// 1 2 3 4 5 인덱스 5는 사용할 수 없네요!
// 입력 예외 처리

public class ExceptionTest3 {
    public static void main(String[] args) {
        try { 
            int num = Integer.parseInt("ABC");
            System.out.println(num);
        } catch (NumberFormatException e) {
            System.out.println("NumberFormat 예외 발생");
        }
    }
}

 

20. try - with - resources 문장

- 문장의 끝에서 리소스들이 자동으로 닫혀지게 함

import java.io.*;

public class TryTest {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("test.txt")) {
            char[] a = new char[50];
            fr.read(a);
            for (char c : a)
                System.out.print(c);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

21. 예외 떠넘기기

- 가끔 메소드가 발생되는 예외를 그 자리에서 처리하지 않고, 자신을 호출한 상위 메소드로 전달하는 편이 더 적절할 수 있음

import java.io.*;

pulbic class ExceptionTest {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("test.txt");
        char[] a = new char[50];
        fr.read(a);
        for (char c : a)
            System.out.print(c);
    }
}

 

'Software > JAVA' 카테고리의 다른 글

[JAVA] Day9. 이벤트 처리  (2) 2023.01.08
[JAVA] Day8. 자바 GUI 기초  (2) 2023.01.08
[JAVA] Day6. 추상클래스, 인터페이스, 중첩클래스  (0) 2022.12.29
[JAVA] Day5. 상속  (0) 2022.12.29
[JAVA] Day 3-4. 클래스와 객체  (2) 2022.12.29

1. 추상 클래스 (abstract class)

- 추상 메소드를 가지고 있는 클래스

- 추상 메소드: 메소드의 선언부(헤드)만 있는 메소드 (= 구현이 되지 않은 클래스)

- ex) void print(int n);

 

- 메소드가 미완성이므로 추상 클래스로는 객체 생성 불가능

- 주로 상속 계층에서 추상적인 개념을 나타내기 위한 용도로 사용

 

- 정의: 앞에 abstract 붙임

public abstract class Animal {
    public abstract void move();
}

public class Lion extends Animal {
    public void move() {
        System.out.println("사자의 move() 메소드");
    }
}

- 추상 클래스를 상속 받으면 추상 메소드를 구현해야 함!!

 

- ex) 도형 클래스

- 각 도형은 위치, 회전 각도, 선 색상, 채우는 색 등의 속성은 모든 도형이 공유

- 기준점을 이동하는 메소드 translate()도 모든 도형에서 동일

-> Shape에서 구체적으로 정의됨

- But) draw() 메소드는 도형마다 그리는 방법이 모두 다르기 때문에 구체적으로 정의될 수 없음

- 메소드의 이름과 매개 변수는 정의될 수 있음 -> 추상 메소드 사용

- draw()의 몸체는 각 자식 클래스에서 정의됨

 

abstract class Shape {
    int x, y;
    public void translate(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    pulic abstract void draw();
}

class Rectangle extends Shape {
    int width, height;
    @Override
    public void draw() { System.out.println("Rectangle draw"); }
}

class Circle extends Shape {
    int radius;
    @Override
    public void draw() { System.out.println("Circle draw"); }
}

public class AbstractTest {
    public static void main(String[] args) {
        // Shape s1 = new Shape();  -> 추상 클래스로 객체 생성 불가능
        Shape s2 = new Circle();    // 업캐스팅
        s2.draw();
    }
}

// Circle draw

 

 

-  추상 메소드로 정의되면 자식 클래스에서 반드시 오버라이드 해야함!

 

2. 하드웨어 인터페이스

- 컴퓨터 하드웨어에서 인터페이스는 서로 다른 장치들이 연결되어 상호 데이터를 주고받는 규격을 의미

- 각자의 클래스를 다른 사람의 클래스와 연결하려면 클래스 간의 상호작용을 기술하는 규격 필요 -> 인터페이스로 정의

 

3. 인터페이스의 용도

- 상속 관계가 아닌, 클래스 간의 유사성을 인코딩하는 데 사용됨 

- ex) 사람과 자동차는 둘 다 달릴 수 있지만, 부모 클래스로 Runner로 정의하고 사람과 차를 Runner의 자식 클래스로 나타내는건 이상함

-> Runnable 인터페이스를 만들고 이 인터페이스를 양쪽 클래스가 구현하도록

 

public interface RemoteControl {
    // 추상 메소드 정의
    public void turnOn();
    public void turnOff();
}

- 인터페이스는 추상 메소드들과 디폴트 메소드들로 이루어짐

- 인터페이스 내에 필드 선언될 수 없음!

- 상수는 정의 가능

 

4. 인터페이스 구현과 사용

class Television implements RemoteControl {
    boolean On;
    public void turnOn() {
        on = true;
        System.out.println("TV ON");
    }
    
    public void turnOff() {
        on = false;
        System.out.println("TV OFF");
    }
}

- 인터페이스는 다른 클래스들에 의해 구현될 수 있음

= 인터페이스에 정의된 추상 메소드의 몸체 정의한다는 의미

 

Television t = new Television();
t.turnOn();
t.turnOff();

 

5. 인터페이스 vs 추상 클래스

- 추상 클래스 사용 권장

    - 관련된 클래스들 사이에서 코드 공유하고 싶은 경우

    - 공통적인 필드나 메소드의 수가 많은 경우

    - public 이외의 접근 지정자를 사용해야 하는 경우

    - 일반 멤버 필드를 선언하기 원하는 경우

 

- 인터페이스 사용 권장

    - 관련 없는 클래스들이 동일한 동작을 구현하기 원할 때 (ex. Comparable, Cloneable)

    - 특정한 자료형의 동작을 지정하고 싶지만, 누가 구현하든지 신경 쓸 필요가 없을 때

    - 다중 상속이 필요할 때

 

6. 인터페이스와 타입

- 인터페이스를 정의하는 것 = 새로운 자료형을 정의하는 것!

// Television 객체이지만 RemoteControl 인터페이스 구현
// -> RemoteControl 타입의 변수로 가리킬 수 있음
RemoteControl obj = new Television();

// obj를 통해서는 RemoteControl 인터페이스에 정의된 메소드만 호출 가능
obj.turnOn();
obj.turnOff();

 

- default 함수 오버라이드 가능

interface RemoteControl {
    ...
    public default void printBrand() { System.out.println("Remote Control 가능 TV"); }
}

class Television implements RemoteControl {
    ...
    @Override
    public void printBrand() { System.out.println("Power JAVA TV"); }
}

public class TestInterface {
    public static void main(String[] args) {
        RemoteControl obj = new Television();
        obj.printBrand();
    }
}

// Power JAVA TV

 

7. 인터페이스 상속

- 인터페이스도 다른 인터페이스 상속받을 수 있음!

 

8. 인터페이스를 이용한 다중 상속

- 다중 상속: 하나의 클래스가 여러 개의 부모 클래스를 갖는 것

 

- 동시에 여러 인터페이스 구현

interface Drivable {
    void drive();
}

interface Flyable {
    void fly();
}

public class FlyingCar1 implements Drivable, Flyable {
    public void drive() { System.out.println("I'm driving"); }
    public void fly() { System.out.println("I'm flying"); }
    
    public static void main(String[] args) {
        FlyingCar1 obj = new FlyingCar1();
        obj.drive();
        obj.fly();
    }
}

// I'm driving
// I'm flying

 

- 하나의 클래스 상속받고 또 하나의 인터페이스 구현

interface Flyable { void fly(); }

class Car {
    int speed;
    void setSpeed(int speed) { this.speed = speed; }
}

public class FlyingCar2 extends Car implements Flyable {
    public void fly() { System.out.println("I'm flying!"); }
    
    public static void main(String[] args) {
        FlyingCar2 obj = new FlyingCar2();
        obj.setSpeed(300);
        obj.fly();
    }
}

// I'm flying!

 

9. 인터페이스에서의 상수 정의

- 인터페이스에서 정의된 변수는 자동적으로 public static final이 되어서 상수가 됨!

 

10. 디폴트 메소드와 정적 메소드

- 디폴트 메소드: 인터페이스 개발자가 메소드의 디폴트 구현을 제공할 수 있는 기능

 

11. 자율 주행 자동차 예시

public interface OperateCar {
    void start();
    void stop();
    void setSpeed(int speed);
    void turn(int degree);
}

public class AutoCar implements OperateCar {
    public void start() { System.out.println("출발"); }
    public void sotp() { System.out.println("정지"); }
    pubilc void setSpeed(int speed) { System.out.println("속도를 "+ speed + "km/h로 변경"); }
    public void turn(int degree) { System.out.println("방향을 " + degree + "도 만큼 변경"); }
}

public class AutoCarTest {
    public static void main(String[] args) {
        OperateCar obj = new AutoCar();
        obj.start();
        obj.setSpeed(30);
        obj.turn(15);
        obj.stop();
    }
}

 

12. Comparable 인터페이스

- 객체와 객체의 순서 비교할 때 사용

public interface Comparable {       // 실제로는 제네릭을 사용해서 정의됨
    int compareTo(Object other);    // -1, 0, 1 반환
}

class Rectangle implements Comparable {
    public int width = 0;
    public int height = 0;
    
    @Override
    public String toString() {
        return "Rectangle [width=" + width + ", height=" + height + "]";
    }
    
    public Rectangle(int w, int h) {
        width = w;
        height = h;
        System.out.println(this);
    }
    
    public int getArea() {
        return width * height;
    }
    
    @Override
    public int compareTo(Object other) {
        Rectangle otherRect = (Rectangle) other;
        if (this.getArea() < otherRect.getArea())
            return -1;
        else if (this.getArea() > otherRect.getArea())
            return 1;
        else
            return 0;
    }
}

public class RectangleTest {
    public static void main(String[] args) {
        Rectangle r1 = new Rectangle(100, 30);
        Rectangle r2 = new Rectangle(200, 10);
        int result = r1.compareTo(r2);
        if (result == 1)
            System.out.println(r1 + "가 더 큼");
        else if (result == 0)
            System.out.println("같음");
        else
            System.out.println(r2 + "가 더 큼");
    }
}

 

13. 중첩 클래스

- 클래스 안에서 클래스 정의

- 정적 중첩 클래스: 앞에 static이 붙어서 내장되는 클래스

- 비정적 중첩 클래스: static이 붙지 않은 일반적인 중첩 클래스

    - 내부 클래스(inner class): 클래스의 멤버처럼 선언되는 중첩 클래스

    - 지역 클래스(local class): 메소드의 몸체 안에서 선언되는 중첩 클래스

    - 익명 클래스(anonymouse class): 수식의 중간에서 선언되고 바로 객체화되는 클래스

 

13-1. 내부 클래스

- 클래스 안에 클래스를 선언하는 경우

- 내부 클래스는 외부 클래스의 인스턴스 변수와 메소드 전부 사용 가능

 

13-2. 지역 클래스

- 메소드 안에 정의되는 클래스

- 메소드 안에서만 사용 가능

 

13-3. 중첩 클래스 사용하는 이유

- 내부 클래스는 외부 클래스의 private 멤버도 접근할 수 있음

 

13-4. 익명 클래스

- 클래스 몸체는 정의되지만 이름이 없는 클래스

- 클래스를 정의하면서 동시에 객체 생성

- 이름이 없기 때문에 한번만 사용 가능

- 부모클래스 참조변수 = new 부모클래스 () { .. }

 

public interface RemoteControl {
    void turnOn();
    void turnOff();
}

public class AnonymousClassTest {
    public static void main(String[] args) {
        // 익명 클래스 정의
        RemoteControl ac = new RemoteControl() {
            public void turnOn() {
                System.out.println("TV turnOn()");
            }
            public void turnOff() {
                System.out.println("TV turnOff()");
            }
        }
        ac.turnOn();
        ac.turnOff();
    }
}

 

'Software > JAVA' 카테고리의 다른 글

[JAVA] Day8. 자바 GUI 기초  (2) 2023.01.08
[JAVA] Day7. 자바 API 패키지, 예외처리, 모듈  (0) 2023.01.02
[JAVA] Day5. 상속  (0) 2022.12.29
[JAVA] Day 3-4. 클래스와 객체  (2) 2022.12.29
[JAVA] Day2. 조건문, 반복문, 배열  (0) 2022.12.27

+ Recent posts