독서모임 -

존스노우·2024년 1월 29일
0

독서모임

목록 보기
1/9

독서모임 정리

  • 늦었지만 지금부터라도 정리를

얕은 복사(Shallow Copy) VS 깊은 복사(Deep Copy)

  • 얕은 복사(Shallow Copy): 객체의 필드를 복사하지만, 필드가 참조하는 객체는 복사하지 않습니다. 즉, 원본 객체와 복사된 객체가 동일한 객체를 참조!

  • '주소 값'을 복사한다는 의미

  • 복사는 동일한 주소를 바라보기때문에 복사한 곳에서 값 변경이 일어나면 바뀜

   public static void main(String[] args) {
        MyObject original = new MyObject(5);
        MyObject shallowCopy = original; // 얕은 복사

        shallowCopy.data = 10;
        System.out.println(original.data); // 출력: 10    
        
}
   static class MyObject {
        int data;
        MyObject(int data) {
            this.data = data;
        }
    }

}

// 10 

  • 그림설명

  • 결국 얕은 복사는 heap영역의 참조값을 동일하게 바라보고 있음.

  • '실제 값'을 새로운 메모리 공간에 복사하는 것을 의미

  • 깊은 복사(Deep Copy): 객체의 필드를 복사하고, 필드가 참조하는 객체도 복사
    원본 객체와 복사된 객체는 완전히 독립적

  • 독립적인 객체 그래서 복사된 값을 바꿔도 변함이없다.

public class DeepCopy {

    public static void main(String[] args) {
        MyObject original = new MyObject(5);
        MyObject deepCopy = original.deepCopy(); // 깊은 복사

        deepCopy.data = 10;
        System.out.println(original.data); // 출력: 5
        
}
   static class MyObject {
       int data;
       MyObject(int data) {
           this.data = data;
       }
       MyObject deepCopy() {
           return new MyObject(this.data);
       }
   }

}

CLONE?

  • 깊은 복사 방법중 하나!
public class CopyObject implements Cloneable {

    private String name;
    private int age;

    public CopyObject() {
    }

    public CopyObject(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public CopyObject clone() throws CloneNotSupportedException {
        return (CopyObject) super.clone();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}




public class Clone {


    public static void main(String[] args) throws CloneNotSupportedException {
        CopyObject original = new CopyObject("superkkj", 22);
        CopyObject copy = original.clone();

        copy.setName("gkj");

        System.out.println(original.getName()); // superkkj
        System.out.println(copy.getName()); // gkj

    }
}

  • 클래스가 Object 클래스의 clone() 메소드를 사용하여 필드별 복사(field-for-field copy)를 수행할 수 있음을 나타내는 역할

  • 마커 인터페이스: Cloneable은 마커 인터페이스로, 이 인터페이스를 구현한다는 것은 해당 클래스가 복제 가능함을 나타냅니다.

  • 복사 허용: 클래스가 Cloneable을 구현하면, Object 클래스의 clone() 메소드를 호출할 때, CloneNotSupportedException 예외가 발생하지 않습니다.

  • 이런 설명..

주의 사항

  • 메소드 오버라이딩: Cloneable 인터페이스를 구현하는 클래스는 일반적으로 Object의 clone() 메소드를 public으로 오버라이딩해야함

  • object의 clone() 메소드는 기본적으로 protected이기 때문에, 이를 오버라이딩하지 않으면 다른 패키지나 클래스에서 접근할 수 없습니다.

  • Object의 clone() 메소드는 기본적으로 얕은 복사를 수행합니다. 따라서 깊은 복사를 원한다면 clone() 메소드를 오버라이딩하여 직접 구현해야 한다!

  • CloneNotSupportedException 처리도 해줘야 됨.

  • 뭐지 근대 위에코드는 얕은복사같은데 왜 깊은복사가 일어나지????

package com.dev.study;

import java.util.ArrayList;
import java.util.List;

public class TestClone implements Cloneable {
    private String name;
    private int age;
    private List<String> hobbies;

    public TestClone(String name, int age, List<String> hobbies) {
        this.name = name;
        this.age = age;
        this.hobbies = hobbies;
    }

    @Override
    public TestClone clone() throws CloneNotSupportedException {
        return (TestClone) super.clone();
    }

    // Getter와 Setter 메서드들

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

        public static void main(String[] args) throws CloneNotSupportedException {
        List<String> hobbies = new ArrayList<>();
        hobbies.add("Reading");
        hobbies.add("Gaming");

        TestClone original = new TestClone("superkkj", 22, hobbies);
        TestClone copy = original.clone();

        // 복사된 객체의 취미 목록 변경
        copy.getHobbies().add("Swimming");
        copy.setAge(30);
        copy.setName("copy");

        System.out.println("Original Name: " + original.getName()); // superkkj
        System.out.println("Copy Name: " + copy.getName()); // copy
        System.out.println("original age: " + original.getAge()); // 22
        System.out.println("Copy age: " + copy.getAge()); // 30

        System.out.println("Original Hobbies: " + original.getHobbies()); // [Reading, Gaming, Swimming]
        System.out.println("Copy Hobbies: " + copy.getHobbies()); // [Reading, Gaming, Swimming]
    }
  • int , String은 깊은복사

  • 리스트는 얕은복사.. 왜 ?

  • 설명에 의하면 기본 타입은 값에 의한 복사가 이루어지고

  • String은 불변 타입 객체가 생성되고 참조가 다시 갱신된다 (새로운 문자열 할당시)

  • 그래서 깊은 복사처럼 보임

  • 참조형? 메모리 주소값 가지니까, 실제 객체의 위치.

  • 얕은 복사가 이루어질때 주소값만 복사되니 동일한 데이터 공유,, 아하..

 /* 복사 생성자 */
    public CopyObject(CopyObject original) {
        this.name = original.name;
        this.age = original.age;
    }

    /* 복사 팩터리 */
    public static CopyObject copy(CopyObject original) {
        CopyObject copy = new CopyObject();
        copy.name = original.name;
        copy.age = original.age;
        return copy;
    }
  • 이런식으로 복사 생성자 , 팩터리를 이용하는게 가장 안전하단다..
  • 딥다이브한건 피하고 여기까지만 알아보자

공변성(Covariance)와 반공변성(Contravariance)

  • 공변성(Covariance): 하위 타입의 객체를 상위 타입 객체로 대체할 수 있는 속성입니다. 예를 들어, Apple이 Fruit의 하위 타입일 때, Fruit 타입의 참조 변수가 Apple 객체를 참조할 수 있는 것을 의미합니다.

  • 자식이 부모를 대체?

  • 반공변성(Contravariance): 상위 타입의 객체를 하위 타입 객체로 대체할 수 있는 속성입니다. 이는 주로 제네릭 타입에서 볼 수 있으며, 예를 들어, Fruit가 Apple의 상위 타입일 때, Apple 타입의 참조 변수로 Fruit 타입 객체를 참조하는 것은 불가능하지만, 반대로 Fruit 타입의 참조 변수로 Apple 타입 객체를 참조하는 것은 가능합니다.

  • 부모가 자식을 대체 흐음.

2024-02-02

예외

profile
어제의 나보다 한걸음 더

0개의 댓글