Java Category/Java

[JAVA] System, Class 클래스

ReBugs 2023. 1. 20.

본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다.


System 클래스

자바 프로그램은 JVM위에서 실행된다. java.lang 패키지에 속하는 System 클래스의 정적 필드와 메소드를 이용하면 프로그램 종료, 키보드 입력, 콘솔(모니터) 출력, 현재 시간 읽기, 시스템 프로퍼티 읽기 등이 가능하다.

System 클래스의 모든 필드와 메소드는 정적 필드와 정적 메소드로 구성되어 있다.

정적 멤버 용도
필드 out 콘솔에 문자 출력
err 콘솔에 에러 내용 출력(빨간 글자색)
in 키보드 입력
메소드 exit(int status) 프로세스 종료(JVM 종료)
currentTimeMillis() 현재 시간을 밀리초 단위의 long 값으로 리턴
nanoTime() 현재 시간을 나노초 단위의 long 값으로 리턴
getProperty() 운영체제와 사용자 정보 제공
getenv() 운영체제의 환경 변수 정보 제공

 

콘솔 출력

out을 이용하면 콘솔에 원하는 문자열을 출력할 수 있다.

err도 out과 동일한데, 차이점은 콘솔 종류에 따라 에러 내용이 빨간색으로 출력된다는 것이다.

public class ErrExample {
	public static void main(String[] args) {
		try {
			int value = Integer.parseInt("1oo");
		} catch(NumberFormatException e) {
			System.err.println("[에러 내용]");
			System.err.println(e.getMessage());
		}
	}
}


키보드 입력

자바는 키보드로부터 입력된 키를 읽기 위해 System 클래스에서 in 필드를 제공한다.

다음과 같이 in 필드를 이용해서 read() 메소드를 호출하면 입력된 키의 코드값을 얻을 수 있다.

출처 : 이것이 자바다 유튜브 동영상 강의

read() 메소드는 호출과 동시에 키 코드를 읽는 것이 아니라, 엔터키를 눌기 전까지는 대기상태이다가 엔터키를 누르면 입력했던 키들을 하나씩 읽기 시작한다.

단 read() 메소드는 IO 예외를 발생할 수 있는 코드이므로 예외처리가 필요하다.

 

아래의 예제는 숫자 키 1과 2를 입력함에 따라 speed 변수값을 증감하는 예제이다. 3을 누르면 종료

public class InExample {
	public static void main(String[] args) throws Exception {
		int speed = 0;
		int keyCode = 0;

		while(true) {
			if(keyCode != 13 && keyCode != 10) { //Enter 키를 읽지 않았을 경우에만 실행
				if (keyCode == 49) { 				//숫자 1 키를 읽었을 경우
					speed++;
				} else if (keyCode == 50) {			//숫자 2 키를 읽었을 경우
					speed--;
				} else if (keyCode == 51) { 		//숫자 3 키를 읽었을 경우
					break;
				}
				System.out.println("-----------------------------");
				System.out.println("1. 증속 | 2. 감속 | 3. 중지");
				System.out.println("-----------------------------");
				System.out.println("현재 속도= " + speed);
				System.out.print("선택: ");
			}
			
			//키를 하나씩 읽음
			keyCode = System.in.read();
		}
		
		System.out.println("프로그램 종료");
	}
}
/*
-----------------------------
1. 증속 | 2. 감속 | 3. 중지
-----------------------------
현재 속도= 0
선택: 1
-----------------------------
1. 증속 | 2. 감속 | 3. 중지
-----------------------------
현재 속도= 1
선택: 2
-----------------------------
1. 증속 | 2. 감속 | 3. 중지
-----------------------------
현재 속도= 0
선택: 1
-----------------------------
1. 증속 | 2. 감속 | 3. 중지
-----------------------------
현재 속도= 1
선택: 1
-----------------------------
1. 증속 | 2. 감속 | 3. 중지
-----------------------------
현재 속도= 2
선택: 1
-----------------------------
1. 증속 | 2. 감속 | 3. 중지
-----------------------------
현재 속도= 3
선택: 1
-----------------------------
1. 증속 | 2. 감속 | 3. 중지
-----------------------------
현재 속도= 4
선택: 1
-----------------------------
1. 증속 | 2. 감속 | 3. 중지
-----------------------------
현재 속도= 5
선택: 3
프로그램 종료
*/

프로그램 종료(exit())

경우에 따라서 강제적으로 JVM을 종료시킬 때도 있다. 이때 System클래스의 exit()메소드를 호출하면 된다.

exit()메소드는 int 매개값을 지정하도록 되어 있는데, 이 값을 종료 상태값이라고 한다. 일반적으로 정상 종료일 경우 0값을 준다.

비정상 종료는 1또는 -1로 주는 것이 관례이다.

System.exit(0); // JVM(프로그램) 강제종료 코드

현재 시각 읽기(currentTimeMillis(), nanoTime())

System 클래스의 currentTimeMillis(), nanoTime() 메소드는 컴퓨터의 시계로부터 현재 시간을 읽어서 밀리세컨드(1/1000초) 단위와 나노세컨드(1/10^9초) 단위의 long 값을 리턴한다.

리턴값은 주로 프로그램의 실행 소요 시간 측정에 사용된다.

아래의 코드는 1부터 100만까지의 합을 구하는데 걸린 시간을 출력하는 코드이다.

public class Main {
	public static void main(String[] args) {
		long time1 = System.nanoTime();
		
		int sum = 0;
		for(int i=1; i<=1000000; i++) {
			sum += i;
		}
		
		long time2 = System.nanoTime();
		
		System.out.println("1~1000000까지의 합 : " + sum);
		System.out.println("계산에 " + (time2-time1) + " 나노초가 소요됨");
		System.out.println((time2-time1)/(10e9));
	}
}
/*
1~1000000까지의 합 : 1784293664
계산에 2873700 나노초가 소요됨
2.8737E-4
 */

 

2.8737 * 10^-4 = 0.00028737초가 소요된 것을 알 수 있다.

 


시스템 프로퍼티(System Property) 읽기

시스템 프로퍼티란 자바 프로그램이 시작될 때 자동 설정되는 시스템의 속성을 말한다.

예를 들어 운영체제 종류 및 사용자 정보, 자바 버전 등의 기본 사양 정보가 해당한다.

속성 이름(key) 설명
java.specification.version 자바 스펙 버전
java.home JDK 디렉토리 경로
os.name 운영체제
user.name 사용자 이름
user.home 사용자 홈 디렉토리 경로
user.dir 현재 디렉토리 경로

 

import java.util.Properties;
import java.util.Set;

public class GetPropertyExample {
	public static void main(String[] args) {
		//운영체제와 사용자 정보 출력
		String osName = System.getProperty("os.name");
		String userName = System.getProperty("user.name");
		String userHome = System.getProperty("user.home");
		System.out.println(osName);
		System.out.println(userName);
		System.out.println(userHome);

		//전체 키와 값을 출력
		System.out.println("---------------------------------");
		System.out.println(" key: value");
		System.out.println("---------------------------------");
		Properties props = System.getProperties();
		Set keys = props.keySet();
		for(Object objKey : keys) {
			String key = (String) objKey;
			String value = System.getProperty(key);
			System.out.printf("%-40s: %s\n", key, value);
		}
	}
}
/*
Windows 11
Lee
C:\Users\Lee
---------------------------------
 key: value
---------------------------------
java.specification.version              : 17
sun.cpu.isalist                         : amd64
sun.jnu.encoding                        : MS949
java.class.path                         : D:\프로그래밍\Eclipse\thisisjava\bin;D:\프로그래밍\Eclipse\thisisjava\lib\lombok.jar
java.vm.vendor                          : Oracle Corporation
sun.arch.data.model                     : 64
user.variant                            : 
java.vendor.url                         : https://java.oracle.com/
java.vm.specification.version           : 17
os.name                                 : Windows 11
....
....
더 많다
*/

 

 

Class 클래스

자바는 클래스와 인터페이스의 메타 데이터를 java.lang 패키지에 소속된 Class로 관리한다.

메타 데이터란 클래스의 이름, 생성자 정보, 필드 정보, 메소드 정보를 말한다.

 

Class 객체얻기(getClass(), forName())

Class 객체를 얻기 위해서 아래의 세 가지 방법 중 하나를 이용하면 된다.

//how1
Class clazz = String.class;

//how2
Class clazz2 = Class.forName("java.lang.String");

//how3
String str = new String();
Class clazz3 = str.getClass();

 

아래의 코드는 모두 같은 클래스를 얻어서 전체이름, 간단한 이름, 패키지의 이름을 출력하는 코드이다.

모두 같은 Class 객체를 얻었기 때문에 출력결과가 같다.

public class Main {
	public static void main(String[] args) throws ClassNotFoundException {
		//how1
		Class clazz = String.class;
		
		//how2
		Class clazz2 = Class.forName("java.lang.String");
		
		//how3
		String str = new String();
		Class clazz3 = str.getClass();
		
		System.out.println(clazz.getName()); //전체이름
		System.out.println(clazz.getSimpleName()); // 간단한 이름
		System.out.println(clazz.getPackage().getName()); // 패키지이름
		System.out.println();
		System.out.println(clazz2.getName()); //전체이름
		System.out.println(clazz2.getSimpleName()); // 간단한 이름
		System.out.println(clazz2.getPackage().getName()); // 패키지이름
		System.out.println();
		System.out.println(clazz3.getName()); //전체이름
		System.out.println(clazz3.getSimpleName()); // 간단한 이름
		System.out.println(clazz3.getPackage().getName()); // 패키지이름
	}
}
/*
java.lang.String
String
java.lang

java.lang.String
String
java.lang

java.lang.String
String
java.lang
 */

 

 

클래스 경로를 활용해서 리소스 절대 경로 얻기

Class 객체는 해당 클래스의 파일 경로 정보를 가지고 있기 때문에 이 경로를 활용해서 다른 리소스 파일의 경로를 얻을 수 있다.

TestPackage 폴더 안에는 bin폴더, Main.java, file1.jpg가 있고, bin 폴더 안에는 file2.jpg가 있다.

public class Main {
	public static void main(String[] args){
		Class clazz = Main.class;

		String photo1Path = clazz.getResource("file1.jpg").getPath();
		String photo2Path = clazz.getResource("bin/file2.jpg").getPath();
		
		System.out.println(photo1Path);
		System.out.println(photo2Path);
	}
}s
/*
/C:/Users/Lee/eclipse-workspace/TestProject/bin/TestPackage/file1.jpg
/C:/Users/Lee/eclipse-workspace/TestProject/bin/TestPackage/bin/file2.jpg
 */

위 코드는 Main.class를 기준으로 한 상대 경로를 이용해서 절대경로를 얻는 코드이다.

댓글