java.lang패키지
가장 기본이 되는 클래스들을 포함
import문 없이 사용가능
Object클래스
모든 클래스의 최고 조상
Object클래스의 멤버들은 모든 클래스에서 바로 사용 가능
중요한 몇가지를 살펴보자
equals(Object obj)
매개변수로 객체의 참조변수를 받아서 비교해, 그 결과를 boolean값으로 알려주는 메소드
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package object;
class Value {
int value;
Value(int value) {
this.value = value;
}
}
public class EqualsEx1 {
public static void main(String[] args) {
Value v1 = new Value(10);
Value v2 = new Value(10);
// 서로 다른 주소값을 갖고 있기 때문에 false
if(v1.equals(v2)) // Object클래스의 equals()메소드 사용
System.out.println("v1과 v2는 같습니다");
else
System.out.println("v1과 v2는 다릅니다");
v2 = v1;
// 같은 주소값을 갖고 있기 때문에 true
if(v1.equals(v2))
System.out.println("v1과 v2는 같습니다");
else
System.out.println("v1과 v2는 다릅니다");
}
}
|
cs |
출력
v1과 v2는 다릅니다
v1과 v2는 같습니다
hashCode()
해싱기법에 사용되는 '해시함수'를 구현한 것
해싱 - 데이터관리기법 중 하나, 다량의 데이터 저장/검색하는 데 유용
해시함수 - 찾고자하는 값을 입력하면, 그값이 저장된 위치를 알려주는 해시코드를 반환
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class HashCodeEx1 {
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));
}
}
|
cs |
출력
true
96354
96354
167185492
592179046
String클래스는 문자열의 내용이 같으면 동일한 해시코드를 반환하도록 hashCode()메소드가 오버라이딩되어 있음
반면에, System.identityHashCode()메소드는 객체의 주소값으로 해시코드 생성해 다른 해시코드값을 가짐
toString()
인스턴스에 대한 정보를 문자열로 제공할 목적으로 정의
Object클래스에 정의된 toString()은 클래스이름과 16진수의 해시코드를 반환
toString()오버라이딩 전
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
class Card {
String kind;
int number;
Card() {
this("SPADE", 1);
}
Card(String kind, int number) {
this.kind = kind;
this.number = number;
}
}
public class CardToString {
public static void main(String[] args) {
Card c1 = new Card();
Card c2 = new Card();
// toString()메소드 오버라이드 x
System.out.println(c1);
System.out.println(c2);
System.out.println(c1.toString());
System.out.println(c2.toString());
}
}
|
cs |
출력
object.Card@50f8360d
object.Card@2cb4c3ab
Object클래스의 toString()메소드의 반환값인,
클래스이름 + @ + 16진수 해시코드 출력됨
toString()오버라이딩 후
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package object;
class Card {
String kind;
int number;
Card() {
this("SPADE", 1);
}
Card(String kind, int number) {
this.kind = kind;
this.number = number;
}
// Object클래스의 toString()메소드 오버라이딩
@Override
public String toString() {
return "kind : " + kind + ", number : " + number;
}
}
public class CardToString {
public static void main(String[] args) {
Card c1 = new Card();
Card c2 = new Card();
// toString()메소드 오버라이드 o
System.out.println(c1);
System.out.println(c2);
System.out.println(c1.toString());
System.out.println(c2.toString());
}
}
|
cs |
출력
kind : SPADE, number : 1
kind : SPADE, number : 1
kind : SPADE, number : 1
kind : SPADE, number : 1
17~20행 - toString()메소드를 19행처럼 출력되도록 오버라이딩
인스턴스 이름 호출 == 인스턴스의 toString()메소드 호출
같은 값이 출력됨
이처럼 toString()메소드를 오버라이딩해서 보다 쓸모 있는 정보를 제공할 수 있다
clone()
자신을 복제하여 새로운 인스턴스를 생성하는 메소드
Object클래스에 정의된 clone()은 단순히 인스턴스변수의 값만을 복사하기 때문에
참조타입의 인스턴스 변수가 있는 클래스는 완전한 복제가 이루어지지 않음
-> 오버라이딩해서 사용
Cloneable인터페이스를 구현해야 사용가능,
접근제어자가 protected이기 때문에 오버라이딩 시, public으로 바꿔줘야함
clone()호출 시, 반드시 예외처리해야함
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
// clone()사용위해 Cloneable인터페이스 구현
class Point implements Cloneable {
int x,y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
// toString()오버라이딩
@Override
public String toString() {
return "x = " + x + ", y = " + y;
}
// clone()오버라이딩
@Override
public Object clone() { // Object클래스의 clone()과 다르게 public으로 접근제어자 변경
Object obj = null;
try {
obj = super.clone(); // Object클래스의 clone()호출
} catch(CloneNotSupportedException e) {}
return obj;
}
}
public class CloneEx1 {
public static void main(String[] args) {
Point original = new Point(3,5);
Point copy = (Point)original.clone(); // Object형으로 반환받았기 때문에 Point형으로 변환
System.out.println(original);
System.out.println(copy);
}
}
|
cs |
출력
x = 3, y = 5
x = 3, y = 5
공변 반환타입
오버라이딩할 때 조상 메소드의 반환타입을 자손 클래스의 타입으로 변경을 허용하는 것
|
1
2
3
4
5
6
7
8
9
10
11
|
// clone()오버라이딩
@Override
public Object clone() { // Object클래스의 clone()과 다르게 public으로 접근제어자 변경
Object obj = null;
try {
obj = super.clone(); // Object클래스의 clone()호출
} catch(CloneNotSupportedException e) {}
return obj;
}
Point copy = (Point)original.clone()
|
cs |
이런 식으로 오버라이딩할 때, 조상에 선언된 메소드의 반환타입을 그대로 사용해야 했지만
|
1
2
3
4
5
6
7
8
9
10
11
|
// clone()오버라이딩
@Override
public Point clone() {
Object obj = null;
try {
obj = super.clone();
} catch(CloneNotSupportedException e) {}
return (Point)obj;
}
Point copy = original.clone()
|
cs |
이처럼 '공변 반환타입'을 사용하면, 조상의 타입이 아닌, 실제로 반환되는 자손 객체의 타입으로 반환할 수 있어
번거로운 형변환을 하지 않아도되는 장점이 있음
얕은 복사와 깊은 복사
얕은 복사
- 객체를 clone()으로 복제하는 경우, 원본과 복제본이 같은 객체를 공유하므로 완전한 복제가 아님
- 원본 변경 -> 복제본도 변경
- 이러한 복제를 얕은 복사
깊은 복사
- 원본이 참조하고 있는 객체까지 복제하는 것
- 원본과 복제본이 서로 다른 객체를 참조 -> 원본 변경해도 복제본 변경x
- 이러한 복제를 깊은 복사
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
class Point{
int x,y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "("+x+", "+y+")";
}
}
// clone()사용위해 Cloneable인터페이스 구현
class Circle implements Cloneable {
Point p;
double r;
Circle(Point p, double r) {
this.p = p;
this.r = r;
}
// 공변반환타입 사용
public Circle shallowCopy() { // 얕은 복사
Object obj = null;
try {
obj = super.clone();
} catch(CloneNotSupportedException e) {}
return (Circle)obj;
}
public Circle deepCopy() { // 깊은 복사
Object obj = null;
try {
obj = super.clone();
} catch(CloneNotSupportedException e) {}
Circle c = (Circle)obj;
c.p = new Point(this.p.x, this.p.y);
return c;
}
public String toString() {
return "[p=" + p + ", r=" + r + "]";
}
}
public class ShallowDeepCopy {
public static void main(String[] args) {
Circle c1 = new Circle(new Point(1,1), 2.0);
Circle c2 = c1.shallowCopy(); // 얕은 복사
Circle c3 = c1.deepCopy(); // 깊은 복사
System.out.println("c1="+c1);
System.out.println("c2="+c2);
System.out.println("c3="+c3);
// 원본 값 변경
c1.p.x = 9;
c1.p.y = 9;
System.out.println("c1="+c1);
System.out.println("c2="+c2); // 변경 영향 o
System.out.println("c3="+c3); // 변경 영향 x
}
}
|
cs |
출력
c1=[p=(1, 1), r=2.0]
c2=[p=(1, 1), r=2.0]
c3=[p=(1, 1), r=2.0]
c1=[p=(9, 9), r=2.0]
c2=[p=(9, 9), r=2.0]
c3=[p=(1, 1), r=2.0]
getClass()
자신이 속한 클래스의 Class객체를 반환하는 메소드
Class객체는 클래스의 모든 정보를 담고 있음
파일 형태로 저장되어 있는 클래스를 읽어서 Class클래스에 정의된 형식으로 변환
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
final class Card {
String kind;
int number;
Card() {
this("SPADE", 1);
}
Card(String kind, int number) {
this.kind = kind;
this.number = number;
}
@Override
public String toString() {
return kind + ":" + number;
}
}
public class ClassEx1 {
public static void main(String[] args) throws Exception {
Card c = new Card("HEART", 3); // new연산자로 객체생성
Card c2 = Card.class.newInstance(); // Class객체를 통해서 객체생성
Class cObj = c.getClass(); // Card클래스의 객체를 얻음
System.out.println(c);
System.out.println(c2);
System.out.println(cObj.getName());
System.out.println(cObj.toGenericString());
System.out.println(cObj.toString());
}
}
|
cs |
출력
HEART:3
SPADE:1
classex.Card
final class classex.Card
class classex.Card
'아카이브 > 자바의 정석' 카테고리의 다른 글
| 9장 java.lang패키지와 유용한 클래스 20201018 (0) | 2020.10.18 |
|---|---|
| 9장 java.lang패키지와 유용한 클래스 20201017 (0) | 2020.10.17 |
| 8장 예외처리 20201012 (0) | 2020.10.12 |
| 8장 예외처리 20201009 (0) | 2020.10.09 |
| 7장 20200926 (0) | 2020.09.26 |