자바의 정석 <기초편> 📌chapter9. java.lang패키지와 유용한 클래스

모깅·2023년 2월 8일
0

📖 01. Object클래스

Java.lang패키지는 자바프로그래밍에 가장 기본이 되는 클래스들을 포함하고 있다. 그렇기 때문에 import문 없이 사용할 수 있게 되어있다.

-> finalize()는 메모리가 부족해서 가비지 컬렉터가 일을 해야 하는데 finalize() 메서드가 실행되면서 또 메모리를 먹고 있기 때문에 사용을 지양하자.


📖 02. Object클래스의 메서드 - equals()

<예제 9-1 >

✍️ 입력

class Ex9_1 {
	public static void main(String[] args) {
		Value v1 = new Value(10);
		Value v2 = new Value(10);

		if (v1.equals(v2))
			System.out.println("v1과 v2는 같습니다.");
		else
			System.out.println("v1과 v2는 다릅니다.");
	} // main
} 

class Value {
	int value;

	Value(int value) {
		this.value = value;
	}
}

💻 출력
v1과 v2는 다릅니다.

-> 두 객체의 참조변수(주소값)을 비교하기 때문에 다를 수 밖에 없다.


📖 03. equals()의 오버라이딩

객체의 멤버변수를 비교하려면 오버라이딩 해야한다.

<예제 9-2 >

✍️ 입력

class Person {
	long id;

	public boolean equals(Object obj) {
		if(!(obj instanceof Person)) return false;
			
		return id ==((Person)obj).id;
	}

	Person(long id) {
		this.id = id;
	}
}

class Ex9_2 {
	public static void main(String[] args) {
		Person p1 = new Person(8011081111222L);
		Person p2 = new Person(8011081111222L);

		if(p1.equals(p2))
			System.out.println("p1과 p2는 같은 사람입니다.");
		else
			System.out.println("p1과 p2는 다른 사람입니다.");
	}
}

💻 출력
p1과 p2는 같은 사람입니다.


📖 04. Object클래스의 메서드 - hashCode()

-> 해시코드가 같은 두 객체가 존재 할 수 있다.

  • 그러나 Object클래스에 정의된 hashCode메서드는 객체의 주소값을 이용해서 해시코드를 만들어 반환하기 때문에 서로 다른 두 객체는 결코 같은 해시코드를 가질 수 없다.

-> 인스턴스변수 값으로 객체가 같고 다름을 판단해야 할 경우라면 equals메서드 뿐 만아니라 hashCode메서드도 오버라이딩 해야한다.

  • 같은 객체라면 hashCode메서드를 호출했을 때 결과값인 해시코드도 같아야 하기 때문이다.
  • 만약 오버라이딩 하지 않는다면 Object클래스에 정의된 대로 모든 객체가 서로 다른 해시코드를 가질 것이다.

<예제 9-3 >

✍️ 입력

class Ex9_3 {
	public static void main(String[] args) {
		String str1 = new String("abc");
		String str2 = new String("abc");

		System.out.println(str1.equals(str2));
		System.out.println(str1.hashCode());
		System.out.println(str2.hashCode());
		System.out.println(System.identityHashCode(str1));
		System.out.println(System.identityHashCode(str2));
	}
}

💻 출력
true
96354
96354
705927765
366712642


📖 05. Object클래스의 메서드 - toString()

  • 인스턴스에 대한 정보를 문자열(String)로 제공할 목적으로 정의한 것이다. 인스턴스의 정보를 제공한다는 것은 대부분의 경우 인스턴스 변수에 저장된 값들을 문자열로 표현한다는 뜻이다.

  • toString()을 오버라이딩하지 않는다면, 클래스이름과 16진수의 해시코드를 얻게 될 것이다.

<예제 9-4 >

✍️ 입력

class Card {
	String kind;
	int number;

	Card() {
		this("SPADE", 1);
	}

	Card(String kind, int number) {
		this.kind = kind;
		this.number = number;
	}
}

class Ex9_4 {
	public static void main(String[] args) {
		Card c1 = new Card();
		Card c2 = new Card();

		System.out.println(c1.toString());
		System.out.println(c2.toString());
	}
}

💻 출력
Card@2a139a55
Card@15db9742

-> toString()을 오버라이딩 하지 않았기 때문에 Object클래스의 toString() 반환값에 따라 다음과 같이 다른 객체의 정보값이 나온다.


📖 06. toString()의 오버라이딩

<예제 9-5 >

✍️ 입력

class Card2 {
	String kind;
	int number;

	Card2() {
		this("SPADE", 1);  // Card(String kind, int number)를 호출
	}

	Card2(String kind, int number) {
		this.kind = kind;
		this.number = number;
	}

	public String toString() {
		return "kind : " + kind + ", number : " + number;
	}
}

class Ex9_5 {
	public static void main(String[] args) {
		Card2 c1 = new Card2();
		Card2 c2 = new Card2("HEART", 10);
		System.out.println(c1.toString());
		System.out.println(c2.toString());
	}
}

💻 출력
kind : SPADE, number : 1
kind : HEART, number : 10

-> toString()을 오버라이딩하여 보다 쓸모 있는 정보를 제공한다.


📖 07. String클래스 && 08. 문자열(String)의 비교

-> '+'를 사용해서 문자열을 결합하는 것은 맨 연산마다 String인스턴스가 생성되어 메모리공간을 차지하게 되므로 가능한 결합횟수를 줄이는 것이 좋다.
-> 문자열 작업이 많이 필요한 경우 StringBuffer클래스를 사용하는 것이 좋다.
why? StringBuffer인스턴스에 저장된 문자열은 변경이 가능하기 때문이다.

<예제 9-6 >

✍️ 입력

class Ex9_6 {
	public static void main(String[] args) {
		String str1 = "abc";
		String str2 = "abc";
		System.out.println("String str1 = \"abc\";");
		System.out.println("String str2 = \"abc\";");

		System.out.println("str1 == str2 ?  " + (str1 == str2));
		System.out.println("str1.equals(str2) ? " + str1.equals(str2));
		System.out.println();

		String str3 = new String("abc");
		String str4 = new String("abc");

		System.out.println("String str3 = new String(\"abc\");");
		System.out.println("String str4 = new String(\"abc\");");

		System.out.println("str3 == str4 ? " + (str3 == str4));
		System.out.println("str3.equals(str4) ? " + str3.equals(str4));
	}
}

💻 출력
String str1 = "abc";
String str2 = "abc";
str1 == str2 ? true
str1.equals(str2) ? true

String str3 = new String("abc");
String str4 = new String("abc");
str3 == str4 ? false
str3.equals(str4) ? true

-> '=='는 주소값 비교, 'equals()'는 내용을 비교


📖 09. 문자열 리터럴(String리터럴)

문자열 리터럴은 클래스 파일이 클래스 로더에 의해 메모리에 올라갈 때, 클래스 파일의 리터럴들이 JVM내에 있는 '상수 저장소(constant pool)'에 저장된다. 이 때, "AAA"와 같은 문자열 리터럴은 자동적으로 생성되어 저장되는 것이다.

<예제 9-7 >

✍️ 입력

class Ex9_7 {
	public static void main(String args[]) {
		String s1 = "AAA";
		String s2 = "AAA";
		String s3 = "AAA";
		String s4 = "BBB";
	}
}

💻 출력
없음.


📖 10. 빈 문자열(empty string)

<예제 9-8 >

✍️ 입력

class Ex9_8 {
	public static void main(String[] args) {
		// 길이가 0인 char배열을 생성한다.
		char[] cArr = new char[0];    // char[] cArr = {};와 같다.
		String s = new String(cArr);  // String s = new String("");와 같다.

		System.out.println("cArr.length="+cArr.length);
		System.out.println("@@@"+s+"@@@");
	}
}

💻 출력
cArr.length=0
@@@@@@

-> 빈 문자열이 가능하며 문자열을 초기화 할 때 ""(문자의 개수가 0인 문자배열)을 쓰고, 문자를 초기화 할 땐 ' '(공백)을 사용하자.(문자는 빈 문자가 안 됨!)


📖 11. String클래스의 생성자와 메서드


📖 12. join()과 StringJoiner

  • 문자열을 결합하는 방법

<예제 9-9 >

✍️ 입력

import java.util.StringJoiner;

class Ex9_9 {
	public static void main(String[] args) {
		String animals = "dog,cat,bear";
		String[] arr   = animals.split(",");

		System.out.println(String.join("-", arr));

		StringJoiner sj = new StringJoiner("/","[","]");

		for(String s : arr)
			sj.add(s);

		System.out.println(sj.toString());
	}
}

💻 출력
dog-cat-bear
[dog/cat/bear]

-> for(String s : arr) : arr배열에서 하나씩 꺼내서 s에 넣는다.


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

방법 1은 가독성이 좋으니 극한으로 성능을 올리는게 아니라면 방법 1을 사용하자.

valueof()는 참조변수의 값을 반환한다. 그러나 오토박싱에 의해서 기본 자료형으로 받을 수 있다.


📖 14. 문자열과 기본형 간의 변환 예제

<예제 9-10 >

✍️ 입력

class Ex9_10 {
	public static void main(String[] args) {
		int iVal = 100;
		String strVal = String.valueOf(iVal); // int를 String으로 변환한다.
		
		double dVal = 200.0;
		String strVal2 = dVal + "";	// int를 String으로 변환하는 또 다른 방법

		double sum  = Integer.parseInt("+"+strVal)
                                          + Double.parseDouble(strVal2);
		double sum2 = Integer.valueOf(strVal) + Double.valueOf(strVal2);
		
		System.out.println(String.join("",strVal,"+",strVal2,"=")+sum);
		System.out.println(strVal+"+"+strVal2+"="+sum2);
	}
}

💻 출력
100+200.0=300.0
100+200.0=300.0

-> + "" 을 해주는 경우는 String 객체를 계속 생성해서 더해주는 거라서 효율적이지 않다.
-> join()을 사용해서 메모리를 효율적으로 관리하자.


📖 15. StringBuffer클래스 && 16. StringBuffer의 생성자


📖 17. StringBuffer의 변경

  1. 배열(StringBuffer)을 재선언 한다.
  2. 복사한다.
  3. 원래 참조변수의 새로운 참조변수의 값을 넣어준다.
  • append()는 StringBuffer(자기자신)을 반환하기 때문에 연속해서 사용 할 수 있다.
    ex) sb.append("123").append("ZZ");

📖 18. StringBuffer의 비교

<예제 9-11 >

✍️ 입력

class Ex9_11 {
	public static void main(String[] args) {
		StringBuffer sb  = new StringBuffer("abc");
		StringBuffer sb2 = new StringBuffer("abc");

		System.out.println("sb == sb2 ? " + (sb == sb2));
		System.out.println("sb.equals(sb2) ? " + sb.equals(sb2));
		
		// StringBuffer의 내용을 String으로 변환한다.
		String s  = sb.toString();	// String s = new String(sb);와 같다.
		String s2 = sb2.toString();

		System.out.println("s.equals(s2) ? " + s.equals(s2));
	}
}

💻 출력
sb == sb2 ? false
sb.equals(sb2) ? false
s.equals(s2) ? true

-> StringBuffer는 equals()를 오버라이딩 하고 있지 않기 때문에 주소값을 비교한다.
-> 같은 내용으로 비교하고 싶다면 toString()을 통해 문자열로 바꾼 후 equals()를 사용하자.


📖 19. StringBuffer의 생성자와 메서드


📖 20. StringBuffer의 생성자와 메서드 예제

<예제 9-12 >

✍️ 입력

class Ex9_12 {
	public static void main(String[] args) {
		StringBuffer sb = new StringBuffer("01");
		StringBuffer sb2 = sb.append(23);
		sb.append('4').append(56);
		
		StringBuffer sb3 = sb.append(78);			
		sb3.append(9.0);

		System.out.println("sb ="+sb);
		System.out.println("sb2="+sb2);
		System.out.println("sb3="+sb3);

		System.out.println("sb ="+sb.deleteCharAt(10));
		System.out.println("sb ="+sb.delete(3,6));
		System.out.println("sb ="+sb.insert(3,"abc"));
		System.out.println("sb ="+sb.replace(6, sb.length(), "END"));

		System.out.println("capacity="+sb.capacity());
		System.out.println("length="+sb.length());
	}
}

💻 출력
sb =0123456789.0
sb2=0123456789.0
sb3=0123456789.0
sb =01234567890
sb =01267890
sb =012abc67890
sb =012abcEND
capacity=18
length=9


📖 21. StringBuilder

  • StringBuffer : 멀티쓰레드에 안전하도록 동기화
  • StringBuilder : 싱글 쓰레드, 비동기화 -> 더 빠르다.

📖 22. Math클래스 && 23. Math의 메서드

  • Math클래스의 생성자는 접근 제어자가 private이기 때문에 다른 클래스에서 Math인스턴스를 생성할 수 없도록 되어있다.
    그 이유는 클래스 내에 인스턴스 변수가 하나도 없기 때문에 생성할 필요도 없다. Math클래스의 메서드는 모두 static이다.


📖 24. Math의 메서드 예제

<예제 9-13 >

✍️ 입력

import static java.lang.Math.*;
import static java.lang.System.*;

class Ex9_13 {
	public static void main(String args[]) {
		double val = 90.7552;
		out.println("round("+ val +")="+round(val));// 반올림

		val *= 100;
		out.println("round("+ val +")="+round(val));// 반올림

		out.println("round("+ val +")/100  =" + round(val)/100);   // 반올림
		out.println("round("+ val +")/100.0=" + round(val)/100.0); // 반올림
		out.println();
		out.printf("ceil(%3.1f)=%3.1f%n",  1.1, ceil(1.1));    // 올림
		out.printf("floor(%3.1f)=%3.1f%n", 1.5, floor(1.5));   // 버림	
		out.printf("round(%3.1f)=%d%n",    1.1, round(1.1));   // 반올림
		out.printf("round(%3.1f)=%d%n",    1.5, round(1.5));   // 반올림
		out.printf("rint(%3.1f)=%f%n",     1.5, rint(1.5));    // 반올림
		out.printf("round(%3.1f)=%d%n",   -1.5, round(-1.5));  // 반올림
		out.printf("rint(%3.1f)=%f%n",    -1.5, rint(-1.5));   // 반올림
		out.printf("ceil(%3.1f)=%f%n",    -1.5, ceil(-1.5));   // 올림
		out.printf("floor(%3.1f)=%f%n",   -1.5, floor(-1.5));  // 버림
	}
}

💻 출력
round(90.7552)=91
round(9075.52)=9076
round(9075.52)/100 =90
round(9075.52)/100.0=90.76

ceil(1.1)=2.0
floor(1.5)=1.0
round(1.1)=1
round(1.5)=2
rint(1.5)=2.000000
round(-1.5)=-1
rint(-1.5)=-2.000000
ceil(-1.5)=-1.000000
floor(-1.5)=-2.000000


📖 25. 래퍼(wrapper) 클래스

객체지향 개념에서 모든 것은 객체로 다루어져야 한다. 그러나 자바에서는 8개의 기본형을객체로 다루지 않는다. 대신 높은 성능을 얻을 수 있다.
때로는 기본형 변수도 어쩔 수 없이 객체로 다뤄야 할 경우가 있는데 이때 사용되는 것이 래퍼(wrapper)클래스이다.


📖 26. 래퍼(wrapper) 클래스 예제

<예제 9-14 >

✍️ 입력

class Ex9_14 {
	public static void main(String[] args) {
		Integer i  = new Integer(100);
		Integer i2 = new Integer(100);

		System.out.println("i==i2 ? "+(i==i2));
		System.out.println("i.equals(i2) ? "+i.equals(i2));
		System.out.println("i.compareTo(i2)="+i.compareTo(i2));
		System.out.println("i.toString()="+i.toString());

		System.out.println("MAX_VALUE="+Integer.MAX_VALUE);
		System.out.println("MIN_VALUE="+Integer.MIN_VALUE);
		System.out.println("SIZE="+Integer.SIZE+" bits");
		System.out.println("BYTES="+Integer.BYTES+" bytes");
		System.out.println("TYPE="+Integer.TYPE);
	}
}

💻 출력
i==i2 ? false
i.equals(i2) ? true
i.compareTo(i2)=0
i.toString()=100
MAX_VALUE=2147483647
MIN_VALUE=-2147483648
SIZE=32 bits
BYTES=4 bytes
TYPE=int


📖 27. Number 클래스

  • BigInteger는 long으로도 다룰 수 없는 큰 범위의 정수를, BigDecimal은 double로도 다룰 수 없는 큰 범위의 부동 소수점수를 처리하기 위한것이다.

📖 28. 문자열을 숫자로 변환하기

문자열 -> 기본형
ex) int i = Integer.ParseInt("100");
문자열 -> 래퍼 클래스
ex) Integer i = Integer.valueOf("100");


📖 29. 문자열을 숫자로 변환하기 예제

<예제 9-15 >

✍️ 입력

class Ex9_15 {
	public static void main(String[] args) {
		int		i  = new Integer("100").intValue();
		int		i2 = Integer.parseInt("100");
		Integer  i3 = Integer.valueOf("100");

		int i4 = Integer.parseInt("100",2);
		int i5 = Integer.parseInt("100",8);
		int i6 = Integer.parseInt("100",16);
		int i7 = Integer.parseInt("FF", 16);
//		int i8 = Integer.parseInt("FF");     // NumberFormatException발생

		Integer i9 = Integer.valueOf("100",2);
		Integer i10 = Integer.valueOf("100",8);
		Integer i11 = Integer.valueOf("100",16);
		Integer i12 = Integer.valueOf("FF",16);
//		Integer i13 = Integer.valueOf("FF"); // NumberFormatException발생

		System.out.println(i);
		System.out.println(i2);
		System.out.println(i3);
		System.out.println("100(2) -> "+i4);
		System.out.println("100(8) -> "+i5);
		System.out.println("100(16)-> "+i6);
		System.out.println("FF(16) -> "+i7);

		System.out.println("100(2) -> "+i9);
		System.out.println("100(8) -> "+i10);
		System.out.println("100(16)-> "+i11);
		System.out.println("FF(16) -> "+i12);
	}
}

💻 출력
100
100
100
100(2) -> 4
100(8) -> 64
100(16)-> 256
FF(16) -> 255
100(2) -> 4
100(8) -> 64
100(16)-> 256
FF(16) -> 255


📖 30. 오토박싱 & 언박싱

이전에는 기본형과 참조형 간의 연산이 불가능했기 때문에, 래퍼 클래스로 기본형을 객체로 만들어서 연산해야 했다.

이제는 컴파일러가 알아서 형변환 해주는데
기본형 값을 래퍼 클래스 객체로 자동 변환해주는 것을 '오토박싱'
그 반대를 '언박싱' 이라고 한다.


📖 31. 오토박싱 & 언박싱 예제

<예제 9-16 >

✍️ 입력

class Ex9_16 {
	public static void main(String[] args) {
		int i = 10;

		// 기본형을 참조형으로 형변환(형변환 생략가능)
		Integer intg = (Integer)i; // Integer intg = Integer.valueOf(i);
		Object obj = (Object)i;    // Object obj = (Object)Integer.valueOf(i);

		Long     lng = 100L;  // Long lng = new Long(100L);

		int i2 = intg + 10;   // 참조형과 기본형간의 연산 가능
		long l = intg + lng;  // 참조형 간의 덧셈도 가능

		Integer intg2 = new Integer(20);
		int i3 = (int)intg2;  // 참조형을 기본형으로 형변환도 가능(형변환 생략가능)

		Integer intg3 = intg2 + i3; 

		System.out.println("i     ="+i);
		System.out.println("intg  ="+intg);
		System.out.println("obj   ="+obj);
		System.out.println("lng   ="+lng);
		System.out.println("intg + 10  ="+i2);
		System.out.println("intg + lng ="+l);
		System.out.println("intg2 ="+intg2);
		System.out.println("i3    ="+i3);
		System.out.println("intg2 + i3 ="+intg3);
	}
}

💻 출력
i =10
intg =10
obj =10
lng =100
intg + 10 =20
intg + lng =110
intg2 =20
i3 =20
intg2 + i3 =40





[출처] 자바의 정석 <기초편> (남궁 성 지음)

profile
멈추지 않기

0개의 댓글