language/java

9. java.lang 패키지와 유용한 클래스

wooweee 2023. 3. 11. 19:28
728x90
  • java.lang package & util class

Object 클래스

// 객체자신.ObjectClassMethod();

protected Object clone(); //객체자신의 복사본 반환

public boolean equals(Object obj); // 객체자신과 객체 obj가 동일한 객체인지 알려준다

public Class getClass(); // 객체자신의 클래스 정보를 담고있는 class instance를 반환 
// class Class명 으로 출력
// getClass().getName()으로 출력시 Class명 만 출력

public int hashCode(); // 객체자신 해시코드 반환

public String toString(); // 객체자신 정보를 문자열로 반환

protected void finalize(); // 객체 소멸시 gc에 의해 호출

public void notify(); // 쓰레드 하나만 깨운다

public void notifyAll(); // 모든 쓰레드 깨운다

//다른 쓰레드가 notify() || notifyAll() 호출할 때까지 현재 쓰레드를 무한 혹은 지정된 시간 동안 대기시킴
public void wait(); // 무한
public void Wait(long timeout); // 1000분의 1초 
public void wait(long timeout, int nanos); // 1000분의 1초, 나노초

 

1. equals()

  • 각각의 참조변수들과 연결된 객체의 주소를 비교한다.
public boolean equals(Object obj){
    return(this==obj);
}

 

  • overriding - 객체의 주소 말고 객체 내부의 값 비교
class Person{

    type 필드;
    @Override
    public boolean equals(Object obj){
        //return this==obj;
        if(obj instanceof Person){
            return this.필드 == (Person)obj.필드;
        }
        return false;
    }
}

 

2. hashcode()

 

  • 해시코드: 해싱 기법에 해시코드가 사용되고, 해시함수가 해시코드를 만들어낸다.
    1. 일반적인 해시코드가 동일한 두객체가 존재 가능

    2. Object class의 경우 참조변수와 연결된 객체의 주소를 이용하여 해시코드를 만들어 반환하기 때문에 서로 다른 두 객체는 절대로 같은 해시코드를 가질 수 없다.
      참조변수와 연결된 객체 주소로 해시코드를 만드는 것이여서 다른 참조변수와 동일한 객체와 연결하면 동일 해시코드가 나온다.
      하지만 equals()만 오버라이딩한 각각의 참조변수들은 다른 해시코드를 가진다.

    3. 자바규칙: equals()가 true인 두 객체의 hashcode()는 동일해야 한다. 그래서 equals()를 overriding 하면 hashcode()도 오버라이딩을 필수적으로 해야 한다.
  • 해싱: 데이터관리기법 중 하나로 데이터를 저장하고 검색하는 데 유용

 

해시코드, 해싱, 해시함수

더보기

해싱(hashing)은 데이터를 빠르게 검색하기 위한 기법 중 하나입니다.

해싱은 데이터를 저장하는 배열에 해시함수를 적용하여, 데이터의 키(key)를 해시코드(hash code)로 변환한 후, 이 해시코드를 인덱스로 사용하여 배열에 접근합니다. 이때, 같은 해시코드를 가진 데이터가 여러 개일 수 있으므로, 각 데이터는 배열 내에서 연결리스트나 트리 등의 자료구조로 저장됩니다.

해시함수(hash function)는 데이터의 키를 입력으로 받아, 고정된 크기의 해시코드를 출력하는 함수입니다.

해시함수는 입력값이 같으면 항상 같은 출력값을 반환해야 하며, 다른 입력값에 대해서는 최대한 고르게 분포된 출력값을 반환해야 합니다. 이는 해시함수가 충돌(collision)을 최소화하기 위해서입니다. 충돌은 서로 다른 입력값에 대해 같은 해시코드를 반환할 때 발생합니다.

해시코드(hash code)는 해시함수를 적용한 결과물로, 고유한 값으로 데이터를 식별하는 역할을 합니다.

해시코드는 일반적으로 정수형 값을 사용하며, 자바에서는 Object 클래스의 hashCode() 메서드를 통해 객체의 해시코드를 구할 수 있습니다. 자바에서는 해싱을 이용한 자료구조로 HashMap, HashSet, Hashtable 등이 제공됩니다. 이러한 자료구조들은 데이터를 빠르게 검색하고, 삽입/삭제 연산을 빠르게 수행할 있습니다.

 

  • 해시코드 오버리이딩
    • Objects: 객체와 관련된 메서드를 제공하는 유틸 크래스
@Override
public int hasCode(){
    return Objects.hash(args); // args = 해당 class field 값 다 넣기
    
    //hash는 가변인자 이므로 hash의 params에 해당 class field를 다 넣으면 된다
}

 

  • equals, hashcode overriding 예제
import java.util.Objects;

public class Try {
    public static void main(String[] args) {
        Abc a = new Abc();
        a.x = 1;
        Abc b = new Abc();
        b.x = 1;

        System.out.println("a.equals(b) = " + a.equals(b));
        System.out.println("a.hashCode() = " + a.hashCode()); // overriding 이후 hashcode
        System.out.println("b.hashCode() = " + b.hashCode()); // overriding 이후 hashcode
        System.out.println("System.identityHashCode(a) = " + System.identityHashCode(a)); // 최초 hashcode
        System.out.println("System.identityHashCode(b) = " + System.identityHashCode(b)); // 최초 hashcode
    }
}

class Abc {
    int x;

    @Override
    public boolean equals(Object abc) {
        if (abc instanceof Abc) {
            Abc abc1 = (Abc) abc;
            return this.x == abc1.x;
        }
        return false;
    }
    @Override
    public int hashCode() {
        return Objects.hash(x); // 해당 class field값ㅇ르 매개변수로 넣어야함
    }
}

 

3. toString()

  • 인스턴스에 대한 정보를 문자열로 제공한다.
public String toString(){
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
// toHexString() 16진수로 변경하는 method

 

  • 오버라이딩
@Override
public String toString(){
    return "적고 싶은 것" + 필드명;
}

 

4. clone()

 

5. getClass()

 

Objects

  • Object class의 보조클래스로 모든 메서드가 static이다.
  • 객체 비교와 null check에 유용하다.
  • 메서드
isNull() // 해당 객체가 널인지 확인 후 null이면 true 반환, 아니면 false 반환
nonNull() // isNull()과 반대 역할

requireNonNull(해당객체, String str) 
// 해당 객체가 null이 아니어야 하는 경우에 사용 , null이면 NullPointException 발생 시킴
// str: 예외메시지 작성칸, 필수는 아니다.

compare(Object a, Object b, Comparator t) // 객체의 크기 비교

equals(a,b) // null 검사를 하지 않아도 되는 장점을 가짐
deepEquals(a,b) // 2차원 비교 가능

hashCode(가변인자) // 가변인자로 들어온 class의 필드값을 가지고 해시코드를 만들어서 반환

 

String 클래스

  1. 문자열 저장
  2. 이를 다루는 메서드 제공
  3. 변경불가능한 클래스
    • 새로운 문자열을 가지 String 객체가 생성되고 참조변수가 해당 객체와 연결된다.
      • 문제점: 항상 새로운 string 객체가 생성되기에 메모리 공간을 많이 차지
      • 해결책: StringBuffer class를 사용
String a = "a"; // 0x100
String b = "b"; // 0x200
a = a+b; // a는 0x100과의 연결을 끊고 0x300와 연결된다.

 

1. 문자열 비교

  • 2가지 방식
    1. 얕은 복사
    2. 깊은 복사
// 문자열 리터럴인 abc 주소가 공유됨 -> 얕은 복사 -> Immutable이기 때문에 read만 가능
String str1 = "abc";
String str2 = "abc";

// 각각 새로운 String 인스턴스를 생성 -> 깊은 복사 -> read, write 가능
string str3 = new String("abc");
string str4 = new String("abc");

 

  • 문자열 리터럴
    • 프로그램 실행 시, 자동으로 생성되는 리터럴로 constant pool에 저장된다.
    • 문자열 리터럴도 String의 인스턴스이다.

 

 

2. 빈 문자열 - 빈 문자    vs    null - 'u\0000'

String s = null;
char c = 'u\0000'; // char의 null 표현

String s = ""; -> 내부적으로 new char[0]인 배열을 저장한 것과 동일
char c = ' ';

 

  •  차이점
      •  참조하는 것이 null이냐 아니냐의 차이

      • null: 아무것도 없는 것을 표현하기 위한 그냥 표지판 같은 것으로 참조변수의 입장에서 참조된 것이 없다 == 초기화가 안되었다는 뜻

      • 빈문자, 빈문자열:  비어있다는 것을 나타내는 것을 표현한 실제 존재하는 값으로 참조변수의 입장에서 참조된 것이 있다. == 초기화된 값
      • 헷갈리는 이유: 둘 다 출력 시 아무것도 출력이 안되기 때문. 하지만 근본적인 시작이 다르다.

 

3. String의 생성자와 메서드

생성자 및 메서드설명

  • CharSequence : 문자열과 관련된 String, StringBuilder, StringBuffer만 params로 받고 싶은데 공통되는 조상이 없어서 해당 인터페이스를 가지도록 함

  • params중 int ch와 char ch가 존재하는 이유
    • 확장된 유니코드를 다루기 위해서
    • 원래는 char의 2byte인 16bit로 문자를 다루기로 했는데 한자등등 수많은 문자가 존재해서 16bit로는 처리가 힘들어졌다. 그래서 20bit로 확장을 결정
    • 실제 int type을 사용하는 것이 아니라 char, char를 2개를 사용하는 형식을 채택 -> char + char = int가 되기 때문에 int type을 받는다고 나타나게 된 것
// 생성자
String(String s)
String(char[] value)
String(StringBuffer buf)

// 메서드
char charAt(int index) // 지정된 인덱스의 문자 반환

int compareTo(String str) // 문자열 사전 순서 비교 -1, 0, 1

String concat(String str) // 문자열을 뒤에 덧붙인다.

boolean contains(CharSequence s) // 지정된 문자열이 포함되는지 검사

boolean startsWith(String prefix) // 지정된 문자열로 시작하는지 검사
boolean endsWith(String suffix) // 지정된 문자열로 끝나는지 검사

boolean equals(Object obj) // String 인스턴스의 문자열을 비교 * obj가 string이 아니여도 false

boolean equalsIgnoreCase(String str) // 대소문자 구분 없이 반환

int indexOf(int ch) // 없으면 -1
int indexOf(int ch, int pos) // 주어진 위치에서 부턴 index 찾는다. 없으면 -1
int indexOf(String str) // str과 동일 문자열 index 반환, str의 첫 char index 반환

String intern() // 문자열 상수풀에 등록

int lastIndexOf(int ch) // 끝에서 부터 문자 찾고 해당 index 반환
int lastIndexOf(String str)

int length()

String replace(char old, char, nw) // 모든 old 문자를 nw로 변경
String replace(CharSequence old, CharSequence nw) // 모든 old 문자열을 nw로 변경
String replaceAll(String regex, String replacement) // 모든 old 문자열을 nw로 변경
String replaceFirst(String regex, String replacement) // 처음 old 문자열을 nw로 변경

String[] split(String regex) // regex에 맞춰서 자름
String[] split(String regex, int limit) // 첫번째만 자름

String substring(int begin) // begin index부터 끝까지 문자열 잘라서 반환
String substring(int begin, int end) // begin index부터 end index까지 문자열을 잘라서 반환

String toLowerCase() // 소문자로 변환
String toUpperCase() // 대문자로 반환

String toString()

String trim() // 양쪽 끝 공백 없앰

String valueOf(all type) // 지정된 값을 문자열로 반환

 

4. join(), StringJoiner

  • 문자열 사이에 구분자를 넣어서 결합
String[] arr = {abc, abc, abc};

// join()
String str = String.join("-", arr);
System.out.println(str); // abc-abc-abc

// StringJoiner
StringJoiner sj = new StringJoiner("-" , "[[" , "]]");
for(String s : strArr)
    sj.add(s);
System.out.println(str); // [[abc-abc-abc]]

 

5. 문자열과 기본형 간의 변환

// 기본형 -> 문자열
// 1) 가시성 좋다
String str1 = 기본형_변수명 + "";
// 2) 성능면 좋다
String str2 = String.valueOf(기본형_변수명);

// 문자열 -> 기본형
// 1)
기본형 변수명 = WrapperClass.parseWrapperClass(문자열);
ex) int i = Integer.parseInt("100");

// 2)
Wrapper 변수명 = WrapperClass.valueOf(문자열); // 오토박싱을 통해 기본형으로 자동 형변환된다.
ex) Integet i = Integer.valueOf("100");

 

StringBuffer 클래스

  • 지정된 문자열이 변경이 가능하다.
  • 내부적으로 문자열 편집을 위한 버퍼를 가지고 있다.

 

  • 생성자
public StringBuffer(int length) {
    value = new char[length];
    shared = false;
}

public Stringbuffer(){
    this(16); // 버퍼 크기 지정 안하면 default로 16 길이로 저장
}
public Stringbuffer(String str){
    this(str.length()+16); // String 길이 + 16 길이로 저장
    append(str);
}

 

  • 공간 부족시 해결 방안
    1. 새로운 길이 배열 생성
    2. 배열 value 내용을 새 배열에 복사
    3. 참조변수와 새 배열 연결
char newValue[] = new char[newCapacity]; // newCapacity는 새로운 정수 값

System.arraycopy(value, 0, newValue, 0, count);

value = newValue;

 

  • StringBuffer 변경
    아래 메서드 이용
    1. append(); // 추가
    2. delete(); // 삭제
    3. insert(); // 중간 삽입

 

  • StringBuffer 비교
    • equals가 오버라이딩 되지 않았다.
    • toString은 오버라이딩이 되어 String 값을 String으로 반환한다.


1. StringBuffer 메서드

StringBuffer()
StringBuffer(int length)
StringBuffer(String str)

StringBuffer append(java type) // 매개변수를 string으로 변환 후, StringBuffer가 저장하고 있는 문자열 뒤에 추가
StringBuffer insert(int pos, java type) // 해당 pos에 String으로 변환된 type 추가
StringBuffer delete(int start, int end) // 지정 범위 문자들을 제거, end는 포함 안됨
StringBuffer deleteCharAt(int index) // 지정된 위치의 문자 제거
StringBuffer replace(int start, int end, String str) // 지정 범위 문자들을 str로 변경, end는 포함 안됨

int capacity() // 버퍼크기
int length() // 문자열 길이

char charAt(int index)

StringBuffer reverse()

void setCharAt(int index, char ch) // 지정된 위치의 문자를 주언진 문자로 바꾼다.
void setLength(int newLength) // 지정된 길이로 문자열의 길이를 변경한다. 늘려진 길이의 빈 공간은 '\u0000'로 채움

String toString()

String substring(int start)
String substring(int start, int end)

 

2. StringBuilder

  • StringBuffer가 멀티스레드에 안전하도록 동기화되어서 멀 티쓰래드 프로그램이 아닌 경우 동기화가 불필요하다. 성능을 떨어뜨리기 때문
  • StringBuffer의 스레드의 동기화만 뺀 것이 StringBuilder이다. StringBuffer와 동일하다.

 

 

Math 클래스

// oveerflow 방지
int addExact(int x, int y) // x + y
int subtractExact(int x, int y) // x - y
int multiplyExact(int x, int y) // x * y
int incrementExact(int a) // a++
int decrementExact(int a) // a--
int negateExact(int a) // -a
int toIntExact(long value) // (int)value

 

static abs(a) // 절대값, double, float, int, long 반환

static ceil(a) // 올림, double 반환
static floor(a) // 내림, double 반환
static round(a) // 소수점 첫째자리 반올림 정수값 반환

static max(a, b) // a,b 중 큰 값 반환, double, float, int, long 반환
static min(a, b) // a,b 중 작은 값 반환, double, float, int, long 반환

static random() // 0.0 ~ 1.0 범위 double 반환, 1.0 포함 안됨

static rint(a) // a와 가까운 정수값 double 반환

wrapper 클래스

// 자료형 타입의 full name으로 첫 철자를 대문자로 작성하고 객체 생성하듯이 생성하면 된다.
Integer i = new Integer(100); // 자료형 매개변수
Integer i1 = new Integer("100"); // 문자열 매개변수
  • 기본형 값을 객체로 다룰 때 사용
    • 매개변수로 객체를 요구할 때
    • 기본형 값이 아닌 객체로 저장해야 할 때
    • 객체 간의 비교가 필요할 때
  • 생성자
    • 매개변수로 문자열 || 자료형의 값을 받는다.
    • 문자열을 넣을 때 각 자료형에 알맞은 문자열을 사용해야 한다.
  • 특징
    1. equals()가 overriding 되어있어서 주소값이 아닌 객체가 가지고 있는 값을 비교
    2. 비교 연산자 사용 불가, compareTo()가 대신 제공
    3. static 상수 제공: MAX_VALUE, MIN_VALUE, SIZE, BYTES, TYPE
  • 문자열 숫자로 변환
int i = new Integer("100").intValue(); //floatValue() logValue() ,,,

 

Number 클래스

  • 추상클래스이다
Object
├── Number
│   ├── BigDecimal // 아주 큰 실수
│   ├── BigInteger // 아주 큰 정수
│   ├── Integer
│   ├── Long
│   ├── Float
│   ├── Double
│   ├── Short
│   └── Byte
├── Character
└── Boolean

 

1. String->number / number -> String 메서드

// 문자열 -> 기본형
byte b = Byte.parseByte("100");
short s = Short.parserShort("100");
int i = Integer.parseInt("100");
long l = Long.parseLong("100");
float f = Float.parseFloat("3.14");
double d = Double.parseDouble("3.14");

// 문자열 -> 레퍼클래스
Byte b = Byte.valueOf("100");
Short s = Short.valueOf("100");
Integer i = Integet.valueOf("100");
Long l = Long.valueOf("100");
Float f = Float.valueOf("3.14");
Double d = Double.valueOf("3.14");

// 기본형 -> 문자열 
String String.valueOf(boolean b);
String String.valueOf(char c);
String String.valueOf(int i);
String String.valueOf(long l);
String String.valueOf(float f);
String String.valueOf(double d);

 

오토박싱 & 언박싱

  • 기본형과 참조형간의 자동 형변환
    • 오토박싱: 기본형 -> 참조형
    • 언박싱: 참조형 -> 기본형
// 언박싱
int i =5;
Integer iObj = new Integer(7);
int sum = i + iObj;

// 컴파일러의 자동 형변환
int i =5;
Integer iObj = new Integer(7);
int sum = i + iObj.intValue();
//오토박싱
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10);

// 컴파일러
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(new Integer(10));

 

 


이전 발행글: 2023.03.10 - [java/java 기초] - 8. 예외 처리

다음 발행글: 2023.03.12 - [java/java 기초] - 10. 날짜와 시간 & 형상화