23.07.01 스터디를 하였으나, 몸이 안좋은 관계로 공부를 못했습니다.
해당 챕터에 대해 필자의 부족함이 느껴져 별도로 시간을 가지고 학습하게되었습니다.
따라서, 자바의 정석 chapter 9 을 읽고, 필요한 내용만 내용 정리하여 포스팅하였습니다.
protected
Object clone() : 객체 자신의 복사본을 반환합니다indetityHashCode()
는 객체의 주소값으로 해시코드를 생성하기 때문에 모든 객체에 대해 항상 다른 해시코드 값을 반환할 것을 보장합니다. --> 객체가 같은지 확인하는 확실한 방법입니다.public static toString() {
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
cloneable
인터페이스를 구현한 클래스에서만 clone()를 호출할 수 있습니다.protected
에서 public
으로 변경해야합니다.객체의 모든 내용을 복사하여 새로운 객체를 생성하는 과정입니다. 깊은 복사를 할 때, 객체 내의 참조되는 객체까지 새롭게 생성되어 복사됩니다. 깊은 복사를 구현하는 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;
}
}
문자열 리터럴은 컴파일 시에 클래스 파일에 저장됩니다.
이때 같은 내용의 문자열 리터럴은 한번만 저장됩니다. 문자열 리터럴도 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"]
형식화된 문자열을 만들어내는 가장 간단한 방법입니다.
참고 <-- 여기에 정리 다 되어있습니다.
스트링 버퍼(StringBuffer)란 가변적인 문자열을 표현하는 자바의 클래스로, 문자열을 추가, 수정, 삭제 등의 작업을 쉽게 수행할 수 있도록 도와줍니다. 문자열 연산이 많이 필요한 경우에는 일반적인 문자열 클래스인 String보다 효율적으로 처리할 수 있습니다. StringBuffer는 동기화(synchronized)되어 있어서 멀티스레드 환경에서 스레드 안전(thread-safe)하게 사용할 수 있는 특징이 있습니다.
append(), insert(), delete(), reverse(), length()
스트링 빌더(StringBuilder)는 마찬가지로 가변적인 문자열을 표현하는 자바의 클래스로, 일반적인 문자열 클래스 String과 마찬가지로 문자열 조작 작업을 효율적으로 처리하는 데 도움을 줍니다.
그런데 이 클래스는 동기화되지 않아 스트링 버퍼에 비해 성능 상의 이점이 있습니다. 하지만 멀티스레드 환경에서는 스레드 안전하지 않을 수 있으므로 주의가 필요합니다.
즉, 정리하면, 멀티스레드 환경에서는 스트링 버퍼를 사용하고, 그렇지 않은 경우에는 성능상의 이점으로 인해 스트링 빌더를 사용하는 것이 좋습니다.
기본 데이터 타입을 객체로 변환해주는 역할을 합니다.
기본 데이터 타입에는 byte, short, int, long, float, double, char, boolean이 있습니다.
이 데이터 타입들을 객체로 다루기 위해 각각에 대응하는 래퍼 클래스가 존재합니다.
BigInteger long으로도 다룰 수 없는 큰범위의 정수
BigDecimal double로도 다룰 수 없는 큰범위의 실수
자바 컴파일러가 자동으로 기본 타입과 그에 해당하는 래퍼 클래스간의 변환을 처리하는 과정이며, 이 기능은 자바 5부터 도입되었습니다.
int myInt = 10;
Integer myInteger = myInt; // 오토박싱이 발생하여 int 타입이 Integer 객체로 변환됩니다.
Integer myInteger = new Integer(10);
int myInt = myInteger; // 오토언박싱이 발생하여 Integer 객체가 int 타입으로 변환됩니다.
이러한 오토박싱과 오토언박싱 덕분에 개발자가 명시적으로 타입 변환을 진행할 필요 없이 자연스럽게 코드를 작성할 수 있습니다.
하지만, 무분별한 오토박싱과 오토언박싱 사용은 성능 저하를 일으킬 수 있으므로 주의해야 합니다.
예를 들어, 빈번한 박싱과 언박싱이 발생하는 계산 과정에서는 기본 타입을 사용하는 것이 더 효율적일 수 있습니다.
문자열을 처리할 때 복잡한 패턴을 찾거나 대체하는데 사용되는 패턴 기반의 표현식입니다.
정규식을 사용하면 복잡한 문자열 처리 작업을 간단하게 처리할 수 있으며, 가독성도 향상됩니다.
자바에서 정규식을 사용하려면 java.util.regex 패키지의 Pattern 클래스와 Matcher 클래스를 사용합니다.
Pattern pattern = Pattern.compile("[a-zA-Z0-9]+");
String inputString = "sample123text";
Matcher matcher = pattern.matcher(inputString);
Pattern과 Matcher 클래스를 사용하여 주요한 정규식 작업들을 수행할 수 있습니다.
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);
위의 예시처럼, 자바의 정규식을 사용하면 문자열 처리 작업을 효과적으로 수행할 수 있습니다.
다양한 패턴을 사용하여 문자열 검색, 대체, 분할 등의 작업을 할 수 있으며, 코드 가독성도 좋아집니다.