자바칩

[자바의 신] 기말고사, 기말 실습문제 본문

Study/Java

[자바의 신] 기말고사, 기말 실습문제

아기제이 2024. 5. 30. 13:40
728x90

기말고사

 

1. String 클래스와 StringBuilder, StringBuffer 클래스의 차이를 정리해 주세요.

클래스 차이점
String 불변성 객체이므로, + 연산을 하면 원본 객체는 버리고 새로운 객체를 리턴한다.
StringBuilder 가변성 객체이므로, append() 메소드를 통해 원본 객체를 변경할 수 있다. Thread Safe하지 않다.
StirngBuffer 가변성 객체이므로, append() 메소드를 통해 원본 객체를 변경할 수 있다. Thread Safe하다.

 

 

2. String 클래스의 indexOf(), substring(), split(), getBytes() 메소드가 어떤 용도로 사용되는지 정리해 주세요.

메소드 용도
indexOf() 문자열 내에서 매개 변수로 들어온 문자열이 시작하는 위치를 리턴한다.
substring() 문자열 내에서 첫번째 매개변수의 위치부터 두번째 매개변수의 위치 - 1까지 문자열을 잘라서 리턴한다.
split() 매개변수 내의 정규 표현식에 맞게 문자열을 나눠서 String 배열로 리턴한다.
getBytes() 문자열을 byte 배열로 바꿔서 리턴한다.

 

 

3. System 클래스의 주요 용도를 정리해 주세요.

System 클래스는 시스템에 대한 정보를 확인하는 클래스이다.
- 시스템 속성(Property)값 관리
- 시스템 환경(Environment) 값 조회
- GC 수행
- JVM 종료
- 현재 시간 조회

 

 

4. System 클래스에서 여러분들이 절대로 사용해서는 안 되는 메소드들은 무엇이고, 그 이유를 정리해주세요.

GC 수행 메소드 설명
gc() 가비지 컬렉터를 실행한다.
runFinalization() GC 처리를 기다리는 모든 객체에 대하여 finalize() 메소드를 실행한다.
이 메소드들을 직접 호출하지 않아도 알아서 JVM이 더 이상 필요 없는 객체를 처리하는 GC 작업과 finalization 작업을 실행한다. 만약 명시적으로 이 메소드를 호출하는 코드를 집어 넣으면, 시스템은 하려던 일을 멈추고 이 작업을 실행한다.
JVM 종료 메소드 설명
exit(int status) 현재 수행중인 JVM을 멈춘다.
이 메소드를 호출하지 않아도 소스들은 알아서 죽는다. 이 메소드를 사용하면 해당 애플리케이션의 JVM이 죽어버려서 바로 장애로 직결되어서 큰일이 날 수도 있다.
매개 변수의 값이 0일 경우에만 정상적인 종료를 의미하고, 그 외의 숫자는 비정상적인 종료를 의미한다.

 

 

5. 제네릭을 사용하는 가장 큰 이유는 무엇인지 정리해 주세요.

타입 형 변환의 문제점을 사전에 제거하기 위해서 사용한다. 여기서 사전이라는 것은, 컴파일할 때를 의미한다.

 

 

6. Set의 용도와 주요 클래스를 정리해 주세요.

Set은 순서를 생각하지 않고, 중복을 제거해주는 용도이다.
주요 클래스는 HashSet, TreeSet, LinkedHashSet 등이 있다.

 

 

7. Set의 데이터를 하나씩 꺼내는 방법을 정리해 주세요.

1. for문 사용
Set<Integer> nums = new HashSet<Integer>();
for (int num : nums) {
    System.out.println(num);
}

2. Iterator 객체 사용
Set<Integer> nums = new HashSet<Integer>();
Iterator iterator= nums.iterator();    // Iterator 객체 생성
while (iterator.hasNext()) {     // 다음 요소가 있는지 확인
    System.out.println(iterator.next());     // 다음 요소를 꺼내옴
}

 

 

8. ArrayList와 같은 List와 배열의 차이가 무엇인지 정리해 주세요.

  차이점
List 저장 공간의 크기가 변한다.
배열 저장 공간의 크기가 고정되어 있다.

 

 

9. Queue의 용도는 무엇이며, LinkedList의 특징이 무엇인지 정리해 주세요.

FIFO(First-In-First-Out, 선입선출)구조로, 먼저 들어온 요소가 먼저 나가게 하기 위한 용도이다.
LinkedList는 각 요소마다 위치 번호는 없고, 요소들은 앞과 뒤만 기억한다. ArrayList같은 경우에는 맨 앞에 있던 요소를 삭제하면 그 뒤에 있던 모든 요소들이 앞으로 한 칸씩 앞당겨지지만, LinkedList는 이런 작업을 하지 않아도 된다. 그래서 Queue에서 LinkedList를 사용하는 것이다.
또한, 중간에 있던 요소에 접근과 삭제가 잦을 경우 ArrayList보다는 LinkedList를 사용하는 것이 좋다. ArrayList는 중간에 있던 요소를 삭제하면 그 뒤에 있던 모든 요소들이 앞으로 한 칸씩 앞당겨지지만, LinkedList는 삭제된 요소의 앞과 뒤에 있던 요소들만 연결시켜주면 되기 때문이다.

 

 

10. Map의 용도와 주요 클래스를 정리해 주세요.

Map은 키(key)와 값(value)를 한 쌍으로 관리한다. 순서를 생각하지 않고, 키는 중복이 되면 안되지만 값은 중복이 되어도 된다. 배열과 List에서는 위치 인덱스를 통해 값을 찾아내지만 Map은 키를 통해 값을 찾아낸다.
주요 클래스는 HashMap, TreeMap, LinkedHashMap 등이 있다.

 

 

11. Arrays 클래스의 주요 용도는 무엇인지 정리해 주세요. 

배열에서 주로 하는 작업을 쉽게 해주는 메소드들을 모아놓은 클래스이다.
배열을 정렬할 때에는 for문을 돌려서 일일히 해야하지만, Arrays클래스의 sort() 메소드를 사용하면 한 번에 정렬이 되어서 편하다. 

*버블 정렬
int[] nums = { 4, 5, 2, 1, 3 };
for (int i = 0; i < 5; i++) {
    for (int j = i; j < 5; j++) {
        if (nums[i] > nums[j]) {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
}
for (int num : nums) {
    System.out.println(num);    // 출력 결과:  1 2 3 4 5


*Arrays.sort()
int[] nums = { 4, 5, 2, 1, 3 };
Arrays.sort(nums);
for (int num : nums) {
    System.out.println(num);    // 출력 결과: 1 2 3 4 5
}

파란색으로 표시한 부분은 정렬하는 과정이다.

 

 

12. StringTokenizer 클래스의 용도는 무엇인지 정리해 주세요.

StringTokenizer 생성자의 매개 변수로 넘겨준 정규 표현식에 맞춰서 String 문자열을 토큰별로 나누어준다.

 

 

13. Thread 클래스를 확장한 클래스를 구현할 때 항상 만들어야 하는 메소드는 무엇인가요? 접근 제어자, 리턴 타입, 메소드 이름을 적어 주세요.

public void run()

 

 

14. Thread 클래스와 Runnable 인터페이스를 구현하여 만든 쓰레드를 실행하려면 각각 어떻게 해야 하는지 정리해 주세요.

1. Thread 클래스를 확장한 쓰레드 실행
public ThreadSample extends Thread {
    public void run() {
        System.out.println("Thread 클래스 확장");
    }
}
ThreadSample thread = new ThreadSample();
thread.start();       // ThreadSample의 run() 메소드 실행

2. Runnable 인터페이스를 구현한 쓰레드 실행
public RunnableSample implements Runnable {
    public void run() {
        System.out.println("Runnable 인터페이스 구현");
    }
}
RunnableSample thread = new RunnableSample();
new Thread(thread).start();      // RunnableSample의 run() 메소드 실행

 

 

15. Synchronized에 대해서 정리해 주세요.

한 객체 내에 있는 인스턴스 변수를 조작하는 메소드에 여러 쓰레드가 동시에 접근했을 때, 인스턴스 변수의 값이 꼬여서 저장되는 것을 방지하기 위해서 synchronized를 사용한다. 이렇게 하면 synchronized로 선언한 메소드나 블록에는 한 번에 한 쓰레드만 접근할 수 있다.

*사용 예시
public class A {
    int result = 0;
    Object lock = new Object();       // 잠금 상태(하나의 쓰레드만 사용)를 처리하기 위한 객체
    // 인스턴스 변수를 조작하는 메소드에 synchronized 선언
    public synchronized void add(int value) {   
        result += value;
    }
    public void subtract(int value) {  
        // 인스턴스 변수를 조작하는 코드에 synchronized 블록 선언
        synchronized(lock) {       
            result -= value;
        }
    }
}

 

 

16. InputStream 클래스의 용도는 무엇이고, Reader 클래스와 어떤 점이 다른지 정리해 주세요.

클래스 차이점
InputStream 바이트 코드를 읽을 때 사용한다.
Reader char나 문자열을 읽을 때 사용한다.

 

 

17. 클래스 선언 시 Serializable을 구현하는 이유는 무엇인지 정리해 주세요.

객체를 저장하거나 다른 서버로 전송하는 행위를 하기 위해서는 Serializable 인터페이스를 구현해야만 한다.

 

 

18. transient로 선언한 변수는 다른 변수와 어떻게 다른지 정리해 주세요.

transient로 선언한 변수는 저장하거나 다른 서버로 전송하지 않는다. 보안이 중요한 변수를 처리할 때 사용한다.

 

 

19. TCP 통신을 처리하기 위해서 사용하는 클래스는 무엇인지 정리해 주세요. 

클래스 용도
Socket 데이터를 전달하고 받기 위해서 사용한다.
ServerSocket 데이터를 수신하기 위해서 사용한다.
클라이언트에서 데이터를 전달하면 Socket 객체로 받아 처리한다.

 

 

20. UDP 통신을 처리하기 위해서 사용하는 클래스는 무엇인지 정리해 주세요.

클래스 용도
DatagramPacket 데이터를 전달하고 받기 위해서 사용한다.
DatagramSocket 데이터를 수신하기 위해서 사용한다.
클라이언트에서 데이터를 전달하면 DatagramPacket 객체로 받아 처리한다.

기말 실습문제

SimpleWebServer.java

 
    package com.basicjava.server;   // 1번

    import java.net.ServerSocket;
    import java.net.Socket;

    import com.basicjava.server.handler.RequestHandler;

    public class SimpleWebServer {  // 1번
        public static void main(String[] args) {    // 1번
            SimpleWebServer server = new SimpleWebServer();
            int port = 9000;
            server.run(port);
        }

        // 6번
        public void run(int port) {    
            ServerSocket server = null;    
            Socket socket = null;
            try {
                server = new ServerSocket(port);  
                while (true) {
                    socket = server.accept();
                    RequestHandler requestHandler = new RequestHandler(socket);
                    requestHandler.start();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (server != null) {
                    try {
                        server.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

 

RequestHandler.java

 
    package com.basicjava.server.handler;   // 2번

    import java.net.Socket;

    import com.basicjava.server.dto.RequestDTO;
    import com.basicjava.server.manager.RequestManager;
    import com.basicjava.server.manager.ResponseManager;

    public class RequestHandler extends Thread {    // 2번
        private Socket socket;  // 2번

        // 2번
        public RequestHandler(Socket socket) {
            this.socket = socket;
        }

        public void run() {     // 2번
            // 7번
            RequestManager requestManager = new RequestManager(socket);
            RequestDTO requestDTO = requestManager.readRequest();
            ResponseManager responseManager = new ResponseManager(socket, requestDTO);
            responseManager.writeResponse();
        }
    }

 

RequestDTO.java

 
    package com.basicjava.server.dto;   // 3번

    // 3번
    public class RequestDTO {
        private String requestMethod = "GET";
        private String uri = "/";
        private String httpVersion = "HTTP/1.1";

        public String getRequestMethod() {
            return requestMethod;
        }

        public void setRequestMethod(String requestMethod) {
            this.requestMethod = requestMethod;
        }

        public String getUri() {
            return uri;
        }

        public void setUri(String uri) {
            this.uri = uri;
        }

        public String getHttpVersion() {
            return httpVersion;
        }

        public void setHttpVersion(String httpVersion) {
            this.httpVersion = httpVersion;
        }
    }

 

RequestManager.java

 
    package com.basicjava.server.manager;   // 4번

    import java.io.BufferedInputStream;
    import java.io.InputStream;
    import java.net.Socket;

    import com.basicjava.server.dto.RequestDTO;

    public class RequestManager {   // 4번
        private Socket socket;      // 4번
        private final int BUFFER_SIZE = 2048;

        // 4번
        public RequestManager(Socket socket) {
            this.socket = socket;
        }

        public RequestDTO readRequest() {   // 4번
            RequestDTO requestDTO = new RequestDTO();   // 4번
            // 8번
            try {
                InputStream request = new BufferedInputStream(socket.getInputStream());
                byte[] receivedBytes = new byte[BUFFER_SIZE];
                request.read(receivedBytes);
                String requestData = new String(receivedBytes).trim();
                System.out.println("RequestData = \n" + requestData);
                System.out.println("----------");
                int index = requestData.indexOf("Host");
                String[] header = requestData.substring(0, index).split(" ");
                requestDTO.setRequestMethod(header[0]);
                requestDTO.setUri(header[1]);
                requestDTO.setHttpVersion(header[2]);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return requestDTO;  // 4번
        }
    }

 

ResponseManager.java

 
    package com.basicjava.server.manager;

    import java.io.PrintStream;
    import java.net.Socket;
    import java.util.Date;

    import com.basicjava.server.dto.RequestDTO;

    public class ResponseManager {  // 5번
        // 5번
        private Socket socket;
        private RequestDTO requestDTO;

        // 5번
        public ResponseManager(Socket socket, RequestDTO requestDTO) {
            this.socket = socket;
            this.requestDTO = requestDTO;
        }

        public void writeResponse() {   // 5번
            // 8번
            try {
                PrintStream response = new PrintStream(socket.getOutputStream());
                String requestMethod = requestDTO.getRequestMethod();
                String uri = requestDTO.getUri();
                String httpVersion = requestDTO.getHttpVersion();
                response.println(httpVersion + " 200 OK");
                response.println("Content-type: text/html");
                response.println();
                if (uri.equals("/today")) {
                    response.print(new Date());
                } else {
                    response.print("It is working");
                }
                response.flush();
                response.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

 

 

자바의 신 1권과 2권까지 자바 버전 변경 부분을 제외하고 다 읽는데 1달이 걸렸다.

짧은 시간동안 많은 분량을 읽고 공부를 했다.

1권을 읽으면서 생각보다 앞 부분에서 몰랐던 개념도 있었고, 2권을 읽으면서는 아예 새로 배운 개념들도 있었다.

기말 실습문제에서는 자바에서 배운 것으로 간단한 웹 개발도 해보았다.

Thread, Stream, Socket 개념은 생소한데, 실습을 해보면서 개념을 확실하게 알게 되는 시간을 가졌다.

이제부터는 객체지향의 원리와 이해 책을 읽을 것이다.

앞으로 더욱 성장하는 개발자가 되고 싶다.