java.lang

Jaca·2021년 9월 5일
0

java.lang 패키지에는 가장 기본적인 패키지들을 포함하고 있다.
그렇기 때문에 java.lang 패키지는 import 없이도 사용할 수 있다.

java.lang의 유용한 패키지들을 알아보자.

Object 클래스

Object 클래스는 모든 클래스의 최고 조상이기 때문에 Object 클래스의 멤버들은 모든 클래스에서 바로 사용 가능하다.

Obeject.메서드설 명
protected Object clone()객체 자신의 복사본을 반환
public boolean equals(Object o)자신과 o가 같은 객체인지 알려줌
protected void finalize()객체가 소멸될 때 가비지 컬렉터에 의해 자동적으로 호출된다. 이 때 수행되어야하는 코드가 있을 때 오버라이딩 한다.(거의 사용 안함)
public Class getClass()객체 자신의 Class 인스턴스를 반환한다.
public int hashCode()객체 자신의 해시코드를 반환한다.
public String toString()객체 자신의 정보를 문자열로 반환한다.
public void notify()객체 자신을 사용하려고 기다리는 쓰레드를 하나만 깨운다.
public void notifyAll()객체 자신을 사용하려고 기다리는 모든 쓰레드를 깨운다.
public void wait()
public void wait(long timeout)
public void wait(long timeout, int nanos)
다른 쓰레드가 notify()나 notifyAll()을 호출할 때까지 현재 쓰레드를 무한히 또는 지정된 시간동안 기다리게 한다.

Object 클래스는 멤버변수는 없고, 11개의 메서드만 가지고 있다.
이 중 중요한 몇가지만 살펴볼 것이다.

equals(Object obj)

매개변수로 객체의 참조변수를 받아서 비교하여 그 결과를 boolean 값으로 알려준다.
두 객체의 같고 다름을 참조변수의 값으로 판단한다.

String, Data, File, wrapper(Integer, Double) 클래스의 equals 메서드는 주소값을 비교하는 것이 아닌, 내용을 비교하도록 오버라이딩 되어 있다.

hashCode()

일반적으로 해시코드가 같은 두 객체가 존재하는 것이 가능하지만,
Object 클래스에 정의된 hashCode 메서드는 객체의 주소값으로 해시코드를 만들어 반환하기 때문에,
32 bit JVM에서는 다른 두 객체가 같은 해시코드를 가질 수 없지만,
64 bit JVM에서는 8byte 주소값으로 해시코드를 만들기 때문에 중복될 수 있다.

클래스의 인스턴스 변수 값으로 객체의 같고 다름을 판단하려면, equals와 hashCode를 적절히 오버라이딩 하는게 좋다.
같은 객체라면 두 해시코드도 같아야 하기 때문이다.

String 클래스는 문자열의 내용이 같으면, 동일한 해시코드를 반환하도록 오버라이딩 되어있다.
그래서 문자열의 내용이 같은 str1과 str2에 대해 hashCode()는 같은 값을 반환한다.
이럴 경우 System.idenitityHashCode(Object x)를 사용하면 원하는 결과를 얻을 수 있다.

toString()

인스턴스에 대한 정보를 문자열로 제공하기 위해 정의한 메서드이다.
Object 클래스에 정의된 toString()는 아래와 같다.

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

즉, 클래스의 이름과 16진수의 해시코드를 출력한다.

하지만 String 클래스와 Date 클래스의 toString()은 각각,
인스턴스가 가지고 있는 문자열과 날짜와 시간을 문자열로 반환하도록 오버라이딩 되어있다.

clone()

이 메서드는 자신을 복제하여 새로운 인스턴스를 생성하는 일을 한다.
Object 클래스의 clone()은 단순히 변수의 값만 복사하기 때문에, 참조타입의 인스턴스 변수가 있는 클래스는 완전한 인스턴스 복제가 일어나지 않는다.

얕은 복사와 깊은 복사
clone()은 단순히 객체에 저장된 값을 그대로 복제할 뿐,
객체가 참조하고 있는 객체까지 복제하지 않는다.

객체 배열을 clone() 으로 복제하는 경우에는 원본과 복제본이 같은 객체를 공유하므로 완전한 복제라고 보기 어렵다.
이것을 '얕은 복사'라고 한다. '얕은 복사'는 원본을 변경하면 복사본도 영향을 받는다.
반면에 원본이 참조하고 있는 객체까지 복제하는 것을 '깊은 복사'라고 한다. 깊은 복사는 원본의 변경이 복사본에 영향을 미치지 않는다.

getClass()

이 메서드는 자신이 속한 클래스의 Class 객체를 반환한다.
Class 객체는 클래스의 모든 정보를 담고 있으며, 클래스 당 1개 가지고 있다.
클래스 파일은 클래스 로더에 의해 메모리에 올라갈 때, 자동으로 생성된다.

String 클래스

변경 불가능한(immutable) 클래스
String 클래스에는 문자열을 저장하기 위해 문자형 배열 참조변수(char[]) value를 인스턴스 변수로 정의하고 있다.

한번 생성된 String 인스턴스가 갖고 있는 문자열은 읽어 올 수만 있고, 변경할 수는 없다.

예를 들어 String을 + 연산으로 문자열을 결합 한다면, 인스턴스가 변경되는 것이 아닌 새로운 인스턴스를 생성하는 것이다.

  • 연산을 통해 문자열을 결합하는 것은 매 연산 시 마다 새로운 문자열을 가진 String 인스턴스를 생성해 메모리를 차지하므로 연산을 줄이는 것이 좋다.
    문자열간의 결합이나 추출 등 문자열을 다루는 작업이 많다면 StringBuffer 클래스를 사용하는 것이 좋다.

문자열의 비교

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

String str1 = "abc"; // 문자열 리터럴 "abc"의 주소가 str1에 저장
String str2 = "abc"; // 문자열 리터럴 "abc"의 주소가 str2에 저장
String str3 = new String("abc"); // 새로운 String 인스턴스 생성
String str4 = new String("abc"); // 새로운 String 인스턴스 생성
str1 == str2; // true
str3 == str4; // false

생성자를 이용한 경우에는 new 연산자에 의해 메모리 할당이 이루어지기 때문에 매번 새로운 String 인스턴스가 생성되지만, 문자열 리터럴은 이미 존재하는 것을 재사용 한다.

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

생성자 or 메서드설명
String(char[] value)주어진 문자열을 갖는 String인스턴스 생성
String(StringBuffer buf)StringBuffer 인스턴스가 갖고 있는 문자열과 같은 내용의 String 인스턴스 생성
char charAt(int index)지정된 위치에 있는 문자를 알려줌
int compareTo(String str)문자열과 사전순서로 비교, 같으면 0, 사전순으로 이전이면 음수, 이후면 양수
String concat(String str)문자열을 뒤에 덧붙임
boolean contains(CharSequence s)지정된 문자열이 포함되었는지 검사
boolean endsWith(String suffix)지정된 문자열로 끝나는지 검사
boolean equals(Object obj)매개변수로 받은 문자열과 String 인스턴스를 비교함
boolean equalsIgnoreCase(String str)문자열과 String 인스턴스를 대소문자 구분 없이 비교
int indexOf(int ch)주어진 문자가 문자열에 존재하는지 확인하여, 있으면 위치를 없으면 -1를 반환
int indexOf(int ch, int pos)주어진 문자가 문자열에 존재하는지 지정된 위치를 확인하여 위치를 알려줌, 못찾으면 -1 반환
int indexOf(String str)주어진 문자열이 존재하는지 확인하여 그 위치를 알려줌, 없으면 -1 반환
String intern()문자열을 상수풀에 등록한다. 이미 상수풀에 같은 내용이 있을 경우 문자열의 주소값을 반환
int lastIndexOf(String str)지정된 문자열을 인스턴스의 문자열 끝에서부터 찾아 위치 반환
String replace(char old, char nw)문자열 중 old를 new로 바꾼 문자열을 반환
String replace(CharSequence old, CharSequence nw)문자열 중 old를 new 바꾼 문자열을 반환
String replaceAll(String regex, String replacement)지정된 문자열과 일치하는 것을 모두 새로운 문자열로 변경
String replaceFirst(String regex, String replacement)문자열 중 지정된 문자열과 일치하는 것 중, 첫번째 문자열만 새로운 문자열로 변경
String[] split(String regex)문자열을 지정된 분리자로 나누어 문자열 배열에 담아 반환
String[] split(String regex, int limit)문자열을 지정된 분리자로 나누어 문자열 배열에 담아 반환, 문자열 전체를 지정된 수로 자른다.
boolean startsWith(String prefix)주어진 문자열로 시작하는지 검사
String substring(int begin)
String substring(int begin, int end)
주어진 시작위치부터 끝 위치 범위에 포함된 문자열을 얻는다.

StringBuffer 와 StringBuilder

String 클래스는 인스턴스를 생성할 때 지정된 문자열을 변경할 수 없지만 StringBuffer 클래스는 변경이 가능하다.
내부적으로 문자열 편집을 위한 버퍼를 가지고 있으며, StringBuffer 인스턴스를 생성할 때 크기를 지정할 수 있다.
편집할 문자열이 버퍼의 크기를 넘어서면, 버퍼의 크기를 늘려주는 작업이 필요하므로 버퍼의 크기 설정시 유의해야한다.

StringBuffer는 멀티쓰레드에 안전하도록 동기화 되어 있다.
동기화는 StringBuffer의 성능을 떨어뜨린다.
그래서 멀티쓰레드 프로그램이 아닐 경우 StringBuffer는 동기화로 인해 불필요한 성능 저하를 가진다.
이를 위해 쓰레드의 동기화를 제거한 StringBuilder를 만들었다.

StringBuffer와 StringBuilder의 메서드나, 사용법은 동일하다.

래퍼(wrapper) 클래스

때로는 기본형 변수도 어쩔 수 없이 객체로 다뤄야 하는 경우가 있다.
이 때를 위해 8개의 기본형을 대표하는 8개의 래퍼클래스가 있다.

래퍼 클래스의 생성자는 매개변수로 각 자료형의 값을 인자로 받는다.

기본형래퍼클래스생성자
booleanBooleanBoolean(boolean value)
Boolean(String s)
charCharacterCharacter(char value)
byteByteByte(byte value)
Byte(String s)
shortShortShort(short value)
Short(String s)
intIntegerInteger(int value)
Integer(String s)
longLongLong(long value)
Long(String s)
floatFloatFloat(float value)
Float(String s)
doubleDoubleDouble(double value)
Double(String s)

위 표를 보면 알 듯이 기본형 변수 말고도 String을 매개변수로도 인스턴스를 생성할 수 있다.
그 때 각 자료형에 알맞는 문자열을 사용해야한다.
예를 들어 new Integer("1.0"); 과 같이 하면 NumberFormatException이 발생한다.

래퍼 클래스들은 모두 equals()가 오버라이딩 되어 있어서 주소값이 아닌 실제 값을 비교한다.

오토박싱 & 언박싱

JDK 1.5 이전에는 기본형과 참조형 간의 연산이 불가능해서, 래퍼 클래스로 기본형을 객체로 만들어서 연산해야 했다.

JDK 1.5 이후 컴파일러가 자동으로 변환하는 코드를 넣어줘서, 기본형과 참조형 간의 연산이 가능하다.

이 외에도 내부적으로 객체 배열을 가지고 있는 Vector 클래스나 ArrayList 클래스에 기본형 값을 저장해야할 때나 형변환이 필요할 때도 컴파일러가 자동적으로 코드를 추가해준다.
기본형 값을 래퍼 클래스로 자동 변환해주는 것을 오토박싱,
반대로 변환하는 것을 언박싱 이라고한다.

유용한 클래스

java.util.Objects

Object클래스의 보조 클래스로 모든 메서드가 static 이다.
객체의 비교나 널 체크에 유용하다.

Objects 클래스의 메서드만 간단히 보고 가자.

메서드설명
static boolean isNull(Object obj)obj가 null이면 true
static boolean nonNull(Object obj)obj가 null이 아니면 true
static <T> T requireNonNull(T obj)
static <T> T requireNonNull(T obj, String message)
static <T> T requireNonNull(T obj, Supplier messageSupplier)
해당 객체가 null이면,
NullPointerException 발생,
String은 예외의 메세지
static int compare(Object a, Object b, Comparator c)a와 b를 비교한다.
비교의 기준이 되는 c를 통해
같으면 0, 작으면 음수, 크면 양수
static boolean equals(Object a, Object b)Object의 equals()와 다른 점은
null 체크를 안해도됨
static boolean deepEquals(Object a, Object b)객체를 재귀적으로 비교
다차원 배열 비교 가능

특이한 점은 Objects 클래스를 static import 해도 Object 클래스의 메서드와 이름이 같으면 컴파일러가 구분하지 못해 충돌이 발생한다.
그럴 때는 Objects.메서드명() 처럼 이름을 붙여서 사용해야 한다.

java.util.Random

난수를 만드는 방법에 Math.Random() 외에도 Random 클래스가 있다.
사실 Math.Random()은 내부적으로 Random 클래스의 인스턴스를 생성해서 사용하므로 큰 차이가 없다.

Math.Random() 과 Random의 가장 큰 차이점은, 종자값(seed)를 설정할 수 있다는 것이다.
종자값이 같은 Random 인스턴스들은 항상 같은 난수를 같은 순서대로 반환한다.

생성자 Random() 은 종자값을 System.currentTimeMillis() // 현재 시간을 천분의 1초 단위로 변환해서 반환 로 하기 때문에 실행할 때 마다 얻는 난수가 달라진다.

같은 종자값을 갖는 Random 인스턴스는 시스템이나 실행시간 등에 관계 ㅇ벗이 항상 같은 값을 순서로 반환할 것을 보장하므로, 같은 시드라면 언제나 같은 순서로 난수가 발생한다.

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())

간단하게 알아보는 정규식 표현

profile
I am me

0개의 댓글