본문 바로가기

JAVA/혼공자

[혼공자] Chapter 11-1 java.lang 패키지 (Object, System, Class)

Chapter 11. 기본 API 클래스

 

Intro. API 란?

API (Application Programming Interface)는
'응용 프로그램 / 프로그래밍 / 인터페이스'로
응용 프로그램에서 프로그래밍 언어를 제어할 수 있게 만든 인터페이스이다.
API는 다양한 분야에서 다양한 의미로 사용되는데,
여기서 자바 API란 자바를 쉽게 구현할 수 있게 한 클래스 라이브러리의 집합이다.
즉, 자바라는 언어를 사용하여 사용자의 부담을 최소화하는 반면에 
입출력, 화면 구성, 이미지, 네트워크와 같이 복잡하지만 필요한 클래스들을 미리 구현하여
사용자가 쉽게 구현하도록 하는 API이다.
더 쉽게 말하면,  java 프로그래밍에 자주 사용되는 패키지라고 생각하면 되겠다.


11-1 java.lang 패키지

java.lang 패키지는 자바의 기본적인 클래스를 담고 있는 패키지이다.
java.lang 패키지의 클래스는 별도의 import 없이 사용할 수 있다. Ex. String, System, Math
java.lang 패키지 안에는 많은 클래스가 있지만, 혼공자에서 공부할 클래스는 아래와 같다.

클래스 용도
Object - 자바 클래스의 최상위 클래스로 사용
System - 운영체제의 일부 기능을 사용할 수 있게 해줌
- 표준 입력장치(키보드)로부터 데이터를 입력받을 때 사용
- 표준 출력장치(모니터)로 출력하기 위해 사용
- 자바 가상 기계를 종료할 때 사용
- 쓰레기 수집기를 실행 요청할 때 사용
Class - 클래스를 메모리로 로딩할 때 사용
String - 문자열을 저장하고 여러가지 정보를 얻을 때 사용
Wrapper Byte, Short, Character,
Integer, Float, Double,
Boolean, Long
- 기본 타입의 데이터를 갖는 객체를 만들 때 사용
- 문자열을 기본 타입으로 변환할 때 사용 cf. Integer.parseInt
- 입력값 검사에 사용
Math - 수학 함수를 이용할 때 사용    

 

API Document 보는 방법

자바에서 제공하는 API는 documet로 정리되어있는데, 이 API documet를 활용하는 것도 개발 능력 중 하나이다.
but, 설명서처럼 document 보는 법을 하나하나 정리하려면 시간이 너무 오래 걸리므로 완전 직관적으로만 정리하겠음!
(더보기 클릭)

더보기

1. document HTML로 이동해서 보고자 하는 버전을 선택
https://docs.oracle.com/en/java/javase/index.html

java 8은 패키지 별로 정리하였고, java 11 이상은 모듈 별로 정리했기 때문에 레이아웃이 다를 수 있다.
확실한 방법을 위해선 패키지를 검색해도 된다.
이클립스에서 클래스에 마우스를 올리고 F1을 눌러서 API document를 볼 수도 있다. 
cf. 복습)) 모듈 = 프로젝트 = 큰 폴더 / 패키지 = 프로젝트 안에 들어가는 작은 폴더

2. 보고자 하는 클래스로 이동

 

Object 클래스

자바 모든 크래스의 최상위 클래스이다.
extends java.lang.Object가 생략되었더라도, 우리가 선언하는 클래스 역시 Object 클래스를 상속하고 있다.
즉, 자바의 모든 클래스는 Object 클래스의 메소드를 사용할 수 있다.
하지만, 대부분의 경우 Object 클래스의 메소드를 그대로 사용하지 않고, 클래스에 맞게 오버라이딩하여 사용한다.
Object 클래스의 본래 메소드와 해당 메소드를 어떻게 오버라이딩하여 사용하는지 확인해보자.

Object 클래스의 메소드
▶ 객체 비교 equals( )
오버라이드 전 : 주소를 비교하는 ==와 동일한 결과 리턴한다.
오버라이드 후 : 두 객체가 논리적으로 동등한지를 조사한다.
이때 논리적으로 동등하다는 것은, 객체의 번지수가 같은지를 리턴하는 ==와 달리,
그 안의 값이 같은지를 비교하는 것이다.
두 String이 같은지를 비교할 때, ==가 아니라 equals를 쓰는 것이 이러한 이유때문이다.

오버라이드 원리 : equals 메소드는 원래 비교연산자인 ==와 동일한 결과를 리턴하지만,
그대로 사용되지 않고 대부분 하위 클래스에서 오버라이딩되어 사용된다.
먼저, 두 객체가 같은 타입인지 확인한다.
이때 if ( 비교객체 instanceof 기존객체 ) 의 문법을 사용한다. 
두 객체가 같은 타입이라면, 강제 타입 변환을 하고, 필드 값이 동일한지 equals 메소드로 확인한다. 
두 if문을 모두 만족해야 true를 리턴하고 그렇지 않은 경우 false를 리턴한다.

class Member {
	public String id;
	
	Member(String id) {
		this.id = id;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Member) { // 같은 타입인지 조사
			Member member = (Member)obj; // 형변환
			if(id.equals(member.id)){ // 값이 같은지 조사 - String의 equals 사용됨
				return true;
			}
		}
		return false; 
	}
}

public class MemberExample {
	public static void main(String[] args) {
		Member obj1 = new Member("blue");
		Member obj2 = new Member("blue");
		Member obj3 = new Member("red");
		
		if(obj1.equals(obj2)) { // true
			System.out.println("obj1과 obj2는 동일합니다.");
		} else {
			System.out.println("obj1과 obj2는 동일하지 않습니다.");
		}
		
		if(obj1.equals(obj3)) { // false
			System.out.println("obj1과 obj3는 동일합니다.");
		} else {
			System.out.println("obj1과 obj3는 동일하지 않습니다.");
		}

	}
}

 


 객체 해시코드 hashCode( )
오버라이드 전 : 객체의 주소값을 변환하여 생성한 고유한 정수값을 리턴한다.
오버라이드 후 : 객체가 논리적으로 동등한지를 식별할 수 있는 정수값을 리턴한다.

오버라이드 원리 :
전제 ① ) 컬렉션 프레임워크인 HashSet, HashMap, Hashtable은 아래와 같은 방법으로 두 객체가 동등한지 비교한다.
(이유는 아직 안 알려주지만, 하지만 여튼 이런 과정을 거친다.)

if ( 두 객체의 hashCode( ) 리턴값이 같음 ) { 
    if(equals( ) 리턴값이 true) { 두 객체는 동등 객체 }
} else { 두 객체는 다른 객체 }

즉, 두 객체가 동등한지 판단하기 위해 1. hashCode( ) 리턴값이 같음 && 2. equals( ) 리턴값이 true를 만족해야 한다.


전제 ② ) Object 클래스의 hashCode( ) 는 '객체의 주소'를 기준으로 해쉬코드를 리턴한다.

이때 Object 클래스의 hashCode( )를 그대로 사용한다면, 전제 ①에서 설명한 방법에서 오류가 발생한다.
따라서 논리적으로 동등한 객체임을 확인하기 위한 첫번째 조건으로
'두 객체의 hashCode( ) 리턴값이 같은가?'를 사용하기 위해서는 hashCode( ) 가 오버라이딩 될 필요가 있다.
왜냐하면, new Student(1)로 생성된 객체와 new Student(1)로 생성된 객체는 동일한 식별값을 가지므로 
논리적으로 동등하게 봐야 하는데, 
이 둘은 주소 상 서로 다른 객체이므로 Object의 hashCode( ) 메소드는 이 둘의 해시코드를 다르게 리턴하기 때문이다.
따라서, hashCode( ) 메소드가 해당 객체의 int 식별자를 리턴하도록 오버라이딩해야된다.

 객체 문자 정보 toString( )
객체를 문자열로 표현한 값인 객체의 '문자 정보'를 리턴한다.
Object 클래스의 toString 메소드는 별 값어치 없는 문자열(클래스 + 16진수 해시코드)을 리턴하므로,
하위 클래스에서 유의미한 문자열을 리턴하도록 재정의한다.
또한, System.out.printl( )으로의 출력을 포맷화 하기 위해서도 toString( ) 메소드를 오버라이드 해두면 좋다.
System.out.printl( ) 메소드의 매개값으로 객체를 주면, 객체의 toString() 메소드를 호출하여 리턴값을 받아 출력하기 때문이다.
Ex. Student 클래스에서 toString()를 오버라이딩하여 "학번은 ~~ 입니다."를 출력하게 재정의한다면, 
System.out.printl( )의 매개로 Student 객체를 전달했을 때 바로 "학번은 ~~ 입니다."의 포맷으로 출력된다.

 

System 클래스

자바는 운영체제에서 실행되는 것이 아니라 JVM위에서 실행되므로 운영체제의 모든 기능을 직접 사용하긴 어렵다. 하지만, System 클래스를 이용하면 운영체제의 일부 기능을 사용할 수 있다. System의 모든 필드와 메소드는 정적 필드, 정적 메소드로 구성되어있다. 따라서 별도의 객체를 생성하지 않아도 System.method()의 문법으로 사용할 수 있다.

System 클래스의 메소드
- 프로그램 종료 exit(int num)
현재 실행중인 프로세스를 강제 종료시킨다. 매개변수로 주는 정수를 종료 상태값이라고 한다. 일반적으로 정상 종료일 경우 종료 상태값으로 0을 준다.
- 현재 시각 읽기 currentTimeMillis( ), nanoTime( )
컴퓨터 시계로부터 현재 시간을 읽어 각각 밀리 세컨드 단위, 나노 세컨드 단위의 long값을 리턴한다. 주로 시작시간과 종료 시간의 차를 구해 실행 소요 시간 측정에 사용된다.

public class SystemTimeExample {
	public static void main(String[] args) {
		long startTime = System.nanoTime(); // 시작시간
		
		int sum = 0;
		for(int i=0; i<=100; i++) {
			sum+=1;
		}
		
		long endTime = System.nanoTime(); // 종료시간
		
		System.out.println("1부터 100까지의 합:"+sum);
		System.out.println("소요 시간(nanosec):"+(endTime-startTime));

	}
}

 

Class 클래스

자바는 클래스와 인터페이스에 대한 정보인 메타 데이터를 Class 클래스로 관리한다. 여기서 메타 데이터란 클래스의 이름, 생성자 정보, 필드 정보, 메소드 정보를 말한다.

Class 클래스의 메소드
- Class 객체 얻기 getClass( ), forName( )
해당 클래스의 메타 데이터를 저장하고 있는 Class 객체를 얻는 세가지 방법
① 클래스로부터 얻는 방법
Class clazz = 클래스이름.class
Class clazz = Class.forName("패키지.클래스이름")
② 객체로부터 얻는 방법
Class clazz = 객체.getClass( );
이렇게 얻은 Class 객체에 메소드를 적용하면, Class 객체에 담긴 클래스의 메타 데이터를 얻을 수 있다.

- 리소스 절대경로 얻기 getResourse("리소스 위치").getPath( );
Class 클래스의 getResourse메소드를 이용하면 클래스의 위치를 기준으로 상대적 위치의 리소스를 가져올 수 있다. 
여기에 getPath( ) 메소드를 붙이면 리소스의 절대 위치를 얻을 수 있다.
Ex. 
Class clazz = Car.class; // clazz에 Car 클래스의 메타 데이터 저장됨
String photoPath = clazz.getResource("images/photo.jpg").getPath( );
// Car.class가 있는 패키지의 images 폴더의 photo.jpg 사진의 절대 경로를 얻을 수 있음