언어/JAVA
[JAVA] Object 클래스
hvoon
2022. 9. 8. 09:54
-사용자 정의 클래스를 생성하면서, extends(상속)을 구현하지 않으면 자동으로 java.lang.Object 클래스를 상속.
-Object 클래스는 Java 에서 사용되는 모든 클래스들의 최상위 부모클래스
-Subclass extends Super 라는 건 Subclass 는 Object 클래스를 상속하지 않지만 Super 클래스가 Object 클래스를 상속하므로, Subclass 는 Object 클래스를 상위의 상위로 상속한것과 같은 의미
class UserClass {
}
public class Extends09_Object01 {
public static void main(String[] args) {
UserClass obj = new UserClass();
// getClass 메소드는 해당 객체의 클래스 이름을 리턴해주는 메서드이며,
// Object 클래스에서 상속 받은 메서드
System.out.println( obj.getClass() );
// hashCode 메소드는 해당 객체의 해시코드값(다른객체와 구분하기위한 고유값)을
// 리턴해주는 메서드(JVM에 의해서 관리되고 있는 번호)
System.out.println( obj.hashCode() );
// toString 메소드는 해당 객체의 정보를 문자열로 리턴해주는 메서드
System.out.println( obj.toString() );
// 객체의 클래스명 + '@' + 해시코드값(16진수)
System.out.println( obj );
//System.out.println(obj.toString()); 와 같음
}
}
toString 메소드의 사용
-toString 메소드는 클래스의 객체 정보를 문자열로 반환 :
-객체의 클래스명 + '@' + 해시코드값(16진수)
-사용자 정의 클래스(직접 개발한 클래스)에 toString 메소드를 오버라이딩하여 클래스의 정보를 문자열로 제공하도록 변형(재정의) 가능
class UserClassB { // toString 메서드를 오버라이딩 하지 않은 클래스
}
class Point { // toString 메서드를 오버라이딩한 클래스
private int x;
private int y;
public Point(int x, int y) {this.x = x; this.y = y;}
public String toString() {
return "(x=" + this.x + ", y=" + this.y + ")";
// "x = 값, y = 값" 리턴
}
}
public class Extends09_Object02 {
public static void main(String[] args) {
UserClassB obj1 = new UserClassB();
UserClassB obj2 = new UserClassB();
System.out.println("오버라이딩 되지 않은 toString() => " + obj1.toString());
System.out.println("오버라이딩 되지 않은 toString() => " + obj2);
Point p = new Point(30,20);
System.out.println("오버라이딩 된 toString() => " + p.toString());
// .toString() 은 print 에서 사용되거나 다른 문자열과 '+' 연산될 때 생략 가능
// System.out.println("오버라이딩 된 toString()=>" + p);
String msg = "Point => " + p; //String msg = "Point => " + p.toString();
System.out.println(msg);
}
}
Object 클래스의 equals 메소드
-객체간의 비교를 위해서 사용되는 메서드
-Object 가 상속한 메서드들 중 toString과 함꼐 가장 많이 오버라이딩 되는 메서드
public class Extends09_Object03 {
public static void main(String[] args) {
// 일반적, 기본 자료형들의 갑의 비교는 비교연산자(==)를 사용
int n1 = 10;
int n2 = 10;
if( n1 == n2 ) System.out.println("n1 변수와 n2 변수는 같습니다.");
else System.out.println("n1 변수와 n2 변수는 다릅니다.");
String s1 = "Hello";
String s2 = "Hello";
if( s1 == s2 ) System.out.println("s1 변수와 s2 변수는 같습니다.");
else System.out.println("s1 변수와 s2 변수는 다릅니다.");
System.out.println(s1); // "Hello"출력
// 이미 String 클래스에는 저장된 문자가 리턴되는 toString() 메서드가 오버라이딩 되어 있음
// == 연산은 변수가 직접 저장한 값으로 비교해주는 연산자라는 것을 감안하면
// s1==s2 는 두개의 참조변수값(주소값)이 비교되었다라는것을 알 수 있음
// 현재의 s1 과 s2 는 같은 주소를 갖고 있다는 말이기도 함
// String s1 = "Hello"; 실행시에 HEAP 영역에 Hello 가 저장되고 그 주소가 s1 변수에 저장
// String s2 = "Hello"; 실행시에는 새로운 영역에 Hello 가 저장되는게 아니라
// 이미 존재하는 Hello 의 주소를 s2 에 또 저장
// 이는 모두 new 키워드가 없어서 새로운 공간이 안생겼기때문에 일어나는 현상
// 물론 s1 = "world"; 라는 새로운 글자를 저장하면 s2는 그데로 있고 새로운 공간에
// "world" 가 저장되고 그 주소를 s1이 저장하긴 함
String s3 = new String("Hello");
String s4 = new String("Hello");
if( s3 == s4 ) System.out.println("s3 변수와 s4 변수는 같습니다.");
else System.out.println("s3 변수와 s4 변수는 다릅니다.");
// 앞선 명령과 달리 이번엔 new 키워드를 사용하여 서로 다른 공간에 Hello 를
// 저장하고 각각의 주소를 s3 와 s4 에 저장
// 결국 (==) 이 연산자는 글자들의 비교가 아니라, 레퍼런스 주소들의 비교라는 의미
// 실제 객체의 값을 비교하기 위한 equals 메소드를 사용하면 참조값이 서로 다른
// 객체의 실제 데이터를 비교하여 동일한 데이터를 가지고 있는지 확인 가능.
if( s3.equals(s4) )
System.out.println("s3 변수와 s4 변수는 같습니다.(equals)");
else
System.out.println("s3 변수와 s4 변수는 다릅니다.(equals)");
// Object 클래스에서 상속받은 equals 메서드를 사용한것이고, String 클래스에 맞게
// 오버라이딩되어 있기때문에 글자끼지 비교
// 오버라이딩 되기 전의 equals 도 참조값끼리 비교
// 같은 패키지안의 다른 파일에 있는 클래스의 객체생성이 자유롭게 가능
Point p1 = new Point(10, 20);
Point p2 = new Point(10, 20);
if( p1.equals(p2) )
System.out.println("p1 변수와 p2 변수는 같습니다.(equals)");
else
System.out.println("p1 변수와 p2 변수는 다릅니다.(equals)");
// equals 를 오버라이딩 하지 않은 클래스의 객체간 equals 매서드 사용은
// 참조값들끼리 비교하는 결과를 얻음
}
}
class Human{
private String name;
private int age;
public Human(String name, int age) {
this.name = name; this.age = age;
}
public String toString() {
String info = "name = " + this.name + ", ";
info += "age = " + this.age;
return info; // "name = 홍길동, age=26"
}
// s1.equals(s2) this <- s1 obj<-s2
public boolean equals( Object obj ) {
// 매개변수로 Human 이 아닌 이상한 클래스의 객체가 왔으면 그냥 바로 return false (메서드 종료)
if( !(obj instanceof Human) )
return false;
Human target = (Human)obj;
boolean flag_name = this.name.equals(target.name);
boolean flag_age = this.age == target.age;
boolean result = flag_name && flag_age;
return result;
}
}
public class Extends09_Object04 {
public static void main(String[] args) {
Human s1 = new Human("홍길동", 21);
Human s2 = new Human("홍길동", 21);
Human s3 = new Human("홍길서", 22);
System.out.println("Human1의 정보 : " + s1);
System.out.println("Human2의 정보 : " + s2);
System.out.println("Human3의 정보 : " + s3);
if( s1 == s2 )
System.out.println("s1 변수와 s2 변수는 같습니다.(s1==s2)");
else
System.out.println("s1 변수와 s2 변수는 다릅니다.(s1==s2)");
if( s1.equals(s2) )
System.out.println("s1 변수와 s2 변수는 같습니다.(s1.equals(s2))");
else
System.out.println("s1 변수와 s2 변수는 다릅니다.(s1.equals(s2))");
}
}
Vector
-배열의 확장형구조(리스트)-객체들을 저장할 수 있는 배열
-사용자가 만든 클래스 객체의 레퍼런스값을 저장하는 다형성 객체 저장 리스트
import java.util.Vector;
//상품과 구매자를 클래스로 만들고 구매, 환불 등의 동작을 매서드로 제작
class Product{
int price;
int bonusPoint; // 상품을 구매했을때 구매자에게 부여된 보너스 포인트
// Product(){}
Product(int p){
this.price = p;
this.bonusPoint = p/10;
}
}
class Computer extends Product{
Computer(){
super(150);
// 부모클래스의 생성자가 디폴트가 아니면, 현재 있는 생성자에 맞춰서 호출해야함
}
public String toString() {
return "Computer";
}
}
class Tv extends Product{
Tv(){ super(100); }
public String toString() { return "Tv"; }
}
class Audio extends Product{
Audio(){ super(60); }
public String toString() { return "Audio"; }
}
class Buyer{
int money = 1000; // 구매자가 소지한 금액
int bonusPoint = 0; // 물건을 구매해서 얻은 보너스포인트
Vector item = new Vector(); // 구매목록
// Computer c = new Computer();
// item.add(c);
//public void buy(Tv t) { item.add(t); }
//public void buy(Computer c) { item.add(c); }
//public void buy(Audio a) { item.add(a); }
// 부모클래스의 레퍼런스 변수에는 자식인스턴스의 주소를 저장할 수 있음 (자동 캐스팅)
public void buy( Product p ) {
// 부모클래스의 레퍼런스변수에 저장된 자식클래스 객체에서 물려준 멤버들,
// 오버라이딩된 멤버들에 접근이 가능
// 전달된 제품을 구매할정도의 잔액이 충분한가
if( this.money < p.price ) {
System.out.println("잔액이 부족합니다");
return;
}
this.money -= p.price;
// 제품의 bonusPoint 를 Buyer 의 bonusPoint 에 가산
this.bonusPoint += p.bonusPoint;
System.out.println( p + "을 구입하셨습니다" );
// p(부모클래스의 레퍼런스 변수)로 오버라이딩된 toString()을 사용
// 제품 객체를 item 리스트객체에 추가
item.add(p);
// Vector 클래스의 멤버메서드add 의 생김새 - 매개변수가 Object 형이어야 뭐든 전달 가능
// public void add( Object obj ){ }
}
public void summary() {
int sum = 0; // 지출 총액 변수
String itemList = ""; // 구매 목록 변수.
if( item.isEmpty() ) {
// item.isEmpty() :Vector 객체인 item 이 비어 있으면 true 리턴하는 메서드
System.out.println("구입하신 제품이 없습니다");
return;
}
for( int i=0; i<item.size(); i++) {
// item.size() : 저장된 요소의 갯수 리턴합니다
// item 에 저장됬던 걸 읽어내서 Product 형 변수에 담음
Product p = (Product)item.get(i);
// 부모레퍼런스변수에 저장됬던 자식인스턴스의 주소값이, 다시 자식레퍼런스에
// 전달되려면 강제 캐스팅이 필요
sum += p.price; // 구입금액 합산
itemList = itemList + p + " " ; // 구매상품이름 이어붙임
}
System.out.println("지출총액 : " + sum + ", 구매목록 : " + itemList);
// Product p = (Product)item.get(i);
// get메서드는 꺼내고 지우고동작이 아니라 읽어내는 동작.
// 따라서 get이 실행된다고 리스트에서 지워지는건 아님
}
public void refund( Product p ) {
// item.remove(p) : item에서 p를 삭제 - 참조값(주소)로 검색해서 삭제
// 삭제가 잘 되었다면 true 를 리턴해주는 메서드
if( item.remove(p) ) {
// buyer 잔액에 상품 가격 합산
money += p.price;
// 보너스 포인트 차감
bonusPoint -= p.bonusPoint;
// 환불 상품안내 "~~를 반품하셨습니다"
System.out.println(p + "을/를 반품하셨습니다.");
}else {
System.out.println("구입하신 물품중에 해당 제품이 없습니다");
}
}
}
public class Extends09_Object05 {
public static void main(String[] args) {
Tv t = new Tv();
Computer c = new Computer();
Audio a = new Audio();
System.out.println(t); // toString() 메서드가 오버라이딩되면, 생략해도 호출됨
System.out.println(c);
System.out.println(a);
Buyer b = new Buyer();
b.buy(c);
b.buy(a);
b.buy(t);
b.summary();
b.refund(c);
b.summary();
}
}