패키지(1) java.lang 의 Object, Wrapper, String, StringBuffer 클래스

Yeppi's 개발 일기·2022년 5월 24일
0

JAVA

목록 보기
22/27
post-thumbnail

1. java.lang 패키지

1) 개념

  • 모든 자바 프로그램에서 기본적으로 사용하는 필수 클래스들을 모아 놓은 패키지
  • ex. System 클래스, String 클래스
  • 워낙 자주 사용해서, 유일하게 import 없이 사용가능

2) 구조

최상위

Object

중간

String, StringBuffer, Number, Boolean, Character

Number 의 하위

Byte, Short, Integer, Long, Float, Double



2. Object 클래스

1) 개념

  • 모든 클래스의 최상위 부모 클래스
  • 자동 추가
    눈에 보이지 않지만 상속하고 있음
  • Object 클래스는 힙 메모리를 사용
  • 메서드의 두 인스턴스가 같다
    = 힙 메모리가 같다
    = 메모리 위치(주소)가 같다
  • 사용이유?
    • 모든 자바 클래스가 가지고 있어야할 공통의 변수와 메소드를 Object 가 가지고 있음
      → 자식 클래스가 상속받기 위해
    • 묵시적 형변환으로
      → 모든 자바 객체를 하나의 타입으로 묶어서 다형성을 적용하기 위해


2) hashCode()

생성된 객체의 메모리 주소정보를 리턴

  • 인스턴스의 저장 주소를 반환
  • hash 란?
    정보를 저장, 검색하는 자료구조
  • hash 방식이란?
    힙메모리에 인스턴스가 저장되는 방식
  • 자료의 특정 값(키 값)에 대한 저장 위치를 반환해주는 해시 함수를 사용
  • 두 인스턴스가 같다는 것은?
    두 인스턴스에 대한 equals() 의 반환 값이 true
    ⇒ 동일한 hashCode() 값을 반환

📌해시코드 값이 다른 경우📌

  • 객체에 같은 값을 할당하더라도, 주소 값은 다를 수 있음
    ❗ 실행 결과는 동적으로 생성된 해시코드 정보이기 때문 ❗

  • 아래 출력결과는 서로 다른 객체 주소 값을 출력

Fruit apple1 = new Fruit("사과", 11);
System.out.println(apple1.hashCode());

Fruit apple2 = new Fruit("사과", 11);
System.out.println(apple2.hashCode());

📌해시코드 값이 같은 경우📌

  • 위와 같은 경우, 같은 값을 할당했는 지 비교할 수 없는 문제점이 발생. . .
    = 객체 주소는 달라도, 객체가 가진 멤버변수에 할당한 값이 동일한 경우
  • 객체 주소를 비교하지 않고,
    객체의 멤버변수에 해시 값을 생성하여 비교하면?
    두 객체가 같은 값을 가지고 있는 지 비교할 수 있음
  • Object 클래스의 hashCode() 메서드가 상속되지 않도록 ⇒ 메서드 오버라이딩
    • hashCode() 매개변수 값이 동일한 경우? 동일한 해시코드 return
public class Fruit extends java.lang.Object {
	. . . 
	public int hashCode() {
		return Objects.hash(name, number); // 사과, 11
	}
}


3) equals()

객체의 내용을 비교

  • 원래는 두 인스턴스의 주소 값을 비교하여 true/false를 반환 ⇒ ==
  • 그러나 재정의 하여 두 인스턴스가 논리적으로 동일함의 여부를 구현함
  • 인스턴스가 다르더라도 논리적으로 동일한 경우
    true를 반환하도록 재정의 할 수 있음
    ex. 같은 학번, 같은 사번, 같은 아이디의 회원

👉 물리적으로 다르지만, 논리적으로 같은 경우

  • 따라서 객체 주소를 비교하는 == 연산자와 유사한 동작
    • 참조 변수의 메모리 주소만 비교하므로, equals() 와 같은 명령어라 볼 수 있음
  • hashCode() 처럼, 객체의 내용을 비교하기 위해 메서드 오버라이딩 해야 함

📌예시📌

  • hashCode(), equals() 가 있는 Fruit 클래스
public class Fruit {
	private String name;
	private int number;
	
	public Fruit(String name, int number) {
		super();
		this.name = name;
		this.number = number;
	}
    
	@Override
	public int hashCode() {
		return Objects.hash(name, number);
	}

	@Override
	public boolean equals(Object obj) {
		Fruit other = (Fruit) obj;
		return name.equals(other.name) && number == other.number;
	} 

	public String getName() {
		return name;
	}
	public int getScore() {
		return number;
	}

}
  • main
		Fruit apple1 = new Fruit("사과", 11);
		Fruit apple2 = new Fruit("사과", 11);
		
		if(apple1==apple2) {
			System.out.println("객체의 주소는 동일");
		} else {
			System.out.println("객체의 주소는 다름");
		}
		
		if(apple1.equals(apple2)) {
			System.out.println("객체의 내용은 동일");
		} else {
			System.out.println("객체의 내용은 다름");
		}

출력결과

객체의 주소는 다름
객체의 내용은 동일

📌예시📌

  • hashCode(), equals()true, false
	@Override
	public int hashCode() {
		return studentNum;
		
	}

	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Student) {
			Student std = (Student) obj; // 다운캐스팅
			
			if(this.studentNum == std.studentNum) {
				return true;
			}
			else return false;
		}
		return false;
	}
  • main
		Student std1 = new Student(100, "Lee");
		Student std2 = new Student(100, "Lee");
		
		// 다른 객체이기 때문에 false
		System.out.println(std1 == std2); 
		
		// equals() 오버라이딩 해주면, 논리적으로 같기 때문에 true
		System.out.println(std1.equals(std2));
		
		// hashCode() 오버라이딩 해주면, 논리적으로 같기 때문에 같은 주소 값 출력
		System.out.println(std1.hashCode());
		System.out.println(std2.hashCode());
		
		// 실제 가상 메모리 주소 값 출력
		System.out.println(System.identityHashCode(std1));
		System.out.println(System.identityHashCode(std2));

// Integer, String도 마찬가지 같은 주소 값 출력

출력결과

false
true
100
100
1131316523
852687460


4) toString()

"클래스 이름 + 객체의 메모리 주소" 의 문자열 리턴

  • 객체의 멤버변수에 할당된 값을, 하나의 문자열로 리턴

  • 위 메서드들과 마찬가지로, 실제 객체의 값을 리턴하기 위해서는?
    ⇒ 메서드 오버라이딩


📌예시📌

  • hashCode(), equals() 가 있는 Fruit 클래스
public class Fruit {
	. . .
	
    @Override
	public String toString() {
		return "과일의 종류는 " + name + ", 개수는 " + number + "개";
	}
}
  • main
Fruit apple1 = new Fruit("사과", 11);		
System.out.println(apple1.toString()); // 명시적 호출
System.out.println(apple1); // 묵시적 호출

출력결과

과일의 종류는 사과, 개수는 11개
과일의 종류는 사과, 개수는 11개


5) clone()

객체의 원복을 복제

  • 생성과정의 복잡한 과정을 반복하지 않고 복제 할 수 있음
  • 생성자와의 차이점
    • 생성자 초기화해서 처음 값을 가지고 초기값 생성
    • clone () 하위 클래스까지 변한 값을 그대로 복제
  • clone() 메서드를 사용하면?
    객체의 정보(멤버 변수 값 등)가 동일한 또 다른 인스턴스가 생성되는 것
    ⇒ 객체 지향 프로그램에서의 정보 은닉, 객체 보호의 관점에서 위배될 수 있음

👉 해당 클래스의 clone() 메서드의 사용을 허용한다는 의미로, cloneable 인터페이스명시해


📌예시📌

  • public class Student implements Cloneable
public class Student implements Cloneable {

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}
  • main 에서 throws CloneNotSupportedException
std1.setStudentName("KIM");
Student copyStudent = (Student) std1.clone(); // 100, KIM
System.out.println(copyStudent); // 출력 100, KIM


💡 Alt + Shift + S 💡

  • hashCode(), equals(), toString() 등 메서드 오버라이딩 단축키

👉 클래스를 만들면, 기본적으로 hashCode() equals() toString() 메소드를 오버라이딩 해두자!



3. String 클래스

1) 개념

가장 많이 사용해서 중요

  • 일반 클래스와 달리 객체를 생성하는 방법이 두 가지

힙 메모리에 인스턴스로 생성

  • 힙 메모리 생성될 때마다 다른 주소 값
  • 일반 클래스와 마찬가지로 new 를 사용
  • 새로운 메모리공간에 각각 사과 생성
    ex. String apple1 = new String("사과");


상수 풀(constant pool)에 있는 주소를 참조

  • 상수 풀의 문자열은 모두 같은 주소 값
  • 쌍따옴표로 문자열을 감싸서 리터럴 형태로 생성
  • 문자열 객체를 위한 리터럴 영역에 별도의 메모리 공간 사용
    ex. String apple2 = "사과";


2) String 메서드

종류

메소드기능
charAt(int idx) : char인덱스(idx)에 위치한 문자(char)
concat(String str) : String새로운 문자열(str)을 연결
endsWith(String suffix) : boolean특정 문자열(suffix)로 끝나는지
equalsIgnoreCase(String str) : boolean대소문자를 무시했을 때, 비교 문자열(str)과 내용이 같은지
indexOf(int ch) : int특정 문자(ch)의 인덱스 위치
indexOf(String str) : int특정 문자열(str)의 인덱스 위치
length() : int문자열의 길이
startsWith(Strng prefix) : boolean특정 문자(prefix)로 시작하는지
substring(int beginIdx) : String특정 인덱스(beginIdx)이후의 문자열
substring(int start, int end) : Stringstart 인덱스부터 다른 end 인데스까지의 문자열
toLowerCase() : String문자열을 소문자로 변환
toUpperCase() : String문자열을 대문자로 변환
trim() : String문자열 앞 뒤의 공백을 제거
split(String regex) : String[]특정 문자열(regex)을 구분자로 문자열을 분해
문자열 배열(String[])로 리턴

중요 메서드

  • split(" "); → 문자열을 공백 기준으로 분리한 단어
  • length() → 문자열 길이
  • indexOf('o') → 문자열에서 첫 번째 o의 위치
  • startsWith("kim") → 문자열이 kim으로 시작하나?
  • substring(10, 26) → 문자열 10~26인덱스 사이의 문자열


📌예시📌

  • 한번 생성된 String 은 불변(immutable)
    new, 상수 둘 다 불변이다
  • String 을 연결하면 기존의 String 에 연결되는 것이 아닌
    새로운 문자열이 생성됨
    메모리 낭비가 발생할 수도 있음

메모리 낭비 예시1

  • 총 7개의 메모리가 생김
String str = "11" + "22" + "33" + "44";

메모리 낭비 예시2

  • String 연결 시 새로운 문자열 생성
		String java = new String("java");
		String android = new String("android");
		
		System.out.println(System.identityHashCode(java)); // 263025902 출력
		java = java.concat(android); // java와 android 연결  => 새로운 문자열 생성
		
		System.out.println(System.identityHashCode(java)); // 438135304 출력
		// android와 연결된 java는 기존 java와 다른 주솟값을 가리킨다.

출력결과

1651191114
javaandroid
1586600255


4. StringBuffer 클래스

1) 개념

  • 내부적으로 가변적인 char[]를 멤버 변수로 가짐
  • 문자열을 여러번 연결하거나 변경할 때 사용하면 유용함
  • 새로운 인스턴스를 생성하지 않고 char[] 를 변경함
  • StringBuffer
    멀티 쓰레드 프로그래밍에서 동기화(synchronization)을 보장
    ⇒ 두 개 이상의 스레드가 같은 메모리 엑세스할때 순서 정해짐

  • 단일 쓰레드 프로그램에서는 StringBuilder 사용을 권장



2) StringBuffer 메서드

메소드기능
length() : int문자열의 길이
charAt(int index) : char특정 인덱스에 위치한 문자
toStirng() : StringStringBuffer 저장된 문자열
delete(int start, int end) : StringBufferstart부터 end까지의 문자 제거
indexOf(String str) : int문자열(str)의 인덱스 위치
insert(int offset, String str) : StringBufferoffset 인덱스 위치에 문자열(str) 삽입
substring(int start) : Stringstart 위치에서부터 문자열 잘라서 리턴


📌예시📌

  • StringBuilder, StringBuffer 활용
  • toString() 메서드로 String 반환
		String java = new String("java");
		String android = new String("android");
		
		StringBuilder buffer = new StringBuilder(java); 
		System.out.println(System.identityHashCode(buffer)); // 1651191114 출력
		
		buffer.append(android); // append()로 buffer에 값 넣기
		System.out.println(System.identityHashCode(buffer)); // 1651191114 출력
		// buffer는 가변적이므로, 주소값이 동일
		
		String test = buffer.toString(); // toString()으로 buffer 사용하기
		System.out.println(test);

출력결과

1651191114
1651191114
javaandroid


🍑String VS StringBuffer🍑

고정 길이 문자열

  • 한 번 생성된 객체는 변경되지 않고 새로운 문자열 객체가 생성
  • String
    • 문자열 이어붙이면 새로 생성 ⇒ 메모리 낭비
    • 절대 안변함
    • 고정 길이

가변 길이 문자열

  • StringBuffer
    • 하나의 문자열에 계속 붙여나갈 수 있음 ⇒ 메모리 효율
    • 변함
    • 가변 길이


5. Wrapper 클래스

1) 개념

Boolean, Character

Byte, Short, Integer, Long, Float, Double

  • 기본 타입의 데이터를 객체로 감싼다
  • 기본형 타입 클래스 8개
  • 기본형 타입을 객체 형태로 저장하기 위해 사용
  • Character-char와 Integer-int 제외,
    나머지는 기본 타입과 클래스 이름이 동일
  • 클래스이름.메소드호출 → static 메소드
    Integer.parseInt


📌예시📌

  • 문자열형태의 데이터를 기본형 데이터로 바꾸고 싶을 때
int a = Integer.parseInt(args[0]);
System.out.println("정수 값 : " + a);


오토 박싱 & 언박싱

boxing

기본타입의 데이터 → 래퍼 객체로 변환

unboxing

래퍼 객체 → 기본 타입으로 변환


📌예시📌

		int num1 = 11;		

		// 정상적 boxing
		Integer baseBox = Integer.valueOf(num1);

		// 정상적 unboxing
		int baseUnbox = baseBox.intValue();
		System.out.println(baseUnbox);
		
		
		int num2 = 22;

		// 오토 boxing
		Integer autoBox = num2;

		// 오토 unboxing
		int autoUnbox = autoBox;
		System.out.println(autoUnbox);

출력 결과

11
22


6. text block

  • java 13 부터 사용 가능
  • 문자열을 """ """ 사이에 이어서 만들 수 있음
  • html, json 문자열을 만드는데 유용하게 사용

📌예시📌

	// text block 사용하기, java 13버전부터
	public static void main(String[] args) {

		String textBlocks = """
				Hello,
				hi,
				how r u""";
		System.out.println(textBlocks);
		System.out.println(getBlockOfHtml());
	}
	
	
	public static String getBlockOfHtml() {
	    return """
	            <html>
	                <body>
	                    <span>example text</span>
	                </body>
	            </html>""";
	}

출력결과

Hello,
hi,
how r u
<html>
    <body>
        <span>example text</span>
    </body>
</html>
profile
imaginative and free developer. 백엔드 / UX / DATA / 기획에 관심있지만 고양이는 없는 예비 개발자👋

0개의 댓글