본문 바로가기
프로그래밍언어/Java

11-1 java.lang 패키지(2)

by 스꼬맹이브로 2022. 3. 2.
728x90
반응형
SMALL

(이전글 --> java.lang 패키지(1))

https://yuna96.tistory.com/109

 

11-1 java.lang 패키지(1)

java.lang 패키지는 자바 프로그의 기본적인 클래스를 담고 있는 패키지로 import 없이 사용이 가능하다. java.lang 패키지에 속하는 주요 클래스와 클래스의 용도를 간단하게 살펴보면 다음과 같다.

yuna96.tistory.com

 

< Class 클래스 >

자바는 클래스와 인터페이스의 메타 데이터(클래스 이름, 생성자·필드·메소드 정보)를 java.lang 패키지에 소속된 Class 클래스로 관리한다.

 

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

프로그램에서 Class 객체를 얻는 방법은 클래스로부터 얻는 방법 두 가지와 객체로부터 얻는 방법 한 가지로 총 세 가지가 있다.

// 클래스로부터 얻는 방법 1
Class clazz = 클래스이름.class

// 클래스로부터 얻는 방법 2
Class clazz = Class.forName("패키지...클래스이름")

//객체로부터 얻는 방법 3
Class clazz = 참조변수.getClass( );

첫 번째와 두 번째는 객체 없이 클래스 이름만으로 Class 객체를 얻는다.

세 번째는 클래스로부터 객체가 이미 생성되어 있을 경우 사용하는 방법이다.

 

다음 예제는 세 가지 방법을 사용하여 Car 클래스의 Class 객체를 얻고, Class 메소드를 이용하는 것을 보여준다.

//example 패키지 안에 있는 Car 클래스
package example;

public class Car {
	
}
package example;

public class ClassExample {
	public static void main(String[] args) throws Exception {
		//방법 1
		//Class clazz = Car.class;
		
		//방법 2
		//Class clazz = Class.forName("chap11.Car");
		
		//방법 3
		Car car = new Car();
		Class clazz = car.getClass();
		
		System.out.println(clazz.getName());
		System.out.println(clazz.getSimpleName());
		System.out.println(clazz.getPackage().getName());
	}
}

결과 : 

출력은 클래스의 전체 이름, 간단한 이름, 패키지 이름을 출력하였으며 세 가지 방법 동일한 결과를 확인할 수 있다.

 

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

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

이 방법은 UI 프로그램에서 많이 활용되며 방법은 getPath()함수를 사용한다.

 

예를 들어 Car클래스와 photo1.jpg, photo2.jpg 파일을 사용해야 한다고 가정하자.

프로그램 실행 중 이미지 파일의 절대 경로가 필요할 경우 Car.class를 기준으로 한 상대 경로를 이용해서 절대 경로를 얻을 수 있다.

파일 경로 예시

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

		String photo1Path = clazz.getResource("photo1.jpg").getPath();
		String photo2Path = clazz.getResource("images/photo2.jpg").getPath();
		
		System.out.println(photo1Path);
		System.out.println(photo2Path);
	}
}

결과 : 

사진의 입력값으로 상대 경로를 입력하였지만 출력값으로 절대 경로를 돌려준 것을 확인할 수 있다.

 

< String 클래스 >

어떤 프로그램이든 문자열은 데이터로서 아주 많이 사용된다.

그렇기 때문에 문자열을 생성하는 방법과 추출, 비교, 찾기, 분리, 변환 등을 제공하는 메소드들은 잘 익혀두어야 한다.

 

String 생성자

자바의 문자열은 java.lang 패키지의 String 클래스의 인스턴스로 관리된다.

소스상에서 문자열 리터럴은 String 객체로 자동 생성되지만 String 클래스의 다양한 생성자를 이용해서 직접 String 객체를 생성할 수도 있다.

어떤 생성자를 이용해서 String 객체를 생성할지는 제공되는 매개값의 타입에 달려있다.

 

다음은 String 클래스에서 사용 빈도 수가 높은 생성자들이다.

파일의 내용을 읽거나, 네트워크를 통해 받은 데이터는 보통 byte[ ] 배열이므로 이것을 문자열로 변환하기 위해 사용된다.

 

 

다음 예제를 통해 확인해보자.

public class ByteToStringExample {
	public static void main(String[] args) {
		byte[] bytes = { 72, 101, 108, 108, 111, 32, 74, 97, 118, 97  };
		
		String str1 = new String(bytes);
		System.out.println(str1);
		
		String str2 = new String(bytes, 6, 4); //bytes 배열의 74숫자 인덱스 위치부터 4개
		System.out.println(str2);
	}
}

결과 :

바이트 배열을 입력받아 문자열로 변환하여 출력해주는 것을 확인할 수 있다.

 

String 메소드

String 클래스는 문자열의 추출, 비교, 찾기, 분리, 변환 등과 같은 다양한 메소드를 가지고 있으며 사용 빈도수가 높은 메소드는 다음과 같다.

º 문자추출 charAt()

charAt() 메소드는 매개값으로 주어진 인텍스의 문자를 리턴한다.

다음은 주민등록번호를 통해 남자와 여자를 구분하는 예제이다.

public class StringCharAtExample {
	public static void main(String[] args) {
		String ssn = "010624-1230123"; //주민번호 
		char sex = ssn.charAt(7);
		switch (sex) {
			case '1':
			case '3':
				System.out.println("남자 입니다.");
				break;
			case '2':
			case '4':
				System.out.println("여자 입니다.");
				break;
		}
	}
}

결과 :

º 문자열 비교 equals()

기본 타입을 비교할 때에는 == 연산자를 사용하지만 문자열에서는 equals를 사용해야 한다.

== 연산자를 사용할 경우, String은 객체이기 때문에 new 연산자를 사용하여 다른 객체를 생성한 경우 같은 값일지라도 false를 출력하기 때문이다.

때문에 두 String 객체의 문자열만을 비교하고 싶다면 == 연산자 대신에 equals() 메소드를 사용해야 한다.

public class StringEqualsExample {
	public static void main(String[] args) {
		String strVar1 = new String("신민철");
		String strVar2 = "신민철";

		if(strVar1 == strVar2) {
			System.out.println("같은 String 객체를 참조");
		} else {
			System.out.println("다른 String 객체를 참조");
		}
		
		if(strVar1.equals(strVar2)) {
			System.out.println("같은 문자열을 가짐");
		} else {
			System.out.println("다른 문자열을 가짐");
		}
	}
}

결과 :

º 바이트 배열로 변환 getBytes()

네트워크로 문자열을 전송하거나, 문자열을 암호화할 때 문자열을 바이트 배열로 변환해야 할 필요가 있다.

이럴 경우 문자열을 바이트 배열로 변환하는 메소드는 두 가지가 있다.

byte[] bytes = "문자열".getBytes();
byte[] bytes = "문자열".getBytes(Charset charset);

첫 번째 메소드는 시스템의 기본 문자셋으로 인코딩된 바이트 배열을 리턴한다.

두 번째 메소드는 시스템의 기본 문자셋이 아닌 특정 문자셋으로 인코딩된 바이트 배열을 얻으려고 할 때 사용할 수 있다.

 

다음은 EUC-KR과 UTF-8로 각각 인코딩된 바이트 배열을 리턴하는 코드이다.

try {
	byte[] bytes1 = "문자열".getBytes("EUC-KR");
	byte[] bytes2 = "문자열".getBytes("UTF-8");
}catch(UnsupportedEncodingException e){
	
}

여기서 어떤 문자셋으로 인코딩하느냐에 따라 바이트 배열의 크기가 달라지며 EUC-KR의 경우 알파벳은 1바이트, 한글은 2바이트로 변환하고, UTF-8은 알파벳은 1바이트, 한글은 3바이트로 변환한다.

getBytes(Charset charset)메소드는 잘못된 문자셋을 매개값으로 줄 경우, java.io.UnsupportedEncodingException이 발생하므로 예외처리가 필요하다.

 

바이트 배열을 다시 문자열로 변환(디코딩)할 때에는 어떤 문자셋으로 인코딩된 바이트 배열이냐에 따라서 디코딩 방법이 달라진다.

단순히 String(byte[] bytes) 생성자를 이용해서 디코딩할 경우 시스템의 기본 문자셋을 이용하며 기본 문자셋이 아닌 다른 문자셋으로 인코딩된 바이트 배열일 경우 다음의 String 생성자를 이용해서 디코딩을 해야 한다.

String str = new String(byte[] bytes, String charsetName);

다음은 문자열을 바이트 배열로 인코딩하고 길이를 출력한 후 다시 디코딩하는 예제이다.

import java.io.UnsupportedEncodingException;

public class StringGetBytesExample {
	public static void main(String[] args) {
		String str = "안녕하세요";
		
		//시스템의 기본 문자셋으로 인코딩 및 디코딩
		byte[] bytes1 = str.getBytes();
		System.out.println("bytes1.length: " + bytes1.length);
		String str1 = new String(bytes1);
		System.out.println("bytes1->String: " + str1);
		
		try {
			//EUC-KR을 이용한 인코딩 및 디코딩
			byte[] bytes2 = str.getBytes("EUC-KR");
			System.out.println("bytes2.length: " + bytes2.length);
			String str2 = new String(bytes2, "EUC-KR");
			System.out.println("bytes2->String: " + str2);
			
			//UTF-8을 이용한 인코딩 및 디코딩
			byte[] bytes3 = str.getBytes("UTF-8");
			System.out.println("bytes3.length: " + bytes3.length);
			String str3 = new String(bytes3, "UTF-8");
			System.out.println("bytes3->String: " + str3);		
			
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
}

결과 : 

º 문자열 찾기 indexOf()

indexOf()메소드는 매개값으로 주어진 문자열이 시작되는 인덱스를 리턴한다.

만약 주어진 문자열이 포함되어 있지 않으면 -1을 리턴한다.

(주로 if문의 조건식에서 특정 문자열의 포함 여부에 따라 코드 실행 여부를 정할 때 사용된다.)

public class StringIndexOfExample {
	public static void main(String[] args) {
		String subject = "자바 프로그래밍";
		
		int location = subject.indexOf("프로그래밍");
		System.out.println(location);
		
		if(subject.indexOf("자바") != -1) {
			System.out.println("자바와 관련된 책이군요");
		} else {
			System.out.println("자바와 관련없는 책이군요");
		}
	}
}

결과 : 

º 문자열 길이 length()

length() 메소드는 문자열의 길이(문자의 수)를 리턴한다. 문자열에 포함된 공백까지 포함한다는 점 잊지 말자.

public class StringLengthExample {
	public static void main(String[] args) {
		String ssn = "7306241230123";
		int length = ssn.length();
		if(length == 13) {
			System.out.println("주민번호 자리수가 맞습니다.");
		} else {
			System.out.println("주민번호 자리수가 틀립니다.");
		}
	}
}

결과 :

º 문자열 대치 replace()

replace() 메소드는 첫 번째 매개값인 문자열을 찾아 두 번째 매개값인 문자열로 대치한 새로운 문자열을 생성하고 리턴한다.

여기서 리턴하는 문자열은 수정본이 아닌 완전한 새로운 문자열임을 기억하자.

public class StringReplaceExample {
	public static void main(String[] args) {
		String oldStr = "자바는 객체지향언어 입니다. 자바는 풍부한 API를 지원합니다.";
		String newStr = oldStr.replace("자바", "JAVA");
		
		System.out.println(oldStr);
		System.out.println(newStr);
	}
}

결과 :

º 문자열 잘라내기 substring()

substring() 메소드는 주어진 인덱스에서 문자열을 추출한다.

substring() 메소드는 매개값의 수에 따라 두 가지의 형태로 사용된다.

첫 번째로 매개값이 두 개일 경우, 시작과 끝 인덱스 사이의 문자열을 추출한다.

두 번째로 매개값이 한 개일 경우, 주어진 인덱스부터 끝까지 문자열을 추출한다.

public class StringSubstringExample {
	public static void main(String[] args) {	
		String ssn = "880815-1234567 ";
		
		String firstNum = ssn.substring(0, 6);
		System.out.println(firstNum);		
		
		String secondNum = ssn.substring(7);
		System.out.println(secondNum);
	} 
}

결과 :

º 알파벳 소/대문자 변경 toLowerCase(), toUpperCase()

toLowerCase() 메소드는 문자열을 모두 소문자로 바꾼 새로운 문자열을 생성 후 리턴한다.

toUpperCase() 메소드는 문자열을 모두 대문자로 바꾼 새로운 문자열을 생성 후 리턴한다.

다음 메소드들은 영어로 된 두 문자열을 대소문자 관계없이 비교할 때 주로 이용된다.

equals() 메소드를 사용할 경우, toLowerCase(), toUpperCase() 메소드를 사용하여 대소문자를 맞춰줘야 하지만equalsIgnoreCase() 메소드를 사용할 경우 이 작업이 생략된다.

public class StringToLowerUpperCaseExample {
	public static void main(String[] args) {
		String str1 = "Java Programming";
		String str2 = "JAVA Programming";		
		
		System.out.println(str1.equals(str2));
		
		String lowerStr1 = str1.toLowerCase();
		String lowerStr2 = str2.toLowerCase();
		System.out.println(lowerStr1.equals(lowerStr2));
		
		System.out.println(str1.equalsIgnoreCase(str2));				
	}
}

결과 :

º 문자열 앞뒤 공백 잘라내기 trim()

trim() 메소드는 문자열의 앞뒤 공백을 제거한 새로운 문자열을 생성하고 리턴한다.

public class StringTrimExample {
	public static void main(String[] args) {
		String tel1 = "  02";
		String tel2 = "123   ";
		String tel3 = "   1234   ";
		
		String tel = tel1.trim() + tel2.trim() + tel3.trim();
		System.out.println(tel);
	}
}

결과 :

º 문자열 변환 valueOf()

valueOf() 메소드는 기본 타입의 값을 문자열로 변환한다.

String 클래스에는 매개 변수의 타입별로 valueOf() 메소드가 다음과 같이 오버로딩이 되어있다.

static String valueOf(boolean b)
static String valueOf(char c)
static String valueOf(int i)
static String valueOf(long l)
static String valueOf(double d)
static String valueOf(float f)

(getClass() : Java에서 변수의 타입을 확인하는 메소드)

public class StringValueOfExample {
	public static void main(String[] args) {
		String str1 = String.valueOf(10);
		String str2 = String.valueOf(10.5);
		String str3 = String.valueOf(true);		
		
		System.out.println(str1 +", type : " + str1.getClass());
		System.out.println(str2 +", type : " + str2.getClass());
		System.out.println(str3 +", type : " + str3.getClass());
	
	}
}

결과 :

< Wrapper(포장) 클래스 >

자바는 기본 타입의 값을 갖는 객체를 생성할 수 있다.

이런 객체를 포장(Wrapper) 객체라고 하는데, 그 이유는 기본 타입의 값을 내부에 두고 포장하기 때문이다.

포장 객체의 특징은 포장하고 있는 기본 타입 값은 외부에서 변경할 수 없다는 것이다.

만약 내부의 값을 변경하고 싶다면 새로운 포장 객체를 만들어야 한다.

 

포장 클래스는 java.lang 패키지에 포함되어 있으며 기본 타입에 대응되는 클래스들은 다음과 같다.

▶ 박싱(Boxing)과 언박싱(Unboxing)

기본 타입의 값을 포장 객체로 만드는 과정을 박싱(Boxing)이라고 하고, 반대로 포장 객체에서 기본 타입의 값을 얻어내는 과정을 언박싱(Unboxing)이라고 한다.

 

다음은 박싱의 과정을 나타내며 간단하게 기본 타입의 값 또는 문자열을 넘겨주면 된다.

또한 생성자를 이용하지 않아도 각 포장 클래스마다 가지고 있는 정적 valueOf() 메소드를 사용하여 생성할 수도 있다.

//기본 타입의 값을 줄 경우
Integer obj = Integer.valueOf(1000);
//문자열을 줄 경우
Integer obj = Integer.valueOf("1000");

 

이렇게 박싱된 포장 객체에서 다시 기본 타입의 값을 얻어내기 위해서(언박싱을 위해서)는 각 포장 클래스마다 가지고 있는 '기본 타입 이름 + Value()' 메소드를 호출하면 된다.

▶ 자동박싱과 언박싱

기본 타입 값을 직접 박싱, 언박싱하지 않아도 자동으로 박싱과 언박싱이 일어나는 경우가 있다.

자동 박싱은 포장 클래스 타입에 기본값이 대입될 경우에 발생한다.

//example
Integer obj = 100; //자동 박싱

자동 언박싱은 기본 타입에 포장 객체가 대입되는 경우와 연산에서 발생한다.

//example
Integer obj = new Integer(200);
int value1 = obj; //자동 언박싱
int value2 = obj + 100; //자동 언박싱

▶ 문자열을 기본 타입 값으로 변환

포장 클래스의 주요 용도는 기본 타입의 값을 박싱해서 포장 객체로 만드는 것이지만, 문자열을 기본 타입 값으로 변환할 대에도 많이 사용한다.

대부분의 포장 클래스에는 'parse+기본 타입 이름'으로 되어 있는 정적(static) 메소드가 있다.

이 정적 메소드는 문자열을 매개값으로 받아 기본 타입 값으로 변환한다.

포장 값 비교

포장 객체는 내부의 값을 비교하기 위해 ==와 != 연산자를 사용하지 않는 것이 좋다.

왜냐하면 이 연산자들은 내부의 값을 비교하는 것이 아니라 포장 객체의 참조를 비교하기 때문이다.

자바 언어 명세를 보면 타입별 규칙이 존재한다.

박싱된 값이 위와 같은 표에 나와 있는 범위의 값이라면 ==와 != 연산자로 바로 비교가 가능하지만 그 이외의 경우는 언박싱 후 비교해야한다.

따라서 직접 내부 값을 언박싱해서 비교하거나, equals()메소드로 내부 값을 비교하는 것이 좋다.

포장 클래스의 equals()메소드는 내부의 값을 비교하도록 재정의되어 있음을 참고하자.

public class ValueCompareExample {
	public static void main(String[] args) {
		System.out.println("[-128~127 초과값일 경우]");
		Integer obj1 = 300;
		Integer obj2 = 300;
		System.out.println("==결과: " + (obj1 == obj2));
		System.out.println("언박싱후 ==결과: " + (obj1.intValue() == obj2.intValue()));
		System.out.println("equals() 결과: " + obj1.equals(obj2));
		System.out.println();
		
		System.out.println("[-128~127 범위값일 경우]");
		Integer obj3 = 10;
		Integer obj4 = 10;
		System.out.println("==결과: " + (obj3 == obj4));
		System.out.println("언박싱후 ==결과: " + (obj3.intValue() == obj4.intValue()));
		System.out.println("equals() 결과: " + obj3.equals(obj4));
	}
}

결과 :

< Math 클래스 >

java.lang.Math 클래스는 수학 계산에 사용할 수 있는 메소드를 제공한다.

Math 클래스가 제공하는 메소드는 모두 정적(static) 메소드이므로 Math 클래스로 바로 사용이 가능하다.

다음은 Math 클래스가 제공하는 메소드를 설명한 표이다.

여기서 round() 메소드에 대해 조금더 살펴보자.

round() 메소드는 항상 소수점 첫째 자리에서 반올림해서 정수값을 리턴한다. 

만약 원하는 소수 자릿수에서 반올림된 값을 얻기 위해서는 반올림할 자릿수가 소수점 첫째자리가 되도록 10^n을 곱한 후 round()메소드의 리턴 값을 얻고 다시 곱한 값을 나눠주어야 한다.

 

다음 코드는 소수점 셋째 자릿수에서 반올림하는 코드이다.

public class MathExample {
	public static void main(String[] args) {
		double value = 12.3456;
		double temp1 = value * 100; //10^2 곱하기
		long temp2 = Math.round(temp1);
		double v1 = temp2 / 100.0; //10^2 나누기
		System.out.println("v1=" + v1);
	}
}

결과 : 

 

728x90
반응형
LIST

'프로그래밍언어 > Java' 카테고리의 다른 글

11-2 java.util 패키지  (0) 2022.03.03
11-1 java.lang 패키지(1)  (0) 2022.02.23
10-2 예외 처리  (0) 2021.12.27
10-1 예외 클래스  (0) 2021.12.27
09-2 익명 객체  (0) 2021.12.14