모든 클래스의 상위 클래스
상속이 명시 X
-> extends java.lang.Object 가 추가(컴파일러)
Object 클래스에 정의된 메서드
-> 모든 클래스가 사용가능(다형성)
참고) 자바문서_Object
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html
// Object클래스에 정의된 toString()의 기본구현내용
public String toString(){
return getClass().getName() + "@" + Integer.toHexString(hasgCode());
}
getClass().getName() : 클래스명(패키지명을 포함한 전체 클래스명)
ex) exam06.Book@3b07d329
클래스명.class, 참조변수.getCalss() Integer.toHexString(hashCode()) : 객체의 주소값을 16진수로 변환한 문자열
ex) exam06.Book@3b07d329
참조 변수를 출력 -> 참조변수.toString() // 컴파일러가 자동추가
-> 참조변수.toString() : object에 있는 toString()메서드를 호출
ex) exam06.Book@3b07d329
기본 object에 있는 내용(클래스명 + @ + 객체주소값)이 아니면 모두 재정의 되었다고 보면 됨(오버라이드)
ex) 데이터클래스 -> 변수의 값확인
ex) LocalDate클래스 -> 2024-04-23(날짜출력)
예시)

ㄴ Book extends java.lang.Object // 안보이지만 컴파일러가 자동추가
ㄴ object에 있는 toString()메서드를 컴파일러가 자동 호출
ㄴ 참조 변수를 출력 -> 참조변수.toString()
// Object클래스에 정의된 equals()의 기본구현내용 : '=='(동일성 비교, 주소비교)
public boolean equals(Object obj) {
return (this == obj);
}
동일성 비교 (주소비교) : ==
동등성 비교 (다른 객체, 다른주소여도 값이 동등하면 됨) : equals and hashCode 메서드의 재정의
ex) String 클래스
// String 클래스에 정의된 equals()
// Object클래스에 정의된 equals()의 기본구현내용과 다름 -> 동등성 비교로 재정의되어있다
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
return (anObject instanceof String aString)
&& (!COMPACT_STRINGS || this.coder == aString.coder)
&& StringLatin1.equals(value, aString.value);
}
// String 클래스에 정의된 hashCode()
// 논리적으로 동일한 문자열이면 객체가 뭐든지 간에 동일한 hashCode() 값이 나온다
public int hashCode() {
// The hash or hashIsZero fields are subject to a benign data race,
// making it crucial to ensure that any observable result of the
// calculation in this method stays correct under any possible read of
// these fields. Necessary restrictions to allow this to be correct
// without explicit memory fences or similar concurrency primitives is
// that we can ever only write to one of these two fields for a given
// String instance, and that the computation is idempotent and derived
// from immutable state
int h = hash;
if (h == 0 && !hashIsZero) {
h = isLatin1() ? StringLatin1.hashCode(value)
: StringUTF16.hashCode(value);
if (h == 0) {
hashIsZero = true;
} else {
hash = h;
}
}
return h;
}
equals() 는 주로 재정의하여 동등성비교할 때 많이 씀
equals() and hashCode() : 재정의를 염두해둔 메서드동등성 비교의 기준
-> equals() and hashCode()
-> equals() 가 true이면서 hashCode() 값이 동일한가
-> ① 중복제거 예시 참조
참고) String 클래스
- 문자열 비교
==쓰면❌ -> equals 사용⭕ 해야함- 문자열도 하나의 객체이다
참고) 자바스크립트
===: 동일성
==: 동등성
예시)

ㄴ b1 == b2: false
-> == : 동일성 비교
ㄴ b1.equals(b2): false
-> Object클래스에 정의된 equals()의 기본구현내용도 == (동일성 비교, 주소비교)
예시) String

ㄴ str1 == str2 : false
-> == : 동일성 비교
ㄴ str1.equals(str2): true
-> 음? Object클래스에 정의된 equals()의 기본구현내용은 == 라서 동일성 비교(주소비교)이고 str1과 str2의 주소는 다른데 왜 true이지?
-> equals() 가 동등성 비교(가치비교)로 재정의 되었구나
equals())를 통해 중복제거예시1) Stirng 클래스

ㄴ 중복되는 집합이 제거됨
-> Stirng 클래스 : 객체가 뭐든지 간에 문자열이 같으면 hashCode() 값도 동일
예시1-1) Stirng 클래스의 객체 간 hashCode() 값 비교

ㄴ Stirng 클래스 : 객체가 달라도 문자열이 같으면 같은 hashCode()값이 출력됨
예시2) Book클래스

ㄴ 생성자함수 통해 멤버변수 초기화함
ㄴ equals(), toString() 메서드 재정의함

ㄴ 중복되는 집합이 있음

ㄴ 어? 중복제거가 안됨 왜??
-> equals() 뿐만이 아니라 hashCode() 값도 같아야 동등한지 판단이 되고 동등한지 판단이 된 다음에야 중복제거가 됨
-> Book클래스는 아직 hashCode() 재정의 시행하지 않음
-> 미완성 동등성 비교

ㄴ 왜 generate에 동등성 비교가 equals() and hashCode() 일까?
-> 동등성비교가 equals() 뿐만이 아니라 hashCode() 값도 같아야 한다는말
-> 동등성 비교의 기준 : equals() and hashCode()

ㄴ equals()는 이미 재정의되어 있으니 hashCode() 재정의 마저 추가해줘서 동등성비교 완료하자
ㄴ hash : 같은 값에 대해서 같은 정수 값을 생성
public int hashCode() {
return Objects.hash(isbn, title, author);
}

ㄴ 오 이제 중복제거 됨
객체를 찾기위한 값(검색)
객체의 주소 값을 이용해서 해싱(hashing) 기법을 통해 해시 코드를 만든 후 반환
기본값은 유일한 값으로 쓰기 위한 객체의 주소값(System.identifyHashCode(..))
엄밀히 말하면 해시코드는 주소값은 아니고, 주소값으로 만든 고유한 숫자값
객체의 지문
-> 왜? 검색할 때 객체를 찾기위한 값이 중복 되면 찾기 힘드니까
필요에 따라 재정의 하는경우도 있음
-> equals와 함께 동등성 비교를 위한 재정의
-> 두 메소드를 같이 재정의 하지 않을시, hash 값을 사용하는 Collection Framework(HashSet, HashMap, HashTable)을 사용할 때 문제가 발생
-> SET : 중복❌는 컬렉션 프레입웤인데도 불구하고 equals만 재정의한 경우 같은 문자열이어도 2개다 add 됨 -> 중복된 요소가 추가된다
hash : 같은 값에 대해서 같은 정수 값을 생성
-> java.util.Objects에 정의된 메서드


ㄴ "ABC" : 힙영역 - 문자열 상수 풀, 문자열 상수, 객체형태의 상수
-> 리터럴 상수와 동일한 목적
-> 객체를 매번 만드는게 아니라 "ABC" 1개만 만든다
-> 자원을 효율적을 활용

ㄴ 객체를 여러개 만드므로 "ABC"가 여러개 존재
String 클래스 안에 정의된 문자열 객체
jdk11 버전 : final char[]
↓ 명칭바뀜
최근: final byte[]
// String 클래스 안에 정의된 final byte[]
private final byte[] value;
final : 문자열은 불변하는 특징
-> 한번문자열을 설정하면 절대 byte공간크기변경❌, 값 변경❌
-> 이러한 불변성 특징 때문에 문자열 추가 혹은 가감 시 기존 문자열객체는 버리고 새로운 객체 생성을 통해 값 변경
매번 문자열 추가 -> 새로운 객체가 만들어진다 -> 성능저하
-> 성능저하 개선방법 : StringBuffer
예시)

ㄴ 문자열은 불변하는 특징이 있기 때문에 값 변경❌
-> 문자열 가감하거나 더할려면 기존데이터를 버리고 새로운 객체를 생성해야 함
ㄴ 기존 문자열 주소값 참조 끊고(GC가 제거) 새로운 객체 주소참조로 변경

ㄴ "ABC" 문자열에 "DEF" 문자열을 더할 경우 불변하는 문자열 특징 상 새로운 객체("ABCDEF")를 생성하고 기존 "ABC", "DEF"에 대한 주소참조는 끊음(참조가 끊겼으니 GC가 제거)
StringBuffer() : 매개변수가 없으면 16바이트참고) 자바문서_StringBuffer
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/StringBuffer.html
예시) StringBuffer

ㄴ StringBuffer sb = new StringBuffer(100); : 100바이트 임시메모리 버퍼공간을 설정함
ㄴ append : 문자열을 버퍼에 추가할 때 쓰는 메서드
ㄴ toString() : 버퍼에 있는 문자열 데이터를 꺼내서 문자열로 반환해주는 역할

ㄴ 버퍼공간이 충분하다면 동일한 버퍼에 모두 담겨 주소가 모두 동일하다 (만약 버퍼공간 대비 담아야 할 데이터가 많다면 새로운 버퍼생성 -> 주소값 다름)
-> 새로운 객체 생성 매번 안하니 성능이 좋다ㅏ
ㄴ 버퍼에서 문자열을 꺼낼 때는 주소가 바뀜
ㄴ ABCDEFGHI : 문자열도 결합이 잘 되어 있군


ㄴ CharSequence가 매개변수인 경우 StringBuffer(CharSequence seq)에 들어갈 수 있는 자료형은 다형성에 따라 CharSequence의 implementing classes들(하위클래스들)이 들어갈 수 있다 -> 유연성
toString()
문자열로 되어 있는 버퍼에 있는 데이터를 꺼내서 문자열로 반환해주는 역할
insert()
지정된 위치에 문자열을 삽입
ex) stringBuffer.insert(5, ","); : 5번째 위치에 , 삽입
delete()
지정된 범위의 문자열을 삭제
replace()
지정된 범위의 문자열을 새로운 문자열로 대체
reverse()
문자열 뒤집기
append()
문자열을 버퍼에 추가할 때 쓰는 메서드, 문자열 뒤에 추가


return this; : 현재 객체의 주소값을 반환 -> 자료형 : 현제 객체 그 자체반환값이 객체 그 자체이면 메서드가 연결된 상태로 계속 작업을 연달아 이어나가는 것을 의도하고 만든 기능
반환값이 본인자료형 그 차체
: 객체 그 자체를 반환 -> 연달아 작업하는 것을 의도 : 메서드 체이닝
반환값이 this
: 객체 그 차제를 반환 -> 메서드 체이닝 기법 의도
예시)

ㄴ append의 반환값 : this = 객체 그 자체
ㄴ sb 와 sb2는 동일한 객체

ㄴ sb 와 sb2 와 sb3은 동일한 객체
ㄴ 어짜피 다 동일한 객체인데 한번에 쓰는게 좋지 않을까? -> 메서드 체이닝

ㄴ 메서드 체이닝 : 반환값이 객체 그 자체이면 메서드가 연결된 상태로 계속 작업을 연달아 이어나가는 것

ㄴ 메서드체이닝해도 동일하게 결과값 출력
기본 자료형을 객체로 래핑(wrapping)하여 제공하는 클래스
기본 자료형을 위한 클래스
기본 자료형의 값 -> 기능x, 객체x
기본자료형의 값을 처리하는 편의 기능 클래스
기본형에 기능을 부여하기 위해 해당 클래스가 존재하고 값은 감싸는 형태로 되어있다
class Integer {
...
private final int value;
...
}
참고) 자바문서_Integer
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html
참고) valueof(int) : 같은기능이니까 객체 1개만 만들고 공유하기
ㄴ 자바 9버전부터는new Integer를 통해 객체 생성하지 말고valueOf(int)(반환값 : static Integer) 를 통해 객체를 생성해라
ㄴ 왜? 10이라는 기능은 항상 같은데new Integer를 사용하면 10이라는 객체가 여러개 생김 = 자원낭비
-> 10이라는 객체 한번만 생성하고 다 같이 공유하자 =valueOf(int)(반환값 : static Integer) 사용하자
예시) doubleValue()

ㄴ Integer num1 = new Integer(10); : 기본형자료형을 Wrapper 클래스 구조의 Integer 자료형 객체로 만든 과정 -> deprecated for remove (자바 9버전부터 쓰지말라 미래 버전에 제거 될 가능성이 있다)
ㄴ double num2 = num1.doubleValue(); : 정수를 double자료형으로 변환
예시) parseInt(...)

ㄴ static int parseInt(...) : 문자열 숫자 -> int형 숫자 변환
ㄴ 반환값 타입이 static이라 객체 생성 안하고 바로 사용 가능
예시) new Integer -> valueof를 써야 하는 이유

ㄴ Wrapper 클래스 객체 2개 생성 -> 서로 다른 객체니까 주소값이 다름
ㄴ Wrapper 클래스 : 정수에 기능을 주는것
ㄴ 10이라는 기능은 똑같은데 번거롭게 객체가 2개 생성되었넹 -> 불필요한 자원낭비
-> 매번 객체를 새로 만들필요가 없다 like 문자열 상수(String), 리터럴 상수
-> 그래서 valueof를 써라 : 매번 만들어도 동일한 객체 : 반환값 static Integer
예시) valueof

ㄴ valueof를 써라 : 매번 만들어도 동일한 객체 : : 반환값 static Integer

ㄴ 근데 항상 동일한 객체 한개만 만드는 건 아니고 byte범위내에서 객체 한개만들고 공유
ㄴ byte범위 넘어가면 객체가 한개 더 생성된다
예시) java.lang.Number : 모든 수 관련 객체의 상위클래스(다형성)

ㄴ 10.0, 10L : 다양한 자료형
-> Number로 자료형 통일(다형성)
-> Number추상클래스에 정의된 추상메서드 doubleValue()를 통해 10.0, 10L를 double기본자료형으로 통일하고 연산수행

ㄴ 출력
연산(+, -, *, / ...)
객체는 연산이 안됨
언박싱 : 객체⭕ -> 객체❌(기본자료형)으로 형변환, 객체안에 있는 값(기본자료형)을 꺼내기
-> intValue : 객체를 내부적으로 연산이 가능한 기본자료형으로 형변환해줌(언박싱)
오토박싱 : 객체❌ -> 객체⭕로 형변환
-> valueof : 객체x -> 객체ㅇ로 형변환 (오토박싱)
예시) 자동형변환

ㄴ int -> double
예시1) 언박싱 : int + Integer // intValue : Integer(객체ㅇ) -> int(객체x)

ㄴ int num1 = 100; : 기본 자료형
ㄴ Integer num2 = Integer.valueOf(200); : 객체

ㄴ 음? 기본자료형 + 객체인데 왜 연산이 되지? 객체는 연산이 안되는데
ㄴ 컴파일러가 내부적으로 안보이지만 형변환해줌
-> 안보이지만 컴파일러가 num2.intvalue(); 추가 해 줌
-> intValue : Integer(객체ㅇ) -> int(객체x) : 기본자료형

예시2) 언박싱 : Integer + Integer

ㄴ Integer + Integer = 객체 + 객체 인데 어떻게 연산이 되냥

ㄴ 안보이지만 컴파일러가 자동으로 intValue()호출해줌 : 언박싱
예시3) 오토박싱 : 기본형자료형을 객체형태의 자료형에 대입하기 // valueof : int(객체x) -> Integer(객체ㅇ)

ㄴ 음? 서로 자료형이 다른데 이게 왜 돼지?
ㄴ Integer(참조자료형 : 객체형태의 자료형)
ㄴ 100, 200 (기본자료형 : 객체x형태의 자료형)

ㄴ 컴파일러가 Integer.valueof 자동 추가
ㄴ Integer.valueof : 객체x -> 객체ㅇ로 형변환
ㄴ 오토박싱 : 객체x -> 객체ㅇ로 형변환

ㄴ 기본형은 메서드가 없음
ㄴ 값은 메서드가 있을 수가 없음 왜? 객체가 아니니까
ㄴ num1은 메서드가 보임 왜? 객체니까~ Integer객체임

ㄴ Integer는 객체이다

ㄴ 언박싱 -> 오토박싱
ㄴ 연산하기 위해 언박싱(기본자료형으로 형변환, 객체x) 한 다음 연산 다 한 뒤 Integer자료형(참조자료형, 객체ㅇ)에 맞게 오토박싱
참고) 자바문서_Class Class
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html
예시) 정적 변수 class : 클래스명.class

ㄴ Person 클래스 정의

ㄴ 모든 클래스에는 안보이지만 class라는 정적변수가 자동으로 생성되어 있음

ㄴ 이제 클래스클래스 객체를 가져 올 수 있음
예시) getClass()

ㄴ 클래스클래스 객체를 가져 올 수 있음
1) : 모든클래스의 전역변수로 쓰임
2) : Object형이 된 getClass()는 객체를 만들어야지만 가능, 객체 자원의 일부로서 인스턴스메서드 형태로 클래스클래스 객체를 가져오는게 가능함
-> 클래스 내부에서 사용 할 목적
-> 어짜피 1)을 통해 객체를 안만들어도 클래스클래스 객체 접근 가능한데 굳이 이걸 쓰는 이유는 클래스 내부에서 사용 할 목적이라는 뜻
참고) 자바문서_Class Class
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html
예시) getFields(), getMethods(), getConstructors()

ㄴ Person클래스 정의

ㄴ 애매할때는 ALT+ENTER해서 import할꺼 지정해줘야 함

ㄴ cls1.getFields() : Person클래스의 변수정보 확인
ㄴ cls1.getMethods() : Person클래스의 함수정보 확인
ㄴ cls1.getConstructors() : Person클래스의 생성자함수정보 확인

ㄴ toString이 용도에 맞게 다들 재정의 되어 있음

ㄴ 출력결과
실행 과정 중에 클래스를 메모리(데이터 영역)에 올린다
= 실행과정중에 원격에서 보내져온 클래스클래스를 Class.forName()이 메모리(데이터 영역)에 올린다
내가 작업을 할려고 카톡에서 파일을 다운받고 문서를 열어서 작업을 함
= 클래스로더가 클래스클래스파일을 메모리에 올린다
-> 작업 중간에 누가 추가 작업물을 카톡으로 보내줌
-> 그럼 작업중간(실행과정 중)에 카톡으로 온 추가작업물을 다운받고 문서를 열어서(메모리에 올린다) 추가작업 시행해야함
-> 이거랑 같은 말이다ㅏㅏ
패키지명을 포함한 클래스이름을 문자열 형태로 매개변수에 넣으면 정보를 확인해 볼 수 있는 클래스클래스 객체를 반환

Class.forName() : 런타임이 포함되어 있지 않은 클래스 -> 무조건 예외처리를 해줘야 함

ㄴ Class.forName() : 예외전가되어 있음
예시) Class.forName()
지금은 할 필요 없지만 예시로 보여주기 위해 시행

ㄴ 예외처리 안해서 예외처리하라고 에러 뜸

ㄴ 예외전가시킴
ㄴ 동적로딩 : exam03.Person 클래스파일이 메모리(데이터영역)에 올라가고 접근가능하게 바뀔 것 임

ㄴ 클래스명 잘 못 입력하면 이렇게 에러 뜸