[자바] lang 패키지와 유용한 클래스

ChoRong0824·2023년 7월 2일
0

Java

목록 보기
25/31
post-thumbnail

23.07.01 스터디를 하였으나, 몸이 안좋은 관계로 공부를 못했습니다.
해당 챕터에 대해 필자의 부족함이 느껴져 별도로 시간을 가지고 학습하게되었습니다.
따라서, 자바의 정석 chapter 9 을 읽고, 필요한 내용만 내용 정리하여 포스팅하였습니다.

Object클래스

  • protected Object clone() : 객체 자신의 복사본을 반환합니다
  • public boolean equals (Object obj) : 객체 자신과 객체 obj가 같은 객체인지 알려줍니다. --> 같으면 true를 반환함
  • getClass() : 객체 자신의 클래스 정보를 담고 있는 Class 인스턴스를 반환합니다.
  • hashCode() : 객체 자신의 해시코드를 반환합니다.
  • toString() : 객체 자신의 정보를 문자열로 반환합니다.
  • notify() : 객체 자신을 사용하려고 기다리는 쓰레드를 하나만 깨웁니다.
  • notifyAll() : 객체 자신을 사용하려고 기다리는 모든 쓰레드를 깨웁니다.

hashCode()

  • 해싱기법에 사용되는 해시함수를 구현한 것입니다.
    해싱은 데이터관리기법 중 하나이며, 다량의 데이터를 저장하고 검색하는 데 유리합니다.
  • 해시함수는 찾고자하는 값을 입력하면, 그 값이 저장된 위치를 알려주는 해시코드를 반환합니다.
  • 해시코드는 중복될 수 있기 때문에(JVM에서는 8byte의 주소값으로 해시코드 4byte를 만들기 때문에 중복될 수 있습니다.
  • 따라서, 클래스의 인스턴스변수 값으로 객체의 같고 다름을 판단해야하는 경우라면 equals메서드 뿐 만 아니라, hashCode 메서드도 적절히 오버라이딩 해야합니다. --> 같은 객체라면, hashCode메서드를 호출했을 때의 결과값인 해시코드도 같아야 하기 떄문입니다.
  • indetityHashCode() 는 객체의 주소값으로 해시코드를 생성하기 때문에 모든 객체에 대해 항상 다른 해시코드 값을 반환할 것을 보장합니다. --> 객체가 같은지 확인하는 확실한 방법입니다.

toString()

  • 객체의 정보를 문자열로 변환하기 위한 메서드입니다.
    호출시, 16진수의 해시코들르 얻게 될 것입니다.
public static toString() {
    return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
  • 참고 : 서로 다른 객체에 대해서 toString()으로 호출한다면, 클래스의 이름은 같아도 해시코드값이 다르게 호출됩니다.
  • 오버라이딩해서 사용하면 내용도 당연히 바뀝니다. 여기까진 누구나 알 것입니다.
    여기서 중요한 것은 접근 제어자가 public 이어야 한다는 것입니다.
    --> toString()의 접근제어자가 public 이기 때문.

clone()

  • 자신을 복제하여 새로운 객체를 생성합니다.
  • 사용 하는 이유 : 어떤 객체에 대해 작업할 때, 원래의 객체는 보존하고 clone메서드를 이용해서 새로운 인스턴스를 생성하여 작업을 하면 작업이전의 값이 보존되므로 작업에 실패해서 원래의 상태로 되돌리거나 변경되기 전의 값을 참고하는데 도움이 되기때문에 사용합니다.
  • clone()는 인스턴스변수의 값만 복사하기 때문에 참조타입의 객체변수가 있는 클래스는 완전한 객체 복제가 이루어지진 않습니다.
    <예시>
    (배열의 경우) 복제된 객체도 같은 배열의 주소를 갖기 때문에 복제된 객체의 작업이 원래의 객체에 영향을 미치게 됩니다. 이때, clone메서드를 오버라이딩하여 새로운 배열을 생성하고, 배열의 내용을 복사해야합니다.
    <참고>
    cloneable 인터페이스를 구현한 클래스에서만 clone()를 호출할 수 있습니다.
    --> 인터페이스니까 다들 아시다시피 implements 인 거 아시죠!? 만약, 까먹으셨다면 챕터 7~8 포스팅 GO !
    또한, clone()를 오버라이딩하면서 접근제어자를 protected에서 public으로 변경해야합니다.
    --> 이유 : 상속관계가 없는 다른 클래스에서 clone()를 할 수 있기 때문입니다.

얕은복사 && 깊은복사

(개념 및 기본 내용)

깊은 복사(Deep Copy)는

객체의 모든 내용을 복사하여 새로운 객체를 생성하는 과정입니다. 깊은 복사를 할 때, 객체 내의 참조되는 객체까지 새롭게 생성되어 복사됩니다. 깊은 복사를 구현하는 3가지 방법은 다음과 같습니다

  1. 기본적인 방법은 재귀 함수를 사용하여 객체 내의 모든 참조 객체들을 복사하는 것입니다.
  2. 직렬화를 사용한 방법으로, 객체를 직렬화하여 새로운 객체로 변환하고 다시 역직렬화하여 깊은 복사를 수행할 수 있습니다.
  3. clone() 메서드를 사용하여 깊은 복사를 수행하는 방법입니다.

깊은복사의 3가지 방법의 예시

// 재귀함수
class DeepCopy {
    public static Node deepCopy(Node node) {
        if (node == null) {
            return null;
        }
        Node copied = new Node(node.data);
        copied.next = deepCopy(node.next);
        return copied;
    }
}
// 직렬화
class DeepCopy {
    public static Node deepCopy(Node node) {
        if (node == null) {
            return null;
        }
        Node copied = new Node(node.data);
        copied.next = deepCopy(node.next);
        return copied;
    }
}
// clone()
class DeepCopy implements Cloneable {
    private ListNode data;
    private DeepCopy next;
    
    public DeepCopy(ListNode data, DeepCopy next) {
        this.data = data;
        this.next = next;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        ListNode dataCopy = new ListNode(this.data.val); // 참조 객체복사
        DeepCopy nextCopy = this.next == null ? null : (DeepCopy) this.next.clone(); 

        DeepCopy cloned = new DeepCopy(dataCopy, nextCopy);
        return cloned;
    }
}

getClass()

  • 자신이 속한 클래스의 Class객체를 반환하는 메서드
  • Class객체는 클래스의 모든 정보를 담고 있으며, 클래스 당 1개만 존재하게됩니다.

String클래스

주요특징

  1. 불변성(Immutability): 생성된 String 객체의 값은 변경될 수 없습니다. 문자열에 변화가 필요한 경우, 새로운 String 객체가 생성되어 수정된 문자열을 반환합니다. 불변성으로 인해 성능에 영향을 줄 수 있지만, 멀티 스레드 환경에서 안전하게 사용할 수 있습니다.
  2. 문자열 리터럴 풀(String Literal Pool): 컴파일 타임에 결정되는 문자열 리터럴은 JVM의 특별한 영역인 상수 풀(Constant Pool)에 저장됩니다. 같은 문자열 리터럴을 사용하는 모든 String 객체는 공유되므로 메모리 효율성이 향상됩니다.
  3. 문자열 연결: 더하기 연산자(+)를 사용하여 String 객체들을 쉽게 결합할 수 있습니다. 그러나, 불변성 때문에 문자열을 많이 변경해야 하는 상황에서는 StringBuilder 또는 StringBuffer를 사용합니다.

문자열 리터럴

문자열 리터럴은 컴파일 시에 클래스 파일에 저장됩니다.
이때 같은 내용의 문자열 리터럴은 한번만 저장됩니다. 문자열 리터럴도 String 인스턴스이고, 한번 생성하면 내용을 변경할 수 없으니 하나의 인스턴스를 공유하면 되기 때문입니다.

빈 문자열

  • 길이가 0인 배열이 존재할 수 있을까? 라고 생각할 수 있지만 --> 존재합니다.
  • char형 배열도 길이가 0인 배열을 생성할 수 있고, 이 배열을 내부적으로 가지고 있는 문자열이 바로 빈 문자열입니다.
  • 참고로, c에서는 문자열의 끝에 널 문자가 항상 붙지만, 자바에서는 널 문자를 사용하지 않습니다. 대신 문자열의 길이정보를 따로 저장합니다.

String클래스의생성자와 메서드 중 자주 사용될만한 것들

  • char charAt(int index)
    문자열에서 해당 인덱스에 위치한 문자를 반환
    "Hello".charAt(1); // 'e'

  • int length()
    문자열의 길이(문자 개수)를 반환
    "Hello".length(); // 5

  • String substring(int beginIndex)
    인덱스 beginIndex부터 끝까지의 부분 문자열을 반환
    "Hello".substring(2); // "llo"

  • String substring(int beginIndex, int endIndex)
    인덱스 beginIndex부터 endIndex까지의 부분 문자열을 반환
    "Hello".substring(1, 4); // "ell"

  • String trim()
    문자열 시작과 끝의 공백을 제거한 새로운 문자열을 반환
    " Hello ".trim(); // "Hello"

  • String toLowerCase()
    모든 문자를 소문자로 변환한 새로운 문자열을 반환
    "HELLO".toLowerCase(); // "hello"

  • String toUpperCase()
    모든 문자를 대문자로 변환한 새로운 문자열을 반환
    "hello".toUpperCase(); // "HELLO"

  • boolean equals(Object anObject)
    문자열이 주어진 객체와 동일한지 비교하여 같으면 true, 다르면 false 반환
    "Hello".equals("hello"); // false

  • int indexOf(String str)
    주어진 문자열이 처음 발견되는 인덱스를 반환하고, 없으면 -1을 반환
    "Hello".indexOf("l"); // 2

  • String replace(CharSequence target, CharSequence replacement)
    문자열에서 target 문자열을 replacement 문자열로 모두 바꿔 새로운 문자열을 반환
    "Hello".replace("l", "x"); // "Hexxo"

  • String[] split(String regex)
    주어진 정규 표현식에 따라 문자열을 분할하여 문자열 배열로 반환
    "a,b,c".split(","); // ["a", "b", "c"]

  • boolean startsWith(String prefix)
    문자열이 주어진 접두사로 시작하면 true, 그렇지 않으면 false 반환
    "Hello".startsWith("He"); // true

  • boolean endsWith(String suffix)
    문자열이 주어진 접미사로 끝나면 true, 그렇지 않으면 false 반환
    "Hello".endsWith("lo"); // true

  • boolean contains(CharSequence sequence)
    문자열이 주어진 문자열을 포함하면 true, 그렇지 않으면 false 반환
    "Hello".contains("ell"); // true

  • int compareTo(String anotherString)
    두 문자열의 사전적 순서를 비교하여 정수 값을 반환. 현재 문자열이 주어진 문자열보다 사전적으로 빠르면 음수, 같으면 0, 느리면 양수를 반환
    "abc".compareTo("xyz"); // 음수값, "abc".compareTo("abc") == 0

  • int lastIndexOf(String str))
    주어진 문자열이 마지막으로 발견되는 인덱스를 반환하고, 없으면 -1을 반환
    "Hello, world! Hello".lastIndexOf("Hello"); // 14

  • String join(CharSequence delimiter, CharSequence... elements))
    주어진 구분자를 사용하여 주어진 문자열 요소를 연결한 문자열을 반환
    String.join("-", "A", "B", "C"); // "A-B-C"

  • String[] split(String regex, int limit)) 주어진 정규 표현식에 따라 문자열 분할하여 문자열 배열로 반환, 분할 제한이 있는 경우
    "a,b,c,d,e".split(",", 3); // ["a", "b", "c,d,e"]

    String.format()

    형식화된 문자열을 만들어내는 가장 간단한 방법입니다.

    문자열간 형변환

    참고 <-- 여기에 정리 다 되어있습니다.


    StringBuffer && StringBuilder

  • 스트링 버퍼(StringBuffer)란 가변적인 문자열을 표현하는 자바의 클래스로, 문자열을 추가, 수정, 삭제 등의 작업을 쉽게 수행할 수 있도록 도와줍니다. 문자열 연산이 많이 필요한 경우에는 일반적인 문자열 클래스인 String보다 효율적으로 처리할 수 있습니다. StringBuffer는 동기화(synchronized)되어 있어서 멀티스레드 환경에서 스레드 안전(thread-safe)하게 사용할 수 있는 특징이 있습니다.
    append(), insert(), delete(), reverse(), length()

  • 스트링 빌더(StringBuilder)는 마찬가지로 가변적인 문자열을 표현하는 자바의 클래스로, 일반적인 문자열 클래스 String과 마찬가지로 문자열 조작 작업을 효율적으로 처리하는 데 도움을 줍니다.
    그런데 이 클래스는 동기화되지 않아 스트링 버퍼에 비해 성능 상의 이점이 있습니다. 하지만 멀티스레드 환경에서는 스레드 안전하지 않을 수 있으므로 주의가 필요합니다.

스트링 버퍼와 스트링 빌더의 차이점

  1. 동기화(Synchronization): 가장 큰 차이점은 동기화에 있습니다. StringBuffer는 동기화되어 있어 멀티스레드 환경에서 안전하게(thread-safe) 사용할 수 있지만, StringBuilder는 동기화되지 않아 멀티스레드 환경에서 동시 변경 시 문제가 발생할 수 있습니다.
  2. 성능: 스트링 빌더는 동기화가 없기 때문에, 스트링 버퍼에 비해 성능이 더 좋습니다. 멀티스레드 환경이 아닌 경우에는 성능상의 이유로 스트링 빌더를 사용하는 것이 더 바람직합니다.
  3. 사용법: 두 클래스 모두 문자열 조작 작업에 비슷한 메소드를 제공하지만, 멀티스레드 환경에서의 안전성을 고려해 선택해야 합니다.

즉, 정리하면, 멀티스레드 환경에서는 스트링 버퍼를 사용하고, 그렇지 않은 경우에는 성능상의 이점으로 인해 스트링 빌더를 사용하는 것이 좋습니다.


래퍼 wrapper 클래스

기본 데이터 타입을 객체로 변환해주는 역할을 합니다.
기본 데이터 타입에는 byte, short, int, long, float, double, char, boolean이 있습니다.
이 데이터 타입들을 객체로 다루기 위해 각각에 대응하는 래퍼 클래스가 존재합니다.

기본형 클래스 --> 래퍼형 클래스 (아래 예시는 래퍼형)

  • byte--> Byte
  • short --> Short
  • int --> Integer
  • long --> Long
  • float --> Float
  • double --> Double
  • char --> Character
  • boolean --> Boolean

Number 클래스

  • 추상 클래스이며, 자바의 래퍼 클래스들이 상속받는 추상 클래스입니다.
    이 클래스는 수치 데이터를 처리하기 위한 메서드를 정의합니다.
    즉, 숫자와 관련된 래퍼클래스들은 모두 Number클래스의 자손이라는 것입니다.

래퍼 객체를 기본형으로 변경 하여 반환해주는 메서드들을 가지고 있습니다.

  1. doubleValue(): 현재 Number 객체의 값을 double 타입으로 반환합니다.
  2. floatValue(): 현재 Number 객체의 값을 float 타입으로 반환합니다.
  3. intValue(): 현재 Number 객체의 값을 int 타입으로 반환합니다.
  4. longValue(): 현재 Number 객체의 값을 long 타입으로 반환합니다.
  5. shortValue(): 현재 Number 객체의 값을 short 타입으로 반환합니다.
  6. byteValue(): 현재 Number 객체의 값을 byte 타입으로 반환합니다.
  • BigInteger long으로도 다룰 수 없는 큰범위의 정수

  • BigDecimal double로도 다룰 수 없는 큰범위의 실수

오토박싱 && 언박싱

자바 컴파일러가 자동으로 기본 타입과 그에 해당하는 래퍼 클래스간의 변환을 처리하는 과정이며, 이 기능은 자바 5부터 도입되었습니다.

  1. 오토박싱(auto-boxing): 기본 타입의 값을 해당하는 래퍼 클래스의 객체로 자동 변환하는 과정입니다. 이렇게 되면 기본 타입 값을 객체처럼 다룰 수 있습니다.
int myInt = 10;
Integer myInteger = myInt; // 오토박싱이 발생하여 int 타입이 Integer 객체로 변환됩니다.
  1. 오토언박싱(auto-unboxing): 래퍼 클래스의 객체를 해당하는 기본 타입 값으로 자동 변환하는 과정입니다.
Integer myInteger = new Integer(10);
int myInt = myInteger; // 오토언박싱이 발생하여 Integer 객체가 int 타입으로 변환됩니다.

이러한 오토박싱과 오토언박싱 덕분에 개발자가 명시적으로 타입 변환을 진행할 필요 없이 자연스럽게 코드를 작성할 수 있습니다.
하지만, 무분별한 오토박싱과 오토언박싱 사용은 성능 저하를 일으킬 수 있으므로 주의해야 합니다.
예를 들어, 빈번한 박싱과 언박싱이 발생하는 계산 과정에서는 기본 타입을 사용하는 것이 더 효율적일 수 있습니다.


정규식

문자열을 처리할 때 복잡한 패턴을 찾거나 대체하는데 사용되는 패턴 기반의 표현식입니다.
정규식을 사용하면 복잡한 문자열 처리 작업을 간단하게 처리할 수 있으며, 가독성도 향상됩니다.
자바에서 정규식을 사용하려면 java.util.regex 패키지의 Pattern 클래스Matcher 클래스를 사용합니다.

  1. Pattern 클래스: 주어진 정규식을 컴파일하고 패턴을 생성하는 클래스입니다. 패턴을 생성하는 방법은 주로 Pattern.compile() 정적 메서드를 사용합니다.
    Pattern pattern = Pattern.compile("[a-zA-Z0-9]+");
  2. Matcher 클래스: 주어진 문자열에 대해 생성된 패턴과의 일치 여부를 확인하고, 일치하는 부분을 찾거나 대체할 수 있는 클래스입니다. Matcher 객체는 Pattern 객체의 matcher() 메서드를 사용하여 생성합니다.
String inputString = "sample123text";
Matcher matcher = pattern.matcher(inputString);

Pattern과 Matcher 클래스를 사용하여 주요한 정규식 작업들을 수행할 수 있습니다.

  • find(): 입력 문자열에서 패턴과 일치하는 부분이 있는지 찾습니다.
  • matches(): 입력 문자열이 패턴과 완전히 일치하는지 확인합니다.
  • group(): 패턴과 일치하는 부분을 반환합니다.
  • replaceAll(), replaceFirst(): 일치하는 부분을 다른 문자열로 대체합니다.
String inputString = "123sample456text789";
Pattern pattern = Pattern.compile("\\d+"); // 숫자를 찾는 정규식
Matcher matcher = pattern.matcher(inputString);

while (matcher.find()) {
    System.out.println("Found a match: " + matcher.group());
}

String replacedString = matcher.replaceAll(""); // 숫자를 제거
System.out.println("Replaced string: " + replacedString);

위의 예시처럼, 자바의 정규식을 사용하면 문자열 처리 작업을 효과적으로 수행할 수 있습니다.
다양한 패턴을 사용하여 문자열 검색, 대체, 분할 등의 작업을 할 수 있으며, 코드 가독성도 좋아집니다.

profile
컴퓨터공학과에 재학중이며, 백엔드를 지향하고 있습니다. 많이 부족하지만 열심히 노력해서 실력을 갈고 닦겠습니다. 부족하고 틀린 부분이 있을 수도 있지만 이쁘게 봐주시면 감사하겠습니다. 틀린 부분은 댓글 남겨주시면 제가 따로 학습 및 자료를 찾아봐서 제 것으로 만들도록 하겠습니다. 귀중한 시간 방문해주셔서 감사합니다.

0개의 댓글