솜이의 데브로그

Chapter 09 ) java.lang 패키지와 그 외 클래스 본문

책을 읽자/Java의 정석

Chapter 09 ) java.lang 패키지와 그 외 클래스

somsoming 2021. 9. 11. 16:55

참고 : Java의 정석

 

1. java.lang 패키지

 

java.lang 패키지는 자바 프로그래밍에 가장 기본이 되는 클래스들을 포함하고 있다. 그러므로 java.lang 패키지의 클래스들은 import문 없이도 사용할 수 있다.

대표적으로 String, System 클래스들을 import문 없이 사용할 수 있었던 이유가 이것이다.

 

Object 클래스

Object 클래스는 멤버변수는 없고 오직 11개의 메서드만을 가지고 있다. 이 중 중요한 몇가지만 정리.

 

(1) equals (Object obj)

매개변수로 객체의 참조변수를 받아서 비교하여 그 결과를 boolean 값으로 알려준다.

즉, 두 객체의 같고 다름을 참조변수의 값으로 판단한다. 따라서 서로 다른 두 객체를 euqals 메서드로 비교하면 항상 false를 결과로 얻는다. (주소값으로 비교, 두 개의 참조변수가 같은 객체를 참조하고 있는지?)

 

value 값을 비교하기 위해서는 equals 메서드를 오버라이딩하여 주소가 아닌 객체에 저장된 내용으로 비교하도록 변경한다.

String 클래스 역시 Object클래스의 equals 메서드를 그대로사용하는 것이 아니라 오버라이딩을 통해 String 인스턴스가 갖는 문자열 값을 비교한다.

 

★ String 에서 equals 와 '==' 차이 꼭 알아두기!

 

 

(2) hashCode()

해시함수는 찾고자하는 값을 입력하면, 그 값이 저장된 위치를 알려주는 해시코드를 반환한다.

equals 메서드처럼, 클래스의 인스턴스변수 값으로 객체의 같고 다름을 판단하는 경우 hashCode 메서드도 적절히 오버라이딩해야한다.

  • String 클래스는 문자열의 내용이 같으면 해시코드를 반환하도록 오버라이딩 되어있음.
  • System.identityHashCode(Object x)는 객체의 주소값으로 해시코드를 생성함.

 

(3) toString()

인스턴스에 대한 정보를 문자열(String)로 제공한다.

Object클래스에 정의된 toString()은 다음과 같다.

 

public String toString(){
	return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

 

클래스를 작성할 때 toString()을 오버라이딩하지 않으면 클래스이름에 16진수의 해시코드를 얻게 된다.

ex) Card@19e0bfd

 

toString()은 일반적으로 인스턴스나 클래스에 대한 정보 또는 인스턴스 변수들의 값을 문자열로 변환하여 반환하도록 오버라이딩한다.

 

 

(4) clone()

자신을 복제하여 새로운 인스턴스를 생성하는 메서드이다.

원래의 인스턴스는 보존하고 clone 메서드를 이용해 새로운 인스턴스를 생성하여 값을 보존하고, 실패시 되돌리기에 용이하다.

 

※ 주의 : 단순히 인스턴스변수의 값만 복사하므로 참조타입의 인스턴스 변수가 있는 클래스는 완전한 복제가 이루어지지 않는다. (같은 객체를 가리킴)

 

class Point implements Cloneable{
	...
    public Object clone(){
    	Object obj = null;
        try{
        	obj = super.clone();
        } catch(CloneNotSupportedException e){}
        return obj;
    }
}

 

clone()을 사용하려면 먼저 복제할 클래스가 Cloneable 인터페이스를 구현하고, clone()을 오버라이딩해야한다.

오버라이딩 시 접근제어자를 protected 에서 public으로 변경해야하며, 예외처리를 반드시 해주어야한다.

 

  • 공변 반환 타입 : JDK1.5부터 허용된 것으로,조상 타입이 아닌 실제로 반환되는 자손 객체의 타입으로 반환 할 수 있는 것이다.
  • 얕은복사 : clone()은 단순히 객체에 저장된 값만을 그대로 복제할 뿐, 객체가 참조하고 있는 객체까지 복제하지는 않는다.
  • 깊은복사 : 원본이 참조하고 있는 객체까지 복제하는 것. 원본과 복사본이 서로 다른 객체를 참조한다.

 

getClass()

  • 자신이 속한 클래스의 Class 객체를 반환하는 메서드.
  • 클래스의 모든 정보를 담고있으며, 클래스 당 1개만 존재함.
  • 클래스 파일이 '클래스 로더'에 의해 메모리에 올라갈 때 자동으로 생성.

Class객체를 이용하면 클래스에 정의된 멤버의 이름이나 개수 등, 클래스에 대한 모든 정보를 얻을 수 있기 때문에 Class 객체를 통해서 객체를 생성하고 메서드 호출 등 동적인 코드를 작성할 수 있다.

 

ex)

Card c = new Card();
Card c = Card.class.newInstance();

 

String 클래스

문자열을 저장하고 이를 다루는데 필요한 메서드를 제공하는 클래스이다.

 

immutable 클래스 (변경 불가능한 클래스)

String클래스에서는 문자형 배열 참조변수를 인스턴스 변수로 정의한다.

한번 생성된 String 인스턴스가 갖고있는 문자열은 읽어올 수만 있고, 변경 할 수 없다. 따라서 + 연산자를 이용하여 문자열 결합하는 것은 새로운 문자열이 담긴 String 인스턴스를 생성하는 것이다. 그러므로 결합횟수를 줄이는 것이 좋다!

 

문자열간의 결합이나 추출 등 문자열을 다루는 작업이 많이 필요한 경우 String 클래스 대신 StringBuffer 클래스를 사용하는 것이 좋다. (StringBuffer인스턴스의 문자열은 변경 가능)

 

 

문자열의 비교

문자열을 만들 때는 문자열 리터럴을 저장하는 방법과 String 클래스의 생성자를 사용하는 방법이 있다.

String 클래스의 생성자를 이용한 경우에는 메모리 할당이 새로 이루어지기 때문에 새로운 String 인스턴스가 생성된다.

그러나 문자열 리터럴은 이미 존재하는 것을 재사용하는 것이다.

 

위에서 언급했던 ★ String 에서 equals 와 '==' 차이

equals()를 사용했을 때는 두 문자열의 '내용'을 비교한다. 등가비교연산자 '==' 는 String 인스턴스의 주소를 비교한다.

 

자바 소스파일에 포함된 모든 문자열 리터럴은 컴파일 시 클래스 파일에 저장된다. 이 때 같은 내용의 문자열 리터럴은 한번만 저장된다.

 

char형 배열의 길이가 0인 배열이 빈 문자열이다.

char[] chArr = new char[0];
int [] iArr = {};

String s = "";

 

그러나 char c = '';  와 같은 표현이 불가능하다. char 형 변수에는 반드시 하나의 문자를 지정해야 한다.

일반적으로 변수를 선언할 때, 각 타입의 기본값으로 초기화하지만 String 은 null 보다는 빈 문자열로(""), char형은 기본값인 \u0000 대신 공백 (' ')으로 초기화한다.

 

 

String클래스의 생성자와 메서드  (자주 사용되는 것 + 잘 기억나지 않는 것)

 

String(StringBuffer buf) StringBuffer 인스턴스가 갖고 있는 문자열과 같은 내용의 String 인스턴스 생성
int compareTo(String str) 문자열(str)과 사전 순서로 비교한다. 같으면 0, 사전순으로 이전이면 음수, 이후면 양수 반환
String concat(String str) 문자열(str)을 뒤에 덧붙인다.
boolean contains(CharSequence s) 지정된 문자열(s)이 포함되었는지 검사한다.)
boolean endsWith(String suffix) 지정된 문자열(suffix)로 끝나는지 검사한다. → 주로 파일검사에 많이 사용할듯
int indexOf(int ch, int pos) / int indexOf(String str) 주어진 문자 / 문자열이 존재하는 위치를 pos부터 확인하여 위치 반환. 찾지 못하면 -1 반환
String[] split(String regex, int limit) 문자열을 지정된 분리자(regex)로 나누어 문자열 배열에 담아 반환. 단, 문자열 전체를 지정된 수(limit)으로 자른다
String substring(int begin, int end) begin위치부터 end범위에 포함된 문자열을 얻는다. (begin <= x < end)
String trim() 문자열의 왼쪽 끝과 오른쪽 끝에 있는 공백을 없앤 결과를 반환한다.
static String valueOf(Object o) 지정된 값을 문자열로 변환하여 반환한다.

 

 

join() 과 StringJoiner

join()은 여러 문자열 사이에 구분자를 넣어서 결합한다.

 

StringJoiner sj = new StringJoiner(",", "[", "]");
String[] strArr = {"aaa", "bbb", "ccc");

for(String s : strArr)
	sj.add(s.toUpperCase());

System.out.println(sj.toString());

 

유니코드

String 클래스의 메서드 중에서 매개변수가 'int ch'인 것들은 보충문자를 지원하는 것이고, 'char ch'인 것들은 지원하지 않는 것들이다.

 

기본형 값을 String으로 변환

  • 숫자에 빈 문자열 "" 을 더한다.  ex) String str1 = 100 + "";
  • valueOf() 를 사용한다 (성능은 더 좋음)  ex) String str2 = String.valueof(100);

 

String을 기본형 값으로 변환

valueOf() 사용.  ex) int i = Integer.valueOf("100");

parseInt() 사용.  ex) int i2 = Integer.parseInt("100");

 

parseInt() 나  parseFloat() 같은 메서드는 문자열에 공백 또는 문자가 포함되어있는 경우 예외가 발생하므로 trim()을 같이 사용하면 좋다.

int val = Integer.parseInt(" 123 ".trim());

 

 

StringBuffer 클래스와 StringBuilder 클래스

  • String클래스는 인스턴스를 생성할 때 지정된 문자열을 변경할 수 없지만 StringBuffer 클래스는 변경이 가능하다.
  • 내부적으로 문자열 편집을 위한 버퍼를 가지고 있다.

 

StringBuffer의 생성자

인스턴스를 생성할 때 적절한 길이의 char형 배열이 생성되고, 이 배열은 문자열을 저장하고 편집하기 위한 공간으로 사용.

버퍼의 길이는 충분히 여유있는 크기로 지정하는 것이 좋으며, 지정하지 않으면 16개의 문자를 저장하는 크기로 생성한다.

 

  • StringBuffer클래스는 equals메서드를 오버라이딩하지 않아서 equals메서드를 사용해도 등가비교연산자(==)로 비교한것과 같은 결과를 얻는다.
  • toString()은 오버라이딩 되어있어서, StringBuffer 인스턴스에 toString()을 호출하면, 담고있는 문자열을 String으로 반환.
  • 따라서 문자열을 비교하기 위해서는 toString()을 호출한 후, 여기에 equals 메서드를 이용해서 비교해야한다.

 

StringBuffer클래스의 생성자와 메서드

String 클래스와 유사한 메서드를 많이 가지고 있으며, 추가,변경,삭제와 같이 저장된 내용을 변경할 수 있는 메서드들이 있다.

StringBuffer(int length) 지정된 개수의 문자를 담을 수 있는 버퍼를 가진 StringBuffer 인스턴스를 생성한다.
StringBuffer append(Object o) 매개변수로 입력된 값을 문자열로 변환하여 StringBuffer인스턴스가 저장하고 있는 문자열의 뒤에 덧붙인다.
int capacity() StringBuffer인스턴스의 버퍼크기를 반환.
length()는 버퍼에 담긴 문자열의 길이를 반환.
StringBuffer delete(int start, int end) 시작위치(start)부터 끝 위치(end) 사이에 있는 문자를 제거한다. 단, 끝 위치의 문자는 제외한다.
StringBuffer insert(int pos, Object obj) 두번째 매개변수로 받은 값을 문자열로 변환하여 지정된 위치에 추가.
StringBuffer reverse() StringBuffer 인스턴스에 저장되어 있는 문자열의 순서를 거꾸로 나열한다.
void setLength(int newLength) 지정된 길이로 문자열의 길이를 변경한다. 길이를 늘리는 경우 나머지 빈공간을 null로 채운다.

 

StringBuilder

멀티쓰레드에 안전하도록 동기화되어 있다. 따라서 StringBuffer에서 쓰레드의 동기화만 뺀 StringBuilder가 새로 추가되었다.

 

Math 클래스

 

  • Math클래스는 기본적인 수학계산에 유용한 메서드로 구성되어 있다.
  • 생성자의 접근제어자가 private 이기 때문에 다른 클래스에서 Math인스턴스를 생성할 수 없도록 되어있다.

 

올림, 버림, 반올림

  • round() : 소수점 첫째 자리에서 반올림한 값을 얻음. 정수값(long)을 결과로 돌려준다.
  • 따라서 원하는 자리수에서 반올림 된 값을 얻기 위해서는 10의 n제곱으로 곱한 후, 다시 곱한수로 나누어준다. 이 때 정수형으로 나누게 된다면 정수형간의 연산에서는 반올림이 이루어지지 않음에 주의하자.

 

삼각함수와 지수, 로그

수학 관련 메서드들은 Java API 를 참고하자.

대표적인 메서드들은 다음과 같다.

  • sqrt() : 제곱근 계산
  • pow() : n제곱 계산
  • sin() , cos() , tan()
  • toRadians() : 각도를 라디안으로 변환

 

Math 클래스의 메서드

static double abs(double a)
static int abs (int f)
...
절대값 반환
static double ceil(double a) 주어진 값을 올림하여 반환
static double floor(double a) 주어진 값을 버림하여 반환
static double max(double a, double b)
static int max(int a, int b)
...
더 큰 값 반환 (min은 더 작은값)
static double random() 0.0~1.0범위의 임의의 double값 반환
(1.0은 범위에 포함하지 않음)
static double rint(double a) 주어진 double값과 가장 가까운 정수값을 double형으로 반환. 단, 두 정수의 정가운데 있는 값 (1.5, 2.5 ...)은 짝수를 반환
static long round(double a)
static long round(float a)
소수점 첫째자리에서 반올림한 정수값(long)을 반환.
매개변수의 값이 음수인 경우, round()와 rint()의 차이 주의.

 

 

래퍼(wrapper) 클래스

  • 기본형 값을 객체로 다룰 수 있는 8개의 클래스들이다.
  • 래퍼클래스들은 모두 equals()가 오버라이딩되어 있어서 주소값이 아닌 객체가 가지고 있는 값들을 비교한다.
  • 이 외에도 MAX_VALUE, MIN_VALUE, SIZE, BYTES, TYPE 등의 static 상수를 공통적으로 가지고 있다.

 

Number 클래스

추상클래스로, 내부적으로 숫자를 멤버변수로 갖는 래퍼 클래스들의 조상이다.

ex : Byte, Short, Integer, Long, Float, Double 의 조상

 

 

문자열을 기본형 또는 래퍼클래스로 변환하는 방법은 위에서 언급한 바와 같다.

 

문자열 -> 기본형 문자열 -> 래퍼클래스
byte b = Byte.parseByte("100");
short s = Short.parseShort("100");
int i = Integer.parseInt("100");
long l = Long.parseLong("100");
float f = Float.parseFloat("3.14");
double d= Double.parseDouble("3.14");
Byte b = Byte.valueOf("100");
Short s = Short.valueOf("100");
Integer i = Integer.valueOf("100");
Long l = Long.valueOf("100");
Float f = Float.valueOf("3.14");
Double d= Double.valueOf("3.14");

 

JDK1.5부터 오토박싱 기능이 도입되어 반환값이 기본형일 때와 래퍼클래스일때의 차이가 없다. 단, 성능은 valueOf()가 조금 더 느리다.

(오토박싱 : 기본형 값을 래퍼클래스의 객체로 자동변환 해주는 것, 반대는 언박싱)

 

 

2. 유용한 클래스

 

(1) java.util.Objects 클래스

  • 객체의 비교나 null 체크에 유용하다.
  • compare() : 두 비교대상이 같으면 0, 크면 양수, 작으면 음수를 반환한다.
  • isNull() , nonNull()

 

(2) java.util.Random 클래스

  • Math.random()과 Random의 가장 큰 차이점은 seed (종자값)을 설정할 수 있다는 것이다.
  • seed 값이 같은 Random 인스턴스들은 항상 같은 난수를 같은 순서대로 반환한다.
  • 데이터베이스에 데이터 넣을 때 유용

 

유용할만한 메서드들 ex)

// 배열 arr을 from과 to 범위의 값들로 채워서 반환
public static int[] fillRand(int[] arr, int from, int to){
	for(int i = 0; i<arr.length; i++)
    	arr[i] = getRand(from, to);
        
    return arr;
}

//배열 arr을 배열 data에 있는 값들로 채워서 반환
public static int[] fillRand(int[] arr, int[] data){
	for(int i =0; i< arr.length; i++)
    	arr[i] = data[getRand(0, data.length-1)];
        
    return arr;
}


//from과 to범위의 정수값을 반환. from과 to 모두 범위에 포함.
public static int getRand(int from, int to){
	return (int)(Math.random() * (Math.abs(to-from)+1)) + Math.min(from, to);
}

 

 

(3) 정규식 - java.util.regex 패키지

  • 텍스트 데이터 중에서 원하는 조건과 일치하는 문자열을 찾아내기 위해 사용하는 것.
  • 미리 정의된 기호와 문자를 이용해서 작성한 문자열
  • 많은 양의 텍스트 파일 중에서 원하는 데이터를 손쉽게 뽑아내거나 입력된 데이터가 형식에 맞는지 체크 가능.

 

정규식을 정의하고 데이터를 비교하는 과정

1. 정규식을 매개변수로 Pattern 클래스의 static 메서드인 Pattern compile(String regex)을 호출하여 Pattern 인스턴스를 얻는다.
Pattern p = Pattern.compile("c[a-z]*");

2. 정규식으로 비교할 대상을 매개변수로 Pattern 클래스의 Matcher matcher(CharSequence input)을 호출해서 Matcher인스턴스를 얻는다.
Matcher m = p.matcher(data[i]);

3. Matcher인스턴스에 boolean matches()를 호출해서 정규식에 부합하는지 확인한다.
if(m.matches())

 

자주쓰이는 정규식 표현 알아두기.

 

 

(4) java.util.Scanner 클래스

  • Scanner는 화면, 파일, 문자열과 같은 입력소스로부터 문자데이터를 읽어오는데 도움을 줄 목적으로 JDK1.5부터 추가되었다.
  • 다양한 입력소스로부터 데이터를 읽을 수 있다.
Scanner(String source)
Scanner(File source)
Scanner(InputStream source)
Scanner(Readable source)
Scanner(ReadableByteChannel source)
Scanner (Path source)

 

(5) java.util.StringTokenizer 클래스

  • StringTokenizer는 긴 문자열을 지정된 구분자(delimiter) 기준으로 토큰(token)이라는 여러개의 문자열로 잘라낸다.
  • String의 split(String regex) , 또는 Scanner의 useDelimiter(String pattern)과 유사
  • 구분자로 단 하나의 문자밖에 사용하지 못하므로 복잡한 형태의 구분자로 나눌 경우는 정규식을 사용하는 위의 메서드를 사용.

 

(6) java.math.BigInteger 클래스정수형으로 표현할 수 있는 값 중 아주 큰 수를 사용할때 사용. long타입보다 훨씬 큰 값을 다룰 수 있다.연산 메서드 및 비트 연산 메서드들이 제공된다.

 

(7) java.math.BigDecimal 클래스정수를 이용해 실수를 표현한다. 오차가 없는 2진 정수로 변환하여 실수 표현.정수를 저장하는데 BigInteger를 사용한다.