본문 바로가기

일/JAVA

java11.basic_API

API관련 수업내용도 너무 길어서

나눠서 올려야지,,,

공부할게 잔뜩 ㅜ

/*

객체비교(객체.equals(Object object))

 

equals 메서드는 매개타입인 Object인데 이것은 모든 객체가 매개값을 대입될 수

있다는 것이다. 그 이유는 Object가 최상위 클래스이므로 모든 객체는 Object타입

으로 자동형변환 될 수 있기 때문이다.

 

java에서는 두 객체를 비교할 때 동등연산자(==)가 아니라 equals()메서드를 사용한다

두 객체를 비교해서 논리적으로 동등하면 true, 아니면 false를 리턴한다.

 

equals 메서드를 재정의할 때 매개값(비교객체)이 기준 객체와 동일한 타입의 객체

인지를 먼저 확인해야 한다. Object타입의 매개변수는 모든 객체가 매개값으로 사용될

수 있기 때문이다.

*/

public class Member {

public String id;

public Member(String id) {

this.id = id;

}

@Override

public boolean equals(Object obj) {

if(obj instanceof Member) {

Member member = (Member) obj;

if(id.equals(member.id)) {

return true;

}

} else {

System.out.println("Member참조타입이 아닙니다");

}

return false;

}

}

public class MemberMain {

 

public static void main(String[] args) {

Member member1 = new Member("hong");

Member member2 = new Member("hong");

Member member3 = new Member("kim");

System.out.println("member1 = " +member1.hashCode());

System.out.println("member2 = " +member2.hashCode());

System.out.println("member3 = " +member3.hashCode());

 

System.out.println(member1.equals(member2)); // 같은 hong이라 true 예상하지만 hashCode가 다르기에 false

System.out.println(member1.equals(member3)); //

System.out.println();

 

if(member1.equals(member2)) {

System.out.println("같은 객체입니다");

}else {

System.out.println("다른 객체입니다");

}if(member1.equals(member3)) {

System.out.println("같은 객체입니다");

}else {

System.out.println("다른 객체입니다");

}if(member1.equals(new Dog())) {

System.out.println("같은 객체입니다");

}else {

System.out.println("다른 객체입니다");

}

}

}

class Dog{}

/*

객체의 해쉬코드(hashCode)

객체의 해쉬코드란?객체를 식별하는 하나의 정수값을 말한다. Object의 hashCode()

메서드는 객체의 메모리번지를 이용햇 해쉬코드를 만들어 리턴하기 때문에 객체마다

달느 값을 가지고 있다. 논리적으로 동등비교시에 hashCode()를 재정의(오버라이드)

할 필요성이 있는 Collection FrameWork에서 HashSet, HashMap, HashTable()은 equals

메서드를 이용해서 비교한다

*/

public class Key {

public int number;

 

public Key(int number) {

this.number = number;

}

 

@Override

public int hashCode() {

return this.number;

}

@Override

public boolean equals(Object obj) {

if(obj instanceof Key) {

Key key = (Key) obj;

if(this.number==key.number) {

return true;

}

}

return false;

}

}

public class KeyMain {

 

public static void main(String[] args) {

Object object1 = 0;

Object object2 = 0;

Object object3 = "0";

Object object4 = new String("0");

 

System.out.println(object1.hashCode());

System.out.println(object2.hashCode());

System.out.println(object3.hashCode());

System.out.println(object4.hashCode());

System.out.println();

 

System.out.println(object1 == object2);

System.out.println(object1 == object3);

System.out.println(object1 == object4);

System.out.println();

 

System.out.println(object1.equals(object2));

System.out.println(object1.equals(object3));

System.out.println(object1.equals(object4));

System.out.println();

 

System.out.println(object1.toString());

System.out.println(object2.toString());

System.out.println(object3.toString());

System.out.println(object4.toString());

System.out.println();

 

Key key1 = new Key(0);

Key key2 = new Key(0);

 

System.out.println(key1.hashCode());

System.out.println(key2.hashCode());

System.out.println();

 

System.out.println(key1==key2);

System.out.println(key1.equals(key2)); // 객체를 비교할 때는 hashCode먼저 비교

System.out.println(key1.toString());

System.out.println(key2.toString());

System.out.println(key1.hashCode() == key2.hashCode());

 

 

}

}

/*

객체의 문자정보(toString())

Object클래스의 toString()메서드는 객체의 문자정보를 리턴한다.

객체의 문자정보란 객체를 문자열로 표현한 값을 말한다. 기본적으로

Object.toString()메서드는 "클래스명@16진수해쉬코드"로 구성된 문자열을

리턴한다.

 

Object.toString() 메서드의 리턴값은 실제적으로는 별 의미가 없는 정보

이기 때문에 하위 클래스에서는 Object.toString()메서드를 재정의해서 간결

하고도 유익한 정보를 리턴하도록 한다.

 

예를 들어 재정의 된 java.util.Date.toString()메서드를 보면 현재의 시스템

날짜와 시간정보를 리턴한다. 그리고 String클래스의 toString()메서드는 저장

하고 있는 문자열을 리턴한다.

*/

깊은 복제와 얕은 복제.

/*

객체의 복제(clone())

 

객체복제는 원본개겣의 필드값과 동일한 값을ㄹ 가지는 새로운 객체를 생성하는 것을 말한다.

객체를 복제하는 이유는 원본객체를 아넌하게 보호하기 위해서이다..

 

신뢰하징낳은 영역으로 원본객체를 넘겨서 작업할 경우 원본객체의 데이터가 훼손될 수 있기

때문에 복제된 객체를 만들어 신뢰하지 않는 영역으로 넘기는 것이 복제된 객체의 데이ㅓ

터가 변경되더라도 원본객체는 아무런 영향을 받지 않기 때문에 안전하게 데이털를 보호할 수

있게 된다.

 

Object.clone()메서드는 자신과 동일한 필드값ㄷ을 가진 얕은 복제된 객체를 리턴한다.

clone()메서드로 객체를 복제하려면 원본객체는 반드시 java.lang.Cloneable인터페이스를

구현하고 있어야 한다.클래스 설계자가 복제허용하지 않도록 한다면 Cloneable 인터페이스를

구현하지 않으면 된다.

 

객체를 복제하는 방법은 얕은 복제와 깊은 복제가 있다.

 

1. 얕은 복제(shallow clone)

얕은 복제란 단순히 필드값을 복사해서 객체를 복제하는 것을 말한다. 필드값만 복제하기

때문에 필드가 기본타입일 경우는 값의 복사가 일어나고 참조타입일 경우는 객체의 메모리

번지가 복사된다.

2. 깊은 복제(deep clone)

얕은 복제의 경우 참조필드는 메모리번지만 복제가 되기 때문에 원본 객체의 필드와 복제

객체의 필드는 같은 메모리 주소를 참조한 동일 객체를 참조하게 된다. 만일, 본체객체에서

참조객체를 변경하면 원본객체도 변경된 객체를 참조하게 된다.

 

이것이 얕은 복제의 문제이다. 이 문제를 보완하기 위해 깊은 복제를 하게 되는데 깊은

복제란 참조하고 있는 객체도 복제하는 것을 말한다. 깊은 복제를 하려면 Object.clone

메서드를 재정의해서 참조객체를 복제하는 코드를 직접 작성해야 한다.

 

*/

 

public class Member implements Cloneable{

public String name; // 예외적으로 깊은 복제를 하게 구성되어 있다

public int age;

public int[] scores;

public Car car;

 

public Member(String name, int age, int[] scores, Car car) {

super();

this.name = name;

this.age = age;

this.scores = scores;

this.car = car;

}

public Member getMember() {

Member cloned = null;

try {

cloned = (Member)clone(); // super. 있고 없고의 차이

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

return cloned;

}

@Override

protected Object clone() throws CloneNotSupportedException {

// 1. 먼저 얕은 복제 : name, age, scores, car

Member cloned = (Member) super.clone(); // Object.clone() 즉, 얕은 복제

 

// 2. 참조타입을 깊은 복제 : scores, car

cloned.scores = Arrays.copyOf(this.scores, this.scores.length);

cloned.car = new Car(this.car.model);

return cloned;

}

 

 

}

class Car{

public String model;

public Car(String model) {

this.model = model;

}

}

public class MemberMain {

 

public static void main(String[] args) {

// 1. 원본객체 생성

Member org_member = new Member("홍길동", 40, new int[] {90,88,99}, new Car("포르쉐 911"));

 

// 2. 복제객체 생성 후에 참조타입객체의 값을 변경

Member clone_member = org_member.getMember();

System.out.println("원본 scores = "+org_member.scores.hashCode());

System.out.println("복제 scores = "+clone_member.scores.hashCode());

System.out.println("원본 car = "+org_member.car.hashCode());

System.out.println("복제 car = "+clone_member.car.hashCode());

System.out.println();

 

clone_member.scores[0] = 100;

clone_member.car.model = "벤츠 s500";

 

System.out.println("[복제객체의 필드 값]");

System.out.println("이름 = " + clone_member.name);

System.out.println("나이 = " + clone_member.age);

System.out.println("점수 = {");

for(int i=0; i<clone_member.scores.length;i++) {

System.out.println(clone_member.scores[i]);

System.out.println(i==(clone_member.scores.length)?"":",");

}

System.out.println();

System.out.println("자동차= " +clone_member.car.model);

System.out.println();

 

System.out.println("[원본객체의 필드 값]");

System.out.println("이름 = " + org_member.name);

System.out.println("나이 = " + org_member.age);

System.out.println("점수 = {");

for(int i=0; i<org_member.scores.length;i++) {

System.out.println(org_member.scores[i]);

System.out.println(i==(org_member.scores.length)?"":",");

}

System.out.println();

System.out.println("자동차= " +org_member.car.model);

}

 

}

public class Member implements Cloneable{

// implements Cloneable : 이 객체는 복제가능하다라는 의미

public String id;

public String name;

public String password;

public int age;

public boolean adult;

public int[] scores = {90,88,92};

 

public Member(String id, String name, String password, int age, boolean adult) {

this.id = id;

this.name = name;

this.password = password;

this.age = age;

this.adult = adult;

}

public Member getMember(){

Member cloned = null;

try {

cloned = (Member) super.clone();

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

return cloned;

}

 

}

public class MemberMain {

 

public static void main(String[] args) {

 

// 1. 원본객체

Member org_member = new Member("hong","홍길동","12345",40,true);

 

 

// 2. 객체를 복제후에 패스워드를 변경

Member clone_member = org_member.getMember();

 

System.out.println("변경전 패스워드= "+org_member.password);

clone_member.password = "67890";

System.out.println();

 

System.out.println("[복제객체 clone_member]");

System.out.println(clone_member.id);

System.out.println(clone_member.name);

System.out.println(clone_member.password);

System.out.println(clone_member.age);

System.out.println(clone_member.adult);

System.out.println();

 

System.out.println("[원본객체 org_member]");

System.out.println(org_member.id);

System.out.println(org_member.name);

System.out.println(org_member.password);

System.out.println(org_member.age);

System.out.println(org_member.adult);

System.out.println();

 

System.out.println(clone_member.password.hashCode());

System.out.println(org_member.password.hashCode());

System.out.println();

 

System.out.println(clone_member.scores.hashCode());

System.out.println(org_member.scores.hashCode());

System.out.println();

 

System.out.println("원본[0]: 변경전 점수= " +org_member.scores[0]);

System.out.println("복제[0]: 변경후 점수= " +clone_member.scores[0]);

System.out.println();

org_member.scores[0] = 100;

System.out.println("원본[0]: 변경전 점수= " +org_member.scores[0]);

System.out.println("복제[0]: 변경후 점수= " +clone_member.scores[0]);

}

 

}

/*

객체소멸자(finalize())

참조하지 않는 배열이나 객체는 GC(Garbage Collector)가 힙영역에서 자동적으로

소멸시킨다. GC는 객체를 소멸하기 직전에 마지막으로 객체의 소멸자(finalize)를

실행시킨다. 소멸자는 Object.finalize()메서드를 말하는데 기본적으로 실행할 내용

이 없다(즉, 실행블럭에는 아무런 내용이 없다.)

 

만약, 객체가 소멸되기 전에 마지막으로 사용했던 자원(데이터베이스 연결객체, 파일객체 등..)

을 닫고 싶거나 중요한 데이터를 저장할 경우에 finalize()를 재정의할 수

있다.

 

gc가 객체를 소멸시킬 때 무작위로 소멸시키기 때문에 순차적인 작업을 할 수가 없기

때문에 유의해서 사용해야 한다.

*/

 

 

' > JAVA' 카테고리의 다른 글

java11.basic_API.class  (0) 2023.05.25
java11.basic_API.Objects  (0) 2023.05.25
java09.exception  (0) 2023.05.25
java08.nested  (0) 2023.05.25
java07.interface  (0) 2023.05.25