⦁ Object클래스
- 모든 클래스의 최고 조상. 오직 11개의 메소드만을 가지고 있다.
- notify(), wait() 등은 쓰레드와 관련된 메소드이다.
⦁ equals(Object obj)
- 객체 자신(this)과 주어진 객체(obj)를 비교한다. 같으면 true 다르면 false.
- Object클래스의 equals()는 객체의 주소를 비교(참조변수 값 비교)
public boolean equals(Object obj) {
return (this==obj);
}
ex)
class Value {
int value;
Value (int value) {
this.value=value;
}
// Object의 equals()를 오버라이딩해서 주소가 아닌 value를 비교
public boolean equals(Object obj) {
// return this==obj; // 서로 다른 객체의 주소비교는 항상 거짓이다.
// 참조변수의 형변환 전에는 반드시 instanceof로 확인해야함.
if(!(obj instanceof Value)) return false;
Value v = (Value)obj; // obj를 value로 형변환
return this.value==v.value;
}
}
public class Ex9_1 {
public static void main(String[] args) {
Value v1 = new Value(10);
Value v2 = new Value(10);
System.out.println(v1.equals(v2));
}
}
⦁ equals(Object obj)의 오버라이딩
- 인스턴스 변수(iv)의 값을 비교하도록 equals()를 오버라이딩해야 한다.
ex)
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;
}
}
public 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는 다른 사람입니다.");
}
}
⦁ hashCode()
- 객체의 해시코드(hash code)를 반환하는 메소드
- Object클래스의 hashCode()는 객체의 주소를 int로 변환해서 반환
- equals()를 오버라이딩하면, hashCode()도 오버라이딩해야 한다.
equals()의 결과가 true인 두 객체의 해시코드는 같아야 하기 때문이다.★★★
- System.identityHashCode(Object obj)는 Object클래스의 hashCode()와 동일
=> hashCode()를 오버라이딩 했을 경우, 기존의 hashCode가 필요할 때 사용하는 메소드
⦁ toString(), toString()의 오버라이딩
- toString() : 객체를 문자열(String)으로 변환하기 위한 메소드
public String toString() { // Objcet클래스의 toString()
return getClass().getName()+“@”+Integer.toHexString(hashCode());
}
(객체==iv집합 이므로 객체를 문자열로 변환한다는 것은 iv의 값을 문자열로 변환한다는 것과 같다.)
ex)
import java.util.Objects;
class Card {
String kind;
int number;
Card() {
this("SPADE", 1);
}
Card(String kind, int number) {
this.kind=kind;
this.number=number;
}
// equals()를 오버라이딩 하면 hashCode()도 일치하도록 오버라이딩 해야한다.
public int hashCode() {
return Objects.hash(kind, number);
}
public boolean equals(Object obj) {
if(!(obj instanceof Card))
return false;
Card c = (Card)obj;
return this.kind.equals(c.kind) && this.number==c.number;
}
// Object 클래스의 toString()을 오버라이딩
public String toString() {
return "kind : " + kind + ", number : " + number;
}
}
public class Ex9_4 {
public static void main(String[] args) {
Card c1 = new Card();
Card c2 = new Card();
System.out.println(c1.equals(c2));
System.out.println(new Card().toString());
System.out.println(new Card().toString());
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
}
}
* hashCode 오버라이딩 관련 참고 *
1) Objects 클래스는 객체와 관련된 유용한 메소드를 제공하는 유틸 클래스
2) int hash(Object... values) {...}
-> 매개변수가 가변인자(Object...)라서 호출시 지정하는 값의 개수가 정해져있지 않다.
⦁ String 클래스
- String 클래스 = 데이터(char[] - 문자배열) + 메소드(문자열 관련)
- 내용을 변경할 수 없는 불변(immutable) 클래스
String a = “a”;
String b = “b”;
a = a + b;
=> “ab” 라는 문자열이 아예 새로운 주소에 저장되고 a는 그 주소를 가리키게 된다.
- 덧셈 연산자(+)를 이용한 문자열 결합은 성능이 떨어짐.
문자열의 결합이나 변경이 잦다면, 내용을 변경가능한 StringBuffer를 사용 (내용변경 가능)
⦁ 문자열의 비교
- String str = “abc”;와 String str = new String(“abc”);의 비교
String str1 = “abc”; // 문자열 리터럴 “abc“의 주소가 str1에 저장됨
String str2 = “abc”; // 문자열 리터럴 “abc“의 주소가 str2에 저장됨
String str3 = new String(“abc”); // 새로운 String 인스턴스를 생성
String str4 = new String(“abc”); // 새로운 String 인스턴스를 생성
⦁ 문자열 리터럴
- 문자열 리터럴은 프로그램 실행시 자동으로 생성된다.(constant pool에 저장)
class Ex9_7 {
public static void main(String args[]) {
String s1 = "AAA";
String s2 = "AAA";
String s3 = "AAA";
String s4 = "BBB";
}
}
- 같은 내용의 문자열 리터럴은 하나만 만들어진다.
=> s1, s2, s3는 “AAA”의 주소를 같이 가리키게 된다.
⦁ 빈 문자열 (“”, empty string)
- 내용이 없는 문자열. 크기가 0인 char형 배열을 저장하는 문자열
String str = “”; // str을 빈 문자열로 초기화
- 크기가 0인 배열을 생성하는 것은 어느 타입이나 가능
char[] chArr = new char[0]; // 길이가 0인 char배열
int[] iArr = {}; // 길이가 0인 int배열
- 문자(char)와 문자열(String)의 초기화
String s = “”; // 빈 문자열로 초기화
char c = ‘ ’; // 공백으로 초기화
⦁ String 클래스의 생성자와 메소드
⦁ join()과 StringJoiner
- join()은 여러 문자열 사이에 구분자를 넣어서 결합한다.
String animals = "dog,cat,bear";
String[] arr = animals.split(","); // 문자열을 ‘,’를 구분자로 나눠서 배열에 저장
String str = String.join("-", arr); // 배열의 문자열을 ‘-’로 구분해서 결합
System.out.println(str); // dog-cat-bear
* 많은 문자열을 결합할 때는 join이 더 효과적이다 *
⦁ 문자열과 기본형 간의 변환
- 숫자를 문자열로 바꾸는 방법
int i = 100;
String str1 = i + ""; // 방법1
String str2 = String.valueOf(i); // 방법2
- 문자열을 숫자로 바꾸는 방법
int i = Integer.parseInt("100"); // “100”을 100으로 변환하는 방법1
int i2 = Integer.valueOf("100"); // “100”을 100으로 변환하는 방법2
Integer i2 = Integer.valueOf("100"); // 원래는 반환 타입이 Integer
=> valueOf는 타입에 상관없이 쓸 수 있어서 편리함. ★
ex)
public 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 + ""; // double을 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);
}
}
⦁ StringBuffer클래스
- String처럼 문자형 배열(char[])을 내부적으로 가지고 있다.
public final class StringBuffer implements java.io.Serializable {
private char[] value;
...
}
- 그러나 String과 달리 내용을 변경할 수 있다.(mutable)
StringBuffer sb = new StringBuffer(“abc”);
=> char 타입인 ‘a’ ‘b’ ‘c’로 저장이 된다.
sb.append(“123”); // sb의 내용 뒤에 “123”을 추가한다.
=> char 타입인 ‘a’ ‘b’ ‘c’ ‘1’ ‘2’ ‘3’ 이 저장 된다.
⦁ StringBuffer의 생성자
- 배열은 길이 변경불가. 공간이 부족하면 새로운 배열을 생성해야 한다.
① 새로운 배열 생성
② 기존 내용을 복사
③ 참조 변경
- StringBuffer는 저장할 문자열의 길이를 고려해서 적절한 크기로 생성해야 한다.
public StringBuffer(int length) {
value = new char[length];
shared = false;
}
public StringBuffer() {
this(16); // 버퍼의 길이를 지정하지 않으면 버퍼의 길이는 16이 된다.
}
public StringBuffer(String str) {
this(str.length() + 16); // 지정한 문자열의 길이보다 16 더 길게 버퍼를 생성한다.
append(str); // 길이 3
}
⦁ StringBuffer의 변경
- StringBuffer는 String과 달리 내용 변경이 가능하다.
StringBuffer sb = new StringBuffer("abc");
sb.append(“123”); // sb의 내용 뒤에 “123”을 추가한다.
(append() : 문자열 추가 / delete() : 삭제 / insert() : 삽입)
- append()는 지정된 내용을 StringBuffer에 추가 후, StringBuffer의 참조를 반환한다.
StringBuffer sb2 = sb.append("ZZ");
System.out.println(sb); // abc123ZZ
System.out.println(sb2); // abc123ZZ
⦁ StringBuffer의 비교
- StringBuffer는 equals()가 오버라이딩 되어있지 않다.
StringBuffer sb = new StringBuffer("abc");
StringBuffer sb2 = new StringBuffer("abc");
System.out.println(sb==sb2); // false
System.out.println(sb.equals(sb2)); // false
- StringBuffer를 String으로 변환 후에 equals()로 비교해야 한다.
String s = sb.toString();
String s2 = sb2.toString();
System.out.println(s.equals(s2)); // true
⦁ StringBuffer의 생성자와 메소드
* 범위 설정의 경우, 시작 index는 포함이 되고 마지막 index는 포함이 되지 않는다.
ex)
public 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());
}
}
⦁ StringBuilder (동기화x)
- StringBuffer는 동기화(데이터보호) 되어 있다. 멀티 쓰레드에 안전(thread-safe)
- 멀티 쓰레드 프로그램이 아닌 경우, 동기화는 불필요한 성능 저하
이럴 땐 StringBuffer대신 StringBuilder를 사용하면 성능 향상
(StringBuffer를 StringBuilder로 바꿔주면 된다)
⦁ Math클래스
- 수학관련 static메소드의 집합
- round()로 원하는 소수점 아래 세 번째 자리에서 반올림하기
1. 원래 값에 100을 곱한다.
90.7552 * 100 -> 9075.52
2. 위의 결과에 Math.round()를 사용한다.
Math.round(9075.52) -> 9076
3. 위의 결과를 다시 100.0으로 나눈다.
9076 / 100.0 -> 90.76
* round()는 HALF_UP(0.5에서 무조건 올림), rint()는 round even(0.5에서 짝수로 만들 수 있을때만 올림)
ex)
public class RoundTest {
public static void main(String[] args) {
double sum = 0;
double sum1 = 0;
double sum2 = 0;
for (double d = 1.5; d<=10.5; d++) {
double d1 = Math.round(d);
double d2 = Math.rint(d);
System.out.printf("%4.1f %4.1f %4.1f%n", d, d1, d2);
sum += d;
sum1 += d1;
sum2 += d2;
}
System.out.println("---------------");
System.out.printf("%4.1f %4.1f %4.1f%n", sum, sum1, sum2);
// d2의 sum 결과값이 원래값인 d의 sum과 일치함(일반 반올림보다 더 정확한 결과가 나옴)
}
}
⦁ 래퍼(wrapper) 클래스
- 8개의 기본형을 객체로 다뤄야할 때 사용하는 클래스
public final class Integer extends Number implements Comparable {
...
private int value;
...
}
⦁ Number클래스
- 모든 숫자 래퍼 클래스의 조상
(Byte, Short, Integer, Long, Float, Double, BigInteger, BigDecimal의 조상)
public abstract class Number implements java.io.Serializable {
public abstract int intValue();
public abstract long longValue();
public abstract float floatValue();
public abstract double doubleValue();
public byte byteValue() {
return (byte)intValue();
}
public short ShortValue() {
return (short)intValue();
}
}
=> 보이는 것처럼, 래퍼 객체를 기본형으로 바꿔주는 메소드들이 있다.
⦁ 문자열을 숫자로 변환하기
- 문자열을 숫자로 변환하는 다양한 방법
int i = new Integer(“100”).intValue();
int i2 = Integer.parseInt(“100”);
Integer i3 = Integer.valueOf(“100”); // 또는 Int i3 = Integer.valueOf(“100”);
* 또는 Byte b = new Byte(“100”); 처럼 생성자를 이용해서 문자열을 원하는 래퍼클래스로 변환 가능
- n진법의 문자열을 숫자로 변환하는 방법
int i4 = Integer.parseInt("100", 2); // 100(2) -> 4
int i5 = Integer.parseInt("100", 8); // 100(8) -> 64
int i6 = Integer.parseInt("100", 16); // 100(2) -> 256
int i7 = Integer.parseInt("FF", 16); // 100(2) -> 255
// int i8 = Integer.parseInt("FF"); // NumberFormatException 발생
⦁ 오토박싱 & 언박싱 – 기본형과 참조형 간의 자동형변환
int -> (오토박싱) -> Integer 자동으로 해줌
int <- (언박싱) <- Integer
- JDK1.5 이전에는 기본형과 참조형간의 연산이 불가능했음
int i = 5;
Integer iObj = new Integer(7);
int sum = i + iObj; // 에러, 기본형과 참조형 간의 덧셈 불가(JDK1.5 이전)
- 기본형의 값을 객체로 자동변환하는 것을 오토박싱, 그 반대는 언박싱
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10); // 오토박싱. 10 -> new Integer(10)
int value = list.get(0); // 언박싱. new Integer(10) -> 10
ex)
import java.util.ArrayList;
public class RoundTest2 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>(); // ArrayList는 객체만 저장가능함
list.add(new Integer(100)); // list에는 객체만 추가 가능
list.add(100); // JDK 1.5 이전에는 에러
// Integer i = list.get(0); // list에 저장된 첫 번째 객체를 꺼낸다.
// int i = list.get(0).intValue(); // intValue()로 Integer를 int로 변환
int i = list.get(0); // OK
}
}
ex)
public 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; // 참조형을 기본형으로 형변환도 가능(형변환 생략가능)
}
}
출처 - 유튜브 남궁성의 정석코딩 [자바의 정석 - 기초편]
'Java > Java의 정석' 카테고리의 다른 글
220319 Java - Chapter 11. Collections Framework Part.1 (0) | 2022.03.19 |
---|---|
220316 Java - Chapter 10. 날짜와 시간 & 형식화 (0) | 2022.03.17 |
220314 Java - Chapter 8. 예외 처리(이어서 마무리) (0) | 2022.03.14 |
220312 Java - Chapter 8. 예외 처리 (0) | 2022.03.13 |
220310 Java - Chapter 7. 객체지향개념 II Part.3 (0) | 2022.03.11 |