- Inline Variable: 변수 추출 없이 표현식을 직접 삽입하는 리팩토링
- 자바에서 모든 클래스의 최상위 부모 클래스는 항상 Object 클래스
- 부모가 없으면 묵시적으로 Object 클래스를 상속받는다.
- toString()은 Object 클래스의 메서드
-
모든 객체는 공통기능을 편리하게 제공(상속)받을 수 있다.
- 객체의 정보를 제공하는 toString()
- 객체의 같음을 비교하는 equals()
- 객체의 클래스 정보를 제공하는 getClass()
- 등등
- 부모는 자식을 담을 수 있다.
- Object는 모든 클래스의 부모 클래스이다. 따라서 모든 객체를 참조할 수 있다.
- instanceof는 변수 타입이 아니라 실제 객체의 타입을 확인한다.
- obj가 Object 타입으로 선언돼도, 안에 실제로 Dog 객체가 들어있으면 obj instanceof Dog는 true가 된다.
- instanceof는 true/false만 반환하며 타입 확인만 한다.
- 자바 16부터 instanceof에 패턴 매칭을 적용해 자동으로
-
Object는 모든 객체를 대상으로 다형적 참조를 할 수 있다.
-
Object를 통해 전달받은 객체를 호출하려면 각 객체에 맞는 다운캐스팅 과정이 필요하다.
-
Object가 모든 메서드를 알고 있는 것이 아니다.
-
toString 오버라이딩 : alt+insert로 하면 매우 편리함
- 코드 상에서 직접 new로 객체 생성
- 컴파일 시점에 의존성이 결정
- 코드 수정 없이는 의존성 교체 어려움
- 객체를 외부에서 주입 (생성자, setter, DI)
- 런타임 시점에 의존성 결정
- 코드 변경 없이 객체 교체 가능
- == 연산자를 사용해서 두 객체의 참조가 동일한 객체를 가리키고 있는지 확인
- equals() 메서드를 사용하여 두 객체가 논리적으로 동등한지 확인
- 동등성 비교가 항상 필요한 것은 아니다. 동등성 비교가 필요한 경우에만 equals()를 재정의하면 된다.
- 기본형: 하나의 값을 여러 변수에서 절대로 공유하지 않는다.
- 참조형: 하나의 객체를 참조값을 통해 여러 변수에서 공유할 수 있다.
- 자바는 항상 값을 복사해서 대입한다.
- 프로그래밍에서 어떤 계산이 주된 작업 외에 추가적인 부수 효과를 일으키는 것을 말함. (부정적인 의미)
- 여러 변수가 하나의 객체를 공유하는 것을 막을 방법은 없다.
- 기본형은 항상 값을 복사해서 대입하기 때문에 값이 절대로 공유되지 않는다.
- 하지만 참조형의 경우 같은 참조값을 복사해서 대입하기 때문에 여러 변수에서 얼마든지 같은 객체를 공유할 수 있다.
- 객체의 상태(객체 내부의 값, 필드, 멤버 변수)가 변하지 않는 객체
- 불변이라는 단순한 제약을 사용해서 사이드 이펙트라는 큰 문제를 막을 수 있다.
- 불변 객체는 값을 변경할 수 없다.
- 따라서 불변 객체의 값을 변경하고 싶다면 변경하고 싶은 값으로 새로운 불변 객체를 생성해야 한다.
- 이렇게 하면 기존 변수들이 참조하는 값에 영향을 주지 않는다.
-
불변 객체에서 값을 변경하는 경우 withYear()처럼 'with'로 시작하는 경우가 많다.
-
불변 객체의 메서드가 'with'로 이름 지어진 경우, 그 메서드가 지정된 수정사항을 포함하는 객체의 새 인스턴스를 반환한다는 사실을 뜻한다.
-
정리하자면 with는 관례처럼 사용되는데, 원본 객체의 상태가 그대로 유지됨을 강조하면서 변경사항을 새 복사본에 포함하는 과정을 표현.
-
모든 클래스를 불변으로 만드는 것은 아니다.
- String은 클래스다. int, boolean 같은 기본형이 아니라 참조형이다.
String str1 = "hello"; //기존
String str1 = new String("Hello"); //변경- 문자열은 매우 자주 사용된다.
- 그래서 편의상 쌍따옴표로 문자열을 감싸면 자바 언어에서 new String("hello")와 같이 변경된다.
- length(): 문자열 길이 반환
- charAt(int index): 특정 인덱스의 문자 반환
- substring(int beginIndex, int endIndex): 문자열의 부분 문자열 반환
- indexOf(String str): 특정 문자열이 시작되는 인덱스 반환
- toLowerCase(), toUpperCase(): 문자열을 소문자 또는 대문자로 반환
- trim(): 문자열 양 끝의 공백을 제거
- concat(String str): 문자열을 더함 (기존 문자열을 바꾸는 것이 아니라 새로운 변수를 지정해줘야함)
- String 클래스 비교할 때는 == 비교가 아니라 항상 equals() 비교를 해야한다.
String str3 = "hello"
String str4 = "hello"
str3 == str4 // true-
문자열 리터럴을 사용하는 경우 자바는 메모리 효율성과 성능 최적화를 위해 문자열 풀을 사용한다.
-
자바가 실행되는 시점에 클래스에 문자열 리터럴이 있으면 문자열 풀에 String 인스턴스를 미리 만들어둔다.
-
이때 같은 문자열이 있으면 만들지 않는다.
-
프로그래밍에서 풀은 공용 자원을 모아둔 곳을 뜻함.
-
참고로 문자열 풀은 힙 영역을 사용.
-
그래도 문자열 비교는 항상 equals()를 사용해서 동등성 비교를 해야 한다.
-
String은 불변 객체이다. 따라서 생성 이후에 절대로 내부의 문자열 값을 변경할 수 없다.
- length(): 문자열 길이 반환
- isEmpty(): 문자열이 비어있는지 확인 (길이가 0)
- isBlank(): 문자열이 비어있는지 확인 (길이가 0이거나 공백만 있는 경우)
- charAt(int index): 지정된 인덱스에 있는 문자를 반환
- equals(Object anObject): 두 문자열 동일한지 비교
- equalsIgnoreCase(String anotherString): 두 문자열을 대소문자 구분 없이 비교
- compareTo(String anotherString): 두 문자열을 사전 순으로 비교
- compareToIgnoreCase(String str): 두 문자열을 대소문자 구분 없이 사전적으로 비교
- startsWith(String prefix): 문자열이 특정 접두사로 시작하는지 확인
- endsWith(String suffix): 문자열이 특정 접미사로 끝나는지 확인
- contains(CharSequence s): 문자열이 특정 문자열을 포함하고 있는지 확인
- indexOf
- lastIndexOf
- substring(int beginIndex) / substring(int beginIndex, int endIndex)
- concat(String str)
- replace(CharSequence target, CharSequence replacement)
- replaceAll(String regex, String replacement)
- replaceFirst(String regex, String replacement)
- toLowerCase() / toUpperCase()
- trim()
- strip()
- split(String regex)
- join(CharSequence delimiter, CharSequence... elements)
-
valueOf(Object obj): 다양한 타입을 문자열로 변환
-
toCharArray(): 문자열을 문자 배열로 변환
-
format(String format, Object... args): 형식 문자열과 인자를 사용하여 새로운 문자열을 생성
-
matches(String regex): 문자열이 주어진 정규 표현식과 일치하는지 확인
-
불변인 String 클래스의 단점은 문자를 더하거나 변경할 때마다 계속해서 새로운 객체를 생성해야 한다는 점이다.
-
문자를 자주 더하거나 변경해야 하는 상황이라면 더 많은 String 객체를 만들고, GC해야 한다.
- String 클래스 단점 해결법. 가변 String이 존재하면 된다.
- StringBuilder는 append()로 문자열을 이어붙여도 동일한 StringBuilder 객체 내부에서만 작업한다.
- String은 불변이라 이어붙일 때마다 새로운 String 객체가 만들어진다.
- 그래서 StringBuilder가 반복적인 문자열 조작에 더 효율적이다.
- toString 메소드를 사용해 StringBuilder의 결과를 기반으로 String을 생성할 수 있다.
- StringBuilder는 보통 문자열을 변경하는 동안만 사용하다가 문자열 변경이 끝나면 안전한(불변) String으로 변환하는 것이 좋다.
- 반복문에서 반복해서 문자를 연결할 때
- 조건문을 통해 동적으로 문자열을 조합할 때
- 복잡한 문자열의 특정 부분을 변경해야 할 때
- 매우 긴 대용량 문자열을 다룰 때
- 메서드 호출 결과로 리턴된 객체에서 또 메서드를 호출하는 방식이다.
- 주로 같은 객체(this)를 리턴해 메서드를 연속 호출할 수 있도록 만든다.
- 코드가 간결해지고 가독성이 좋아진다.
StringBuilder sb = new StringBuilder();
sb.append("Hello")
.append(" ")
.append("World!")
.reverse();
System.out.println(sb.toString());- append()는 StringBuilder 객체를 리턴하기 때문에 연속 호출 가능하다.
- 한 객체에서 여러 메서드를 연속 호출해 작업을 수행한다.
- 메서드가 return this 형태로 객체 자기 자신을 반환해야 가능하다.
- Setter 메서드나 빌더 패턴에서 자주 사용된다.
- 코드가 간결하고 직관적이다.
- 여러 메서드를 연속 호출해 한 번에 여러 작업을 처리할 수 있다.
- 디버깅이 어려울 수 있다.
- 너무 길어지면 가독성이 떨어질 수 있다.
Person person = new PersonBuilder()
.setName("Alice")
.setAge(25)
.build();- 객체가 아님: 객체는 유용한 메서드를 제공할 수 있는데 기본형은 객체가 아니므로 메서드 제공 X
- null 값을 가질 수 없음: 기본형 데이터 타입은 null 값을 가질 수 없다. 때로는 데이터가 없음 이라는 상태를 나타내야 할 필요가 있는데, 기본형은 항상 값을 가지기 때문에 이런 표현을 할 수 없다.
- 기본형을 객체로 감싸서 더 편리하게 사용하도록 도와줌.
| 기본형 | 래퍼 클래스 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
- 불변
- equals로 비교해야 한다.
- new Integer(10)은 직접 사용 X, 작동은 하지만 향후 자바에서 제거될 예정.
- 대신에 Integer.valueOf(10)
- 래퍼 클래스에 들어있는 기본형 값을 다시 꺼내는 메서드.
- 래퍼클래스는 객체이기 때문에 == 비교를 하면 인스턴스의 참조값을 비교한다.
- 래퍼 클래스는 내부의 값을 비교하도록 equals()를 재정의 해두었다. 따라서 값을 비교하려면 equals()를 사용.
- toString()도 재정의했다.
- 자바 오토 언박싱, 박싱 지원: 컴파일러가 개발자 대신 valueOf, xxxValue() 등의 코드 추가해주는 기능.
- valueOf(): 래퍼 타입을 반환. 숫자, 문자열을 모두 지원한다.
- parseInt(): 문자열을 기본형으로 변환.
- compareTo(): 내 값과 인수로 넘어온 값을 비교. 내 값이 크면 1, 같으면 0, 내 값이 작으면 -1을 반환.
- 타입 정보 얻기
- 리플렉션
- 동적 로딩과 생성
- 애노테이션 처리
- class는 자바의 예약어이다. 따라서 패키지명, 변수명으로 사용할 수 없다.
- 이런 이유로 자바 개발자들은 class 대신 clazz라는 이름을 관행으로 사용.
- getDeclaredFields(): 클래스의 모든 필드를 조회.
- getDeclaredMethods(): 클래스의 모든 메서드를 조회.
- getSuperclass(): 클래스의 부모 클래스를 조회.
- getInterfaces(): 클래스의 인터페이스들을 조회.
- 상수들을 사용하여 코드 내에서 미리 정의된 값들의 집합
- 열거형도 클래스이다.
- 열거형은 toString()을 재정의 하기 때문에 참조값을 직접 확인할 수 없다.
- 타입 안정성 향상
- 간결성 및 일관성
- 확장성
- values(): 모든 ENUM 상수를 포함하는 배열을 반환한다
- valueOf(String name): 주어진 이름과 일치하는 ENUM 상수를 반환한다.
- name(): ENUM 상수의 이름을 문자열로 반환한다.
- ordinal(): ENUM 상수의 선언 순서(0부터 시작)를 반환한다.
- toString(): ENUM 상수의 이름을 문자열로 반환한다. name() 메서드와 유사하지만, toString()은 직접 오버라이드 할 수 있다.
-
ordinal()은 가급적 사용하지 않는 것이 좋다.
- 이 값을 사용하다가 중간에 상수를 선언하는 위치가 변경되면 전체 상수의 위치가 모두 변경될 수 있기 때문이다.
- 열거형은 java.lang.Enum을 자동으로 상속 받는다.
- 열거형은 이미 java.lang.Enum을 상속 받았기 때문에 추가로 다른 클래스를 상속을 받을 수 없다.
- 열거형은 인터페이스를 구현할 수 있다.
- 열거형에 추상 메서드를 선언하고, 구현할 수 있다.
- 열거형은 상수로 지정하는 것 외에 일반적인 방법으로 생성이 불가능하다. 따라서 생성자에 접근제어자를 선언할 수 없게 막혀있다. private이라고 생각하면 된다.