모든 클래스의 최고 조상. 오직 11개의 메서드만을 가지고 있다.
따라서 자바의 모든 클래스는 Object 클래스의 모든 메소드를 바로 사용할 수 있습니다.
메소드 | 설명 |
---|---|
protected Object clone() | 해당 객체의 복제본을 생성하여 반환함. |
boolean equals(Object obj) | 해당 객체와 전달받은 객체가 같은지 여부를 반환함. |
protected void finalize() | 해당 객체를 더는 아무도 참조하지 않아 가비지 컬렉터가 객체의 리소스를 정리하기 위해 호출함. |
Class getClass() | 해당 객체의 클래스 타입을 반환함. |
int hashCode() | 해당 객체의 해시 코드값을 반환함. |
void notify() | 해당 객체의 대기(wait)하고 있는 하나의 스레드를 다시 실행할 때 호출함. |
void notifyAll() | 해당 객체의 대기(wait)하고 있는 모든 스레드를 다시 실행할 때 호출함. |
String toString() | 해당 객체의 정보를 문자열로 반환함. |
void wait() | 해당 객체의 다른 스레드가 notify()나 notifyAll() 메소드를 실행할 때까지 현재 스레드를 일시적으로 대기(wait)시킬 때 호출함. |
void wait(long timeout) | 해당 객체의 다른 스레드가 notify()나 notifyAll() 메소드를 실행하거나 전달받은 시간이 지날 때까지 현재 스레드를 일시적으로 대기(wait)시킬 때 호출함. |
void wait(long timeout, int nanos) | 해당 객체의 다른 스레드가 notify()나 notifyAll() 메소드를 실행하거나 전달받은 시간이 지나거나 다른 스레드가 현재 스레드를 인터럽트(interrupt) 할 때까지 현재 스레드를 일시적으로 대기(wait)시킬 때 호출함. |
Car car01 = new Car();
Car car02 = new Car();
Car car03 = new Car();
Car car04 = new Car();
System.out.println(car01.equals(car02)); // false (서로 다른 주소 가리킴)
car03 = car04; // 두 참조 변수가 같은 주소를 가리킴.
System.out.println(car03.equals(car04)); // true (서로 같은 주소 가리킴)
equals( )메서드는 보통 하위 클래스에서 재정의를 통해 논리적으로 동등한지 비교할때 사용됨
만약 객체만을 비교하는 것이 아닌 멤버변수의 값을 비교하기 위해서는 equals메서드를 아래와 같이 오버라이딩 해야한다.
@Override
public boolean equals (Object obj) {
if (obj instanceof Member) {
Member member = (Member) obj;
if(id.equals(member.id)) {
return true;
}
}
return false;
}
실습
class INum extends Object{
private int num;
INum(int num){
this.num = num;
}
public int getNum() {
return num;
}
@Override
public boolean equals(Object obj) { // Object에 있는 equals 메소드를 오버리이딩 함
// ----------- object를 통한 형변환
if (obj instanceof INum) { // obj가 INum을 인스턴스 했을때만 사용할수 있도록 함
INum n = (INum) obj; // 다운 캐스팅
if (this.num == n.getNum()) { // this를 통해 기존 객체(obj1)의 인스턴스변수를 불러오고 c1.getRadius를 통해 obj2의 인스턴스변수를 불러와 비교한다.
return true;
} else {
return false;
}
}return false;
}
}
public class EqualsObject {
public static void main(StringTest[] args) {
INum num1 = new INum(10);
INum num2 = new INum(12);
INum num3 = new INum(10);
if(num1.equals(num2))
System.out.println("num1, num2 내용 동일하다.");
else
System.out.println("num1, num2 내용 다르다.");
if(num1.equals(num3))
System.out.println("num1, num3 내용 동일하다.");
else
System.out.println("num1, num3 내용 다르다.");
}
}
------------- 결과 -------------
num1,num2 내용 다르다
num1,num3 내용 동일하다
오버라이딩
해야 한다.String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1.equals(str2)); // true
System.out.println(str1.hashCode()); // 96354
System.out.println(str2.hashCode()); // 96354
System.out.println(System.identityHashCode(str1)); // 2003749087
System.out.println(System.identityHashCode(str2)); // 1324119927
String클래스는 문자열 내용이 같으면, 동일한 해시코드를 반환하도록 hashCode메서드가 오버라이딩이 되어 있어 str1과 str2에 대해 hashCode( )를 호출하면 항상 동일한 해시코드값을 얻음
반면에, System.identityHashCode는 Object클래스의 hashCode( )메서드처럼 객체의 주소값으로 해시코드를 작성하기 때문에 항상 객체마다 다른 해시코드값을 반환하도록 하여 str1과 str2는 해시코드는 같지만 서로 다른 객체라는 것을 알 수 있다.
객체를 문자열로 변환하기 위한 메서드
반환되는 문자열은 클래스 이름과 함께 구분자로 '@'가 사용되며, 그 뒤로 16진수 해시 코드(hash code)가 추가된다.
public String toString(){
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
--------------------
getClass( ) : 설계도 객체
getName( ) : 클래스 이름
"@" : at 위치
Integer.toHexString : 16진수
hashCode() : 객체 주소
toString( ) 오버라이딩 사용 전
class Card{
String kind;
int number;
Card(){
this("SPADE",1);
}
Card(String kind, int number){
this.kind = kind;
this.number = number;
}
}
public class tostring {
public static void main(String[] args) {
System.out.println(new Card().toString());
System.out.println(new Card().toString());
}
}
-------- 결과 --------
Card@4eec7777
Card@3b07d329
오버라이딩을 하지 않았기 때문에 Object클래스의 toString( )이 호출되어 클래스이름 + 해시코드가 출력이 되었다.
따라서, 문자열로 출력시키기 위해서는 오버라이딩을 해야하는데
public String toString(){
return "kind :" + kind + ", number : " + number;
}
이와 같이 Object클래스에 정의된 toString( )을 오버라이딩하게 되면 문자열로 변환하여 반환되는것을 확인 할 수 있다.
toString( ) 오버라이딩 사용 후
class Card{
String kind;
int number;
Card(){
this("SPADE",1);
}
Card(String kind, int number){
this.kind = kind;
this.number = number;
}
public String toString(){ // Object클래스 toString( ) 오버라이딩
return "kind : "+kind+", number :"+number;
}
}
public class tostring {
public static void main(String[] args) {
Card c1 = new Card();
Card c2 = new Card("Heart",10);
System.out.println(c1.toString());
System.out.println(c2.toString());
}
}
-------- 결과 --------
kind : SPADE, number :1
kind : Heart, number :10
해당 인스턴스를 복제하여, 새로운 인스턴스를 생성해 반환한다.
원본 객체를 안전하게 보호하며 복사한 객체로 작업진행한다.
Cloneable 인터페이스
를 구현한 클래스에서만 clone( )을 호출할 수 있다.
class Point implements Cloneable{ // Cloneable 인터페이스를 구현한다
int x,y;
Point(int x, int y){ // 생성자
this.x = x;
this.y = y;
}
@Override
public String toString(){ // toString() 오버라이딩
return "x=" + x + ", y=" + y;
}
public Object clone(){
// Object클래스의 clone()의 접근제어자 protected 에서 public으로 변경
Object obj = null;
try{ // clone()은 반드시 예외처리를 해줘야 한다.
obj = super.clone(); // 조상클래스의 clone()을 호출
}catch(CloneNotSupportedException e){ }
return obj;
}
}
public class CloneEx {
public static void main(String[] args) {
Point original = new Point(3,5);
Point copy = (Point)original.clone(); // 복제해서 새로운 객체 생성
System.out.println(original);
System.out.println(copy);
}
}
-------- 결과 --------
x=3, y=5
x=3, y=5
불변 클래스
(1) 불변 클래스
String a = "a"; ---- (1)
String b = "b"; ---- (2)
a = a + b; ---- (3)
※ 내용을 변경할 수 없으므로 새로운 문자열 객체가 만들어짐(계속 새로 생겨 성능이 떨어짐)
(2) 문자열 리터럴
String str1 = "abc"; // 문자열 리터럴 "abc"의 주소가 str1에 저장됨
String str2 = "abc"; // 문자열 리터럴 "abc"의 주소가 str2에 저장됨
String str3 = new String("abc"); // 새로운 String인스턴스를 생성
String str4 = new String("abc"); // 새로운 String인스턴스를 생성
(3) 빈 문자열(””, empty string)
String s = " "; // 빈 문자열로 초기화
char c = ' '; // 공백으로 초기화
주어진 문자열을 갖는 String인스턴스를 생성한다
Char → String
char[] c = {'H','e','l','l','o'};
string s = new String(c);
---- 결과 ----
s = "Hello"
해당 문자열의 특정 인덱스에 해당하는 문자를 반환한다.
만약 해당 문자열의 길이보다 큰 인덱스나 음수를 전달하면, IndexOutOfBoundsException 오류가 발생한다.
String str = new String("Java");
System.out.println("원본 문자열 : " + str);
for (int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(i) + " ");
}
System.out.println("\ncharAt() 메소드 호출 후 원본 문자열 : " + str);
---- 결과 ----
원본 문자열 : java
J A V A
charAt()메소드 호출 후 원본 문자열 : Java
해당 문자열을 인수로 전달된 문자열과 사전 순서로 비교한다.
문자열 비교시 대소문자를 구분하여 비교한다.
두 문자열이 같다면 0을 반환하고 해당 문자열이 인수로 전달된 문자열보다 작으면 음수를, 크면 양수를 반환한다.
※ 문자열 비교시 대소문자를 구분하지 않기를 원하면 compareTognoreCase( )메소드 사용
String str = new String("abcd");
System.out.println("원본 문자열 : " + str);
System.out.println(str.compareTo("bcef"));
System.out.println(str.compareTo("abcd") + "\n");
System.out.println(str.compareTo("Abcd"));
System.out.println(str.compareToIgnoreCase("Abcd"));
System.out.println("compareTo() 메소드 호출 후 원본 문자열 : " + str);
---- 결과 ----
원본 문자열 : abcd
-1 abcd < bcef
0 abcd == abcd
32 abcd < Abcd (대문자 이므로 32 = A)
0 abcd == Abcd
compareTo() 메소드 호출 후 원본 문자열 : abcd
해당 문자열의 뒤에 인수로 전달된 문자열을 추가한 새로운 문자열을 반환한다.
문자열을 뒤에 덧붙인다.
String str = new String("Java");
System.out.println("원본 문자열 : " + str);
System.out.println(str.concat("수업"));
System.out.println("concat() 메소드 호출 후 원본 문자열 : " + str);
---- 결과 ----
원본 문자열 : Java
Java수업
concat() 메소드 호출 후 원본 문자열 :Java
지정된 문자열이 포함되어있는지 검사한다.
String s = "abcedfg";
boolean b = s.contains("bc");
---- 결과 ----
true
<br>
해당 문자열에서 특정 문자나 문자열이 처음으로 등장하는 위치의 인덱스를 반환한다.
찾지 못하면 -1을 반환한다.
String str = new String("Oracle Java");
System.out.println("원본 문자열 : " + str);
System.out.println(str.indexOf('o'));
System.out.println(str.indexOf('a'));
System.out.println(str.indexOf("Java"));
System.out.println("indexOf() 메소드 호출 후 원본 문자열 : " + str);
---- 결과 ----
원본 문자열 : Oracle Java
-1
2
7
indexOf() 메소드 호출 후 원본 문자열 : Oracle Java
해당 문자열의 맨 앞과 맨 뒤에 포함된 모든 공백 문자를 제거해 준다.
String str = new String(" Java ");
System.out.println("원본 문자열 : " + str);
System.out.println(str + '|');
System.out.println(str.trim() + '|');
System.out.println("trim() 메소드 호출 후 원본 문자열 : " + str);
---- 결과 ----
원본 문자열 : Java
Java |
Java|
trim() 메소드 호출 후 원본 문자열 : Java
문자열을 지정된 분리자로 나누어 문자열 배열에 담아 반환한다.
String animals = "dog,cat,bear";
String[] arr = animals.split(",")
---- 결과 ----
arr[0] = "dog"
arr[1] = 'cat"
arr[2] = "bear"
toLowerCase() : 해당 문자열의 모든 문자를 소문자로 변환시켜 줍니다.
toUpperCase() : 해당 문자열의 모든 문자를 대문자로 변환시켜 줍니다.
String str = new String("Java");
System.out.println("원본 문자열 : " + str);
System.out.println(str.toLowerCase());
System.out.println(str.toUpperCase());
System.out.println("두 메소드 호출 후 원본 문자열 : " + str);
---- 결과 ----
원본 문자열 : Java
java
JAVA
두 메소드 호출 후 원본 문자열 : Java
주어진 문자열로 시작하는지 검사한다.
String s = "java.lang.Object"
boolean b = s.startsWith("java");
boolean b2 = s.startsWith("lang");
---- 결과 ----
b = true
b2 = false
주어진 시작위치부터 끝 위치 범위에 포함된 문자열을 얻는다. 이 때, 시작위치의 문자는 범위에 포함되지만, 끝 위치의 문자는 포함되지 않는다.(begin <= x < end)
String s = "java.lang.Object"
String c = s.substring(10);
String p = s.substring(5,9);
---- 결과 ----
c = "Object"
p = "lang"
String b = String.valueOf(true);
String c = String.valueOf('a');
String i = String.valueOf(100);
String l = String.valueOf(100L);
String d = String.valueOf(10.0);
---- 결과 ----
b = "true"
c = "a"
i = "100"
l = "100"
d = "10.0"
String animals = "dog, cat, bear";
String[] arr = animals.split(","); // 문자열을 ','를 구분자로 나눠서 배열에 저장
String str = String.join("-",arr); // 배열의 문자열을 '-'로 구분해서 결합
System.out.println(str); // dog-cat-bear
숫자를 문자열로 바꾸는 방법
int i = 100;
String str1 = i + ""; // 100을 "100"으로 변환하는 방법1 (편리함)
String str2 = String.valueOf(i); // 100을 "100"으로 변환하는 방법2 (속도 빠름)
문자를 숫자로 바꾸는 방법
int i = Integer.parseInt("100"); // "100"을 100으로 변환하는 방법1
int i2 = Integer.valueOf("100"); // "100"을 100으로 변환하는 방법2
int i3 = Integer.valueOf("100"); // 원래는 반환 타입이 Integer
---- 설명 ----
원래는 각 형별로
int => parseInt()
long => parseLong()
double => parseDouble()
각각 사용하여 변환했는데 이제는 valueOf()로 통일되어 하나로 사용 가능
String처럼 문자형 배열을 내부적으로 가지고 있다.
값을 바꾸지 못하는 불변인 String과 반대로 값을 변경할 수 있다.
StringBuffer sb = new StringBuffer("abc");
배열의 경우 길이를 변경할 수 없다. 따라서 공간이 부족하면 새로운 배열을 생성해야하는데
(1) 새로운 배열 생성
(2) 기존의 배열을 새로운 배열로 복사
(3) 기존의 배열의 주소를 가르키던 참조를 새로운 배열의 주소로 변경
위와 같은 방식으로 구현을 할 수 있다. 하지만, 성능이 떨어지므로 StringBuffer를 통해사용가능
sb.append("123"); // sb의 내용 뒤에 "123"을 추가함
append( )는 지정된 내용을 StringBuffer에 추가 후, StringBuffer의 참조를 반환
즉, 배열의 3가지 방식을 한번에 구현해줌
StringBuffer sb = new StringBuffer("abc");
sb.append("123"); // abc123 => sb.append("123").append("ZZ") 형식으로 사용도 가능
sb.append("ZZ"); // abc123ZZ
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
실습
public class stringbuffer {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("01"); // sb 객체에 01대입
StringBuffer sb2 = sb.append(23); // sb객체 끝에 23 추가(sb2가 sb객체 주소 가리킴)
sb.append('4').append(56);
StringBuffer sb3 = sb.append(78); // sb객체 끝에 78추가(sb3가 sb객체 주소 가리킴)
sb3.append(9.0); // sb객체 끝에 9.0 추가
System.out.println("sb ="+sb);
System.out.println("sb2 ="+sb2);
System.out.println("sb3 ="+sb3);
System.out.println("sb ="+sb.deleteCharAt(10)); // 10번 index 값 지움
System.out.println("sb ="+sb.delete(3,6)); // 3<= index < 6번 index 값 지움
System.out.println("sb ="+sb.insert(3,"abc")); // index가 3인곳에 추가
System.out.println("sb ="+sb.replace(6,sb.length(),"END")); // 6 <= index <11 사이의 값 바꿈
System.out.println("capacity ="+sb.capacity()); // 배열 길이
System.out.println("length ="+sb.length()); // 문자열 개수
}
}
int i = nwe Integer(100).intValue(); // inValue()를 붙여 기본형으로 변환
int i = new Integer("100").intValue();
모든 숫자 래퍼 클래스의 조상
int i = 5; int i = 5;
Integer iobj = new Integer(7); => Integer iobj = new Integer(7);
int sum = i + iobj; int sum = i + iobj.intValue(); // 컴파일러가 자동으로 형변환
실습
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(100); // 오토박싱 (기본형 -> 객체)
// list에는 객체만 추가가 가능함 즉, new Integer(100)이 들어가야 하지만 컴파일러가 자동 형변환 해줌 list.add(new.Integer(100));
Integer i = list.get(0);
int a = list.get(0); // 언박싱(객체 -> 기본형)
// list는 객체만 가지고 있기 때문에 객체를 반환해줘서 기본형으로 받기 위해서는 형변환이 필요함 list.get(0).intValue();