1. java.lang 패키지
1.1 Object
Object 클래스는 자바의 최상위 부모 클래스로 모든 클래스는 Object 클래스의 자식이거나 자손 클래스이다. 때문에 클래스를 선언할 때 extends 키워드가 명시되어 있지 않더라도 암시적으로 Object 클래스를 상속한다. 그 근거로 모든 클래스에서는 Object의 메소드인 equals, toString을 사용할 수 있다.
equals와 ==의 차이점
보통 두 객체를 동등 비교할 때 equals와 ==를 사용하지만 결과는 조금 다르다. ==는 객체의 번지를 비교하여 두 객체가 동일한 객체이면 true를 리턴하며 그렇지 않으면 false를 리턴한다. Object의 equals의 경우 ==와 동일하지만 프로그래머가 보통 사용하는 equals는 String 클래스에서 오버라이딩한 equals 메소드이다. 때문에 객체의 번지를 비교하는 것이 아니라, 문자열이 동일한지를 비교하여 같다면 true를 그렇지 않다면 false를 리턴한다.
toString 메소드
Object 클래스의 toString() 메소드는 객체의 문자 정보를 리턴한다. 하지만 이 정보의 경우 많이 사용되지 않기 때문에 대부분 toString 메소드를 재정의하여 간결하고 유익한 정보를 리턴하도록 한다.
라이브러리 클래스(SmartPhone)를 보면 toString() 메소드를 재정의하여 해당 클래스의 필드 값을 리턴하도록 했다. 그 결과 실행 클래스(SmartPhoneExample)에서 println메소드를 이용하여 출력(11,12)하였을 경우 Object 클래스의 toString이 아니라 프로그래머가 재정의한 toString이 출력된다. (참조 변수가 가리키는 객체 안에 재정의 된 toString이 있으면 재정의 된 toStrig이 출력)
1.2 Class 클래스
자바는 클래스와 인터페이스의 메타 데이터(클래스 이름, 생성자 정보, 필드 정보 등)를 Class 클래스로 관리하기 때문에 Class 객체를 얻기 위해서는 다음과 같은 방법을 사용할 수 있다.
<클래스로부터 얻는 방법>
1) Class clazz = 클래스이름.class
2) Class clazz = Class.forName("패키지...클래스이름")
<객체로부터 얻는 방법>
3)Class clazz = 참조변수.getClass()
1,2번과 같이 객체 없이 클래스 이름만을 가지고 Class 객체를 얻을 수 있고 클래스로부터 객체가 생성되어 있을 경우에는 3번과 같이 사용할 수 있다.
Class 객체에는 해당 클래스의 파일 경로 정보를 가지고 있기 때문에 이 경로를 활용해서 다른 리소스 파일의 경로를 얻을 수 있다.
Car.class를 기준으로 하기 위해 Car.class 위치를 clazz 참조 변수에 넣어준다. 그 후 9, 10번 줄과 같이 참조변수를 통해 해당 위치에 파일이 있는지 getResource 메소드를 이용해 확인한 후 getPath 메소드를 이용해 절대 경로를 가져와 String 형의 참조 변수에 넣어줌으로 절대 경로를 얻을 수 있다.
1.3 String 클래스
문자열을 사용하기 위한 클래스이다.
System.in.read는 사용자가 키보드를 이용하여 입력할 때 키코드 값(아스키 코드)을 읽는다. 원래 한 문자씩만 가능하지만 10번째 줄과 같이 사용할 경우에는 byte 타입의 빈 배열을 인수로 받아서 해당 배열에 저장한다. (네트워크를 통해 받은 데이터는 보통 byte[] 배열이기 때문에 사용.) 그 후 실제 읽은 바이트 수를 정수로 반환한다. byte 배열에 저장한 값을 12번째 줄과 같이 사용하여 문자열로 바꿀 수 있다. -2를 해주는 이유는 캐리지 리턴과 라인 피드 부분을 제외하고 문자열을 만들기 위해서다.
String 클래스는 문자열의 추출, 비교, 찾기, 분리 등과 같은 다양한 메소드를 가지고 있다.
indexOf() : 문자열 찾기
매개값으로 주어진 문자열이 시작되는 인덱스를 리턴하며 문자열이 포함되어 있지 않으면 -1을 리턴한다.
응용해서 배열에도 적용할 수 있다. for문을 이용해 모든 배열을 살펴보는 과정에서 indexOf를 사용하면 해당 문자열이 포함되어있는지 확인할 수 있다.
replace() : 문자열 대치
첫 번째 매개값인 문자열을 찾아 두 번째 매개값인 문자열로 대치하여 새로운 문자열을 생성하고 리턴한다.
substring() : 문자열 잘라내기
주어진 인덱스에서 문자열을 추출한다.
7번째 줄과 같이 매개 변수가 두개가 있을 경우에는 주어진 첫 번째 매개변수를 시작 인덱스, 두 번째 매개변수를 끝 인덱스로 사이의 문자열을 추출한다. 10번째 줄과 같이 매개변수가 하나일 경우에는 주어진 매개변수를 시작 인덱스로 하여 끝까지 문자열을 추출한다.
2. java.util 패키지
java.util 패키지는 프로그램 개발에서 자주 사용하는 자료구조와 날짜 정보를 제공해주는 API를 포함하고 있다.
2.1 Date 클래스
날짜를 표현하는 클래스로 객체 간에 날짜 정보를 주고받을 때 매개 변수나 리턴 타입으로 주로 사용한다.
현재 시각의 Date 객체를 생성하는 방법은 다음과 같다.
Date now = new Date();
Date 객체의 toString()은 영문으로 된 날짜를 리턴하기 때문에 원하는 날짜 형식의 문자열을 얻기 위해서는 다음과 같은 방법을 사용해야 한다.
import java.text.SimpleDateFormat;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // 바뀔 수 있음
String strNow = sdf.format(now) // 문자열로 저장
2.2 Calendar 클래스
달력을 표현한 클래스이다. Calendar 클래스는 추상 클래스(싱글톤 객체임)로 new 연산자를 사용해서 인스턴스를 생성할 수 없기 때문에 다음과 같은 방법으로 현재 os에 설정되어 있는 시간대를 기준으로 Calendar 하위 객체를 얻을 수 있다.
Calendar now = Calendar.getInstance();
Calendar 클래스의 DAY_OF_MONTH는 1~7을 반환한다.
3. 스레드 (thread)
3.1 메인 스레드
자바의 모든 애플리케이션은 메인 스레드가 main() 메소드를 실행하면서 시작한다. 메인 스레드는 main() 메소드의 첫 코드부터 아래로 순차적으로 실행하고, main() 메소드의 마지막 코드를 실행하거나 return을 만나면 실행이 종료된다.
메인 스레드는 필요에 따라 작업 스레드들을 만들어서 병렬로 코드를 실행할 수 있다.
멀티 스레드 애플리케이션의 경우 실행 중인 스레드가 하나라도 있다면, 프로세스는 종료되지 않는다. 메인 스레드가 작업 스레드보다 먼저 종료되더라도 작업 스레드가 계속 실행 중이라면 프로세스는 종료되지 않는다는 뜻이다. 싱글 스레드의 경우 메인 스레드가 종료하면 프로세스도 종료된다.
3.2 작업 스레드
멀티 스레드로 실행하는 애플리케이션을 개발하기 위해서는 몇 개의 작업을 병렬로 실행할지 우선 결정한 뒤 각 작업별로 스레드를 생성해야 한다. 작업 스레드 또한 객체로 생성되므로 클래스가 필요하며 생성 방법은 다음과 같다.
// Runnable을 매개값으로 갖는 생성자 호출
Thread thread = new Thread(Runnable target);
// 구현 객체 만들어 대입 필요
class Task implements Runnable {
public void run() { 스레드가 실행할 코드; }
}
// Runnable 익명 객체를 매개값으로 사용하여 Thread 생성자 호출
Thread thread = new Thread (new Runnable() {
public void run() { 스레드가 실행할 코드; }
} );
Runnable은 run() 메소드만 있는 인터페이스임으로 사용하기 위해서는 구현 객체를 만들어야 한다. 또한 run() 메서드를 실행하는 방법은 다음과 같다.
thread.start();
작업 스레드를 사용하기 위해 Runnable을 구현하는 클래스를 생성하여 run() 메소드를 재정의한다. (run 메소드 안에 있는 toolkit.beep()는 소리가 나게 해줌. -> 소리를 못들으니 문자열 출력으로 대체) 그후 실행 클래스에서 해당 객체를 생성하고 해당 객체를 매개값으로 Thread 생성자를 호출해 작업 스레드를 생성해준다. 그리고 7번째 줄과 같이 작업 스레드를 실행해준다. 그 결과 출력값을 보면 메인 스레드에서 출력되는 "띵"과 작업 스레드에서 출력되는 "동"을 통해 두 스레드가 동시에(병렬) 실행되고 있음을 알 수 있다.
위와 같이 작업 스레드가 실행할 작업을 Runnable로 만들 수 있지만, Thread의 하위 클래스로 작업 스레드를 정의하면서 작업 내용을 포함시키는 방법이 있다.
예시와 같이 작업 스레드 클래스를 Thread 클래스를 상속하게 해준다. Thread는 이미 Runnable을 상속하고 있음으로 run() 메소드를 재정의할 수 있기 때문에 작업 스레드 클래스에 바로 재정의를 해준다.
스레드의 이름
스레드는 자신의 이름을 가지고 있으며 디버깅할 때 어떤 스레드가 어떤 작업을 하는지를 알기 위한 목적으로 사용된다. 사용 방법은 다음과 같다. (메인 스레드는 main, 생성한 스레드는 자동적으로 Thread-n 이름으로 설정됨.)
thread.setName("스레드 이름"); // Thread 이름 설정하기
thread.getName(); // Thread 이름 얻기
Thread thread = Thread.currentThread(); // 스레드 객체의 참조를 가지고 있지 않은 경우
4. 동기화 메소드
멀티 스레드 프로그램에서 스레드들이 객체를 공유해서 작업하는 경우 의도했던 것과 다른 결과가 발생할 수 있다.
위 코드 결과를 보면 user1의 run() 메소드에서 setMemory(100)을 했지만 user2에서 setMemory(50)을 한 것과 동일한 결과가 나오고 있다.
그 이유로는 calculator는 공유 객체로 사용되고 있다. 그 결과 user1 스레드가 잠시 멈춰있는 사이 user2의 스레드가 calculator의 memory의 설정 값을 변경했기 때문에 위와 같은 결과가 나온다.
위와 같이 한 스레드가 사용 중인 객체를 다른 스레드가 변경할 수 없도록 동기화 작업이 필요하다. 방법은 아래와 같이 간단하다.
[public] synchronized 반환타입 메소드(매개 변수...) {
실행 내용... }
'Develop' 카테고리의 다른 글
[Concept] JAVA (입출력 스트림, OutputStream, InputStream, Writer, Reader, 보조 스트림, 입출력 관련 API) (0) | 2022.07.20 |
---|---|
[Concept] JAVA (제네릭스, 컬렉션 프레임워크, Set, Map, Stack, Queue) (0) | 2022.07.04 |
[Concept] JAVA (인터페이스, 중첩 클래스, 익명 객체, 예외) (0) | 2022.06.16 |
[Concept] JAVA (객체, 싱글톤, 상속, 다형성, 생성자, Getter/Setter) (0) | 2022.06.13 |
[Concept] JAVA (데이터 타입, 타입 변환, 배열, for) (0) | 2022.06.01 |