Publish:

νƒœκ·Έ: , ,

μΉ΄ν…Œκ³ λ¦¬:

ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄

  • ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ— λŒ€ν•΄ μ•Œμ•„λ³΄κ³  μ‚¬μš© 사둀λ₯Ό μ‚΄νŽ΄λ΄…λ‹ˆλ‹€.

μ •μ˜

κΈ°μ‘΄ μΈμŠ€ν„΄μŠ€λ₯Ό λ³΅μ œν•˜μ—¬ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 방법

  • 볡제 κΈ°λŠ₯을 κ°–μΆ”κ³  μžˆλŠ” κΈ°μ‘΄ μΈμŠ€ν„΄μŠ€λ₯Ό ν”„λ‘œν† νƒ€μž…μœΌλ‘œ μ‚¬μš©ν•΄ μƒˆ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

μ£Όμš” ꡬ성 μš”μ†Œ

img

객체λ₯Ό λ³΅μ œν•  λ•Œ μƒκΈ°λŠ” 문제점

객체λ₯Ό λ³΅μ œν•˜λŠ” 것은 μƒκ°μ²˜λŸΌ κ°„λ‹¨ν•œ 일이 아닐 수 μžˆλ‹€. λ‹€μŒκ³Ό 같은 λͺ‡κ°€μ§€ λ¬Έμ œκ°€ μžˆλŠ”λ° ν•˜λ‚˜μ”© μ‚΄νŽ΄λ³΄μž.

객체 μ™ΈλΆ€μ—μ„œ private ν•„λ“œλ₯Ό 볡사할 수 μ—†λ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Person {
  private String name;
  private int age;

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

  // Getter
  public String getName() {
      return name;
  }

  public int getAge() {
      return age;
  }
}

public class Main {
  public static void main(String[] args) {
      Person person1 = new Person("Alice", 30);

       // λΉ„κ³΅κ°œ ν•„λ“œ μ ‘κ·Ό μ‹œλ„ - 였λ₯˜ λ°œμƒ
       // String name = person1.name; // 컴파일 μ—λŸ¬
       // int age = person1.age; // 컴파일 μ—λŸ¬

       // λ³΅μ œλ³Έμ„ μƒμ„±ν•˜λ €κ³  ν•˜μ§€λ§Œ λΉ„κ³΅κ°œ ν•„λ“œμ— μ ‘κ·Όν•  수 μ—†μŒ
       Person person2 = new Person(person1.getName(), person1.getAge());
       
       System.out.println(person1.getName() + ", " + person1.getAge());
       System.out.println(person2.getName() + ", " + person2.getAge());
   }
}

객체의 λ³΅μ œλ³Έμ„ μƒμ„±ν•˜λ €λ©΄ 객체의 클래슀λ₯Ό μ•Œμ•„μ•Ό ν•œλ‹€.

클래슀 μ˜μ‘΄λ„κ°€ 높아진닀.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Employee {
   private String name;
   private int salary;

   public Employee(String name, int salary) {
       this.name = name;
       this.salary = salary;
   }

   // Getter
   public String getName() {
       return name;
   }

   public int getSalary() {
       return salary;
   }

   // 볡사 μƒμ„±μž ν•„μš”
   public Employee(Employee other) {
       this.name = other.name;
       this.salary = other.salary;
   }
}

public class Main {
  public static void main(String[] args) {
      Employee emp1 = new Employee("Bob", 50000);

      // λ³΅μ œλ³Έμ„ μƒμ„±ν•˜λ €λ©΄ Employee ν΄λž˜μŠ€μ— 의쑴
      Employee emp2 = new Employee(emp1); // Employee ν΄λž˜μŠ€μ— 의쑴
       
      System.out.println(emp1.getName() + ", " + emp1.getSalary());
      System.out.println(emp2.getName() + ", " + emp2.getSalary());
  }
}

μΈν„°νŽ˜μ΄μŠ€ 기반 섀계 문제

ꡬ체 ν΄λž˜μŠ€μ— μ˜μ‘΄ν•˜μ§€ μ•Šκ³  객체λ₯Ό λ³΅μ œν•˜κΈ° μ–΄λ ΅λ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
interface Copyable {
    Copyable copy();
}

class Student implements Copyable {
   private String name;
   private int grade;

   public Student(String name, int grade) {
      this.name = name;
      this.grade = grade;
   }

    @Override
    public Copyable copy() {
        return new Student(this.name, this.grade);
    }

    // Getter
    public String getName() {
        return name;
    }

    public int getGrade() {
        return grade;
    }
}

public class Main {
  public static void main(String[] args) {
      Copyable student1 = new Student("Charlie", 10);

      // μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν†΅ν•΄μ„œλŠ” ꡬ체적인 ν΄λž˜μŠ€μ— μ ‘κ·Όν•  수 μ—†μŒ
      // Student student2 = (Student) student1.copy(); // λ‹€μš΄μΊμŠ€νŒ… ν•„μš” - μœ μ—°μ„± μ €ν•˜
        
      Copyable student2 = student1.copy(); // Copyable μΈν„°νŽ˜μ΄μŠ€λ‘œλŠ” ꡬ체적인 ν•„λ“œ μ ‘κ·Ό λΆˆκ°€
        
      // student2κ°€ Student νƒ€μž…μΈμ§€ 확인 ν›„ μΊμŠ€νŒ… ν•„μš”
      if (student2 instanceof Student) {
          Student copiedStudent = (Student) student2;
          System.out.println(copiedStudent.getName() + ", " + copiedStudent.getGrade());
      }
  }
}

μœ„μ™€ 같은 문제λ₯Ό νšŒν”Όν•˜λ©΄μ„œλ„ λ³΅μ œν•  수 μžˆλŠ” 방법에 λŒ€ν•΄ μ•Œμ•„λ³΄μž.

ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄ 예제

μš°μ„  ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ˜ κ΅¬μ„±μš”μ†ŒλŒ€λ‘œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§Œλ“ λ‹€. μ™œ μΈν„°νŽ˜μ΄μŠ€κ°€ ν•„μš”ν•œμ§€μ— λŒ€ν•΄μ„  μ½”λ“œλ₯Ό 톡해 μ•Œμ•„ 보겠닀.

1
2
3
public interface Prototype {
  Prototype clone();
}

κ·Έ ν›„ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 클래슀 λ‚΄μ—μ„œ clone() λ©”μ†Œλ“œλ₯Ό μž¬μ •μ˜ν•œλ‹€.

GameCharacter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class GameCharacter implements Prototype {
  private String name;
  private int level;
  private String profession;

  public GameCharacter(String name, int level, String profession) {
    this.name = name;
    this.level = level;
    this.profession = profession;
  }
  
  public String getName() {
    return name;
  }

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

  public int getLevel() {
    return level;
  }

  public void setLevel(int level) {
    this.level = level;
  }

  public String getProfession() {
    return profession;
  }

  public void setProfession(String profession) {
    this.profession = profession;
  }

  // clone μž¬μ •μ˜
  @Override
  public Prototype clone() {
    return new GameCharacter(name, level, profession);
  }

  @Override
  public String toString() {
    return "GameCharacter [name=" + name + ", level=" + level + ", profession=" + profession + "]";
  }

  @Override
  public boolean equals(Object o) {
    if (this == o)
      return true;
    if (!(o instanceof GameCharacter))
      return false;
    GameCharacter that = (GameCharacter) o;
    return level == that.level && Objects.equals(name, that.name) && Objects.equals(profession,
      that.profession);
  }
}

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class Client {
  public static void main(String[] args) {
    List<Prototype> characters = new ArrayList<>();  // 원본 μ €μž₯용 리슀트
    List<Prototype> charactersCopy = new ArrayList<>();  // 볡제 μ €μž₯용 리슀트

    // 원본 객체 생성
    GameCharacter originalCharacter = new GameCharacter("Archer", 10, "Archer");
    characters.add(originalCharacter);

    // 볡제 객체 생성
    GameCharacter clonedCharacter = (GameCharacter) originalCharacter.clone();
    characters.add(clonedCharacter);

    // 볡제 객체의 속성 λ³€κ²½
    clonedCharacter.setName("Mage");
    clonedCharacter.setProfession("Mage");

    // 좜λ ₯
    System.out.println("Original Character: " + originalCharacter);
    System.out.println("Cloned Character: " + clonedCharacter);
    System.out.println();
    
    cloneAndCompare(characters, charactersCopy);
  }

  private static void cloneAndCompare(List<Prototype> characters, List<Prototype> charactersCopy) {
    // 이 뢀뢄이 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•œ μ΄μœ λ‹€. 
    for (Prototype character : characters) {
      charactersCopy.add(character.clone());
    }

    for (int i = 0; i < characters.size(); i++) {
      if (characters.get(i) != charactersCopy.get(i)) {
        System.out.println(i + ": μ„œλ‘œ λ‹€λ₯Έ 캐릭터 객체닀. (yay!)");
        if (characters.get(i).equals(charactersCopy.get(i))) {
          System.out.println(i + ": 그리고 μ„œλ‘œ 같은 객체닀.(yay!)");
        } else {
          System.out.println(i + ": κ·ΈλŸ¬λ‚˜ μ„œλ‘œ λ‹€λ₯Έ 객체닀. (booo!)");
        }
      } else {
        System.out.println(i + ": μ„œλ‘œ 같은 ν”„λ‘œν† νƒ€μž… 객체닀. (booo!)");
      }
    }
  }
}

μœ„ μ½”λ“œμ—μ„œ characters λ°°μ—΄μ—μ„œ 값을 κΊΌλ‚΄ 각각을 clone() ν• λ•Œ ꡬ체적인 클래슀λ₯Ό λͺ°λΌλ„ μΌκ΄€λœ λ°©μ‹μœΌλ‘œ μ½”λ“œλ₯Ό μž‘μ„± κ°€λŠ₯ν•˜λ‹€. clone() λ‚΄λΆ€μ—μ„œ ꡬ체 ν΄λž˜μŠ€κ°€ λ§Œλ“€μ–΄μ Έ λ³΅μ œλœλ‹€.

1
2
3
for (Prototype character : characters) {
  charactersCopy.add(character.clone());
}

좜λ ₯κ²°κ³Ό

1
2
3
4
5
6
7
Original Character: GameCharacter [name=Archer, level=10, profession=Archer]
Cloned Character: GameCharacter [name=Mage, level=10, profession=Mage]

0: μ„œλ‘œ λ‹€λ₯Έ 캐릭터 객체닀. (yay!)
0: 그리고 μ„œλ‘œ 같은 객체닀.(yay!)
1: μ„œλ‘œ λ‹€λ₯Έ 캐릭터 객체닀. (yay!)
1: 그리고 μ„œλ‘œ 같은 객체닀.(yay!)

clone() νŒ©ν† λ¦¬ λ©”μ†Œλ“œ μ•ˆμ—μ„œ μƒˆλ‘œμš΄ 객체λ₯Ό λ¦¬ν„΄ν•˜κ³  있기 λ•Œλ¬Έμ— μ„œλ‘œ λ‹€λ₯Έ μ£Όμ†Œκ°’μ„ 가진 객체닀. 그리고 객체 λ‚΄λΆ€ ν•„λ“œκ°’μ΄ 같은 경우 같은 객체둜 λ³΄κΈ°μœ„ν•΄ equals() λ₯Ό μž¬μ •μ˜ ν•˜μ˜€κΈ° λ•Œλ¬Έμ— μ„œλ‘œ 같은 κ°μ²΄μž„μ΄ 보μž₯λœλ‹€.

java μ—μ„œ μ§€μ›ν•˜λŠ” Cloneable μΈν„°νŽ˜μ΄μŠ€

java μ—μ„œλŠ” clone() 을 μœ„ν•œ Java Native Interface λ₯Ό μ§€μ›ν•œλ‹€. ν•΄λ‹Ή λ©”μ†Œλ“œ κ΅¬ν˜„ μ‹œ super.clone() 을 ν˜ΈμΆœν•˜κ²Œ 되면 λ‚΄λΆ€μ μœΌλ‘œ 얕은 볡사가 μ§„ν–‰λœλ‹€.

1
2
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;

ν•΄λ‹Ή λ©”μ†Œλ“œλŠ” Object ν΄λž˜μŠ€μ— 있고, 볡제 λ©”μ†Œλ“œκ°€ ν•„μš”ν•œ ν΄λž˜μŠ€μ—μ„œ μž¬μ •μ˜ ν•˜λ©΄ λ˜λŠ”λ°, κ·Έ ν΄λž˜μŠ€λŠ” Cloneable μ΄λΌλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κ³  μžˆμ–΄μ•Ό ν•œλ‹€.

1
2
public interface Cloneable {
}

Cloneable μΈν„°νŽ˜μ΄μŠ€λŠ” μ•„λ¬΄λŸ° λ©”μ†Œλ“œλ„ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ°, 이λ₯Ό 마컀 μΈν„°νŽ˜μ΄μŠ€(Marker Interface)라 ν•œλ‹€. 마컀 μΈν„°νŽ˜μ΄μŠ€κ°€ κ΅¬ν˜„λœ ν΄λž˜μŠ€λŠ” νŠΉμ • μ†μ„±μž„μ„ java κ°€ μ•Œ 수 μžˆλ„λ‘ ν•΄μ€€λ‹€. Cloneable μΈν„°νŽ˜μ΄μŠ€κ°€ κ΅¬ν˜„λ˜μ–΄ μžˆλŠ” ν΄λž˜μŠ€λŠ” clone() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€λŠ” 자격이라고 λ³΄λ©΄λœλ‹€. λ§Œμ•½ 마컀 μΈν„°νŽ˜μ΄μŠ€κ°€ μ—†λŠ” μƒνƒœμ—μ„œ clone() 을 ν˜ΈμΆœν•˜κ²Œ 되면 CloneNotSupportedException이 λ°œμƒν•œλ‹€.

직렬화 객체에 직렬화가 κ°€λŠ₯함을 μ•Œλ¦¬κΈ°μœ„ν•΄ λΆ™μ΄λŠ” Serializable μΈν„°νŽ˜μ΄μŠ€μ˜ κ²½μš°λ„ 마컀 μΈν„°νŽ˜μ΄μŠ€λ‹€.

JNI

Java Native Interface λŠ” java κ΅¬ν˜„λ˜μ§€ μ•Šμ€ 일뢀 ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°€λŠ₯ν•˜κ²Œ λ§Œλ“ λ‹€. 예λ₯Ό λ“€μ–΄ ν•˜λ“œμ›¨μ–΄ μ‘°μž‘ λͺ…λ Ήμ΄λ‚˜ 직접적인 OS API λͺ…λ Ή img 좜처 : https://medium.com/@sarafanshul/jni-101-introduction-to-java-native-interface-8a1256ca4d8e

얕은볡사 / κΉŠμ€λ³΅μ‚¬

객체의 λ³΅μ œμ™€ 항상 ν•¨κ»˜ λ“±μž₯ν•˜λŠ” 주제 쀑 ν•˜λ‚˜κ°€ shallow copy / deep copy 라고 μƒκ°ν•œλ‹€. κ°„λ‹¨νžˆ μ •λ¦¬ν•˜λ©΄

  • shallow copy : 객체의 μ΅œμƒμœ„ 레벨만 볡사. ν•˜μœ„ κ°μ²΄λŠ” μ°Έμ‘°λ₯Ό 곡유. 원본 κ°μ²΄λ‚˜ λ³΅μ‚¬λœ 객체의 변경이 μ„œλ‘œμ—κ²Œ 영ν–₯을 λ―ΈμΉ  수 μžˆλ‹€.
  • deep copy : 객체 전체λ₯Ό μž¬κ·€μ μœΌλ‘œ 볡사. ν•˜μœ„ κ°μ²΄κΉŒμ§€ λͺ¨λ‘ 독립적인 볡사본 생성. μ„œλ‘œ 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠλŠ”λ‹€.

μž₯점과 단점

  • μž₯점
    • λ³΅μž‘ν•œ 객체λ₯Ό λ§Œλ“œλŠ” 과정을 숨길 수 μžˆλ‹€.
    • κΈ°μ‘΄ 객체λ₯Ό λ³΅μ œν•˜λŠ” 과정이 μƒˆ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“œλŠ” 것보닀 λΉ„μš©λ©΄μ—μ„œ 효율적일 μˆ˜λ„ μžˆλ‹€.
    • 좔상적인 νƒ€μž…μ„ 리턴할 수 μžˆλ‹€.
  • 단점
    • λ³΅μ œν•œ 객체λ₯Ό λ§Œλ“œλŠ” κ³Όμ • μžμ²΄κ°€ λ³΅μž‘ν•  수 μžˆλ‹€. (μˆœν™˜ μ°Έμ‘°κ°€ μžˆλŠ” 경우)

μžλ°”μ—μ„œ μ°Ύμ•„λ³΄λŠ” ν”„λ‘œν† νƒ€μž…

ArrayList.clone()

ArrayList λ₯Ό λ³΅μ‚¬ν• λ•Œ clone() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€.

img.png ArrayList λŠ” Cloneable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κ³  μžˆλ‹€.

κ·ΈλŸ¬λ‚˜ 이 방법은 잘 쓰이지 μ•ŠλŠ”λ‹€. μ™œλƒν•˜λ©΄ 보톡 ArrayList λ₯Ό λ°›μ„λ•Œ μ•„λž˜μ²˜λŸΌ μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μœΌλ‘œ λ°›κΈ° λ•Œλ¬Έμ΄λ‹€.

1
List<Item> items = new ArrayList<>();

List μΈν„°νŽ˜μ΄μŠ€μ—λŠ” clone() λ©”μ†Œλ“œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€.

ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ„ 쓰지 μ•Šκ³  μƒμ„±μžλ‘œ 볡사

ArrayList 의 μƒμ„±μž 쀑에 μ»¬λ ‰μ…˜ νƒ€μž…μ„ λ°›λŠ” μƒμ„±μžκ°€ μžˆλ‹€. 인자둜 μ „λ‹¬ν•˜λ©΄ λ³΅μ œλœλ‹€.

ArrayList

1
2
3
4
5
6
7
8
9
10
11
12
13
public ArrayList(Collection<? extends E> c) {
    Object[] a = c.toArray();
    if ((size = a.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
            elementData = Arrays.copyOf(a, size, Object[].class);
        }
    } else {
        // replace with empty array.
        elementData = EMPTY_ELEMENTDATA;
    }
}

Client

1
List<Item> clone = new ArrayList<>(items);  // νŒŒλΌλ―Έν„°λ‘œ μ»¬λ ‰μ…˜ νƒ€μž…μ„ μ „λ‹¬ν•˜λ©΄ λ³΅μ œλœλ‹€.

ν•΄λ‹Ή λ©”μ†Œλ“œ 쀑간에 Arrays.copyOf() λ©”μ†Œλ“œλ₯Ό 톡해 νŒŒλΌλ―Έν„°λ‘œ λ„˜κ²¨λ°›μ€ μ»¬λ ‰μ…˜μ„ λ³΅μ‚¬ν•œλ‹€.

λ¦¬ν”Œλž™μ…˜ μ‚¬μš©

λ¦¬ν”Œλž™μ…˜μ„ μ΄μš©ν•œ 라이브러리λ₯Ό μ‚¬μš©ν•˜λ©΄ λ³΅μž‘ν•œ μ½”λ“œλ₯Ό 직접 μ§œμ§€ μ•Šμ•„λ„ μ‰½κ²Œ λ³΅μ œκ°€ κ°€λŠ₯ν•˜λ‹€. 첫번째 인자둜 μ˜€λŠ” νƒ€κ²Ÿ 객체λ₯Ό λ‘λ²ˆμ§Έ 인자의 νƒ€μž…μœΌλ‘œ λ³€ν™˜μ‹œμΌœμ€€λ‹€.

λ¦¬ν”Œλž™μ…˜ κ΄€λ ¨ν•΄μ„œλŠ” ν•΄λ‹Ή κΈ€μ—μ„œ μ •λ¦¬ν–ˆλ‹€.

ModelMapper 라이브러리

1
2
ModelMapper modelMapper = new ModelMapper();
GithubIssueData githubIssueData = modelMapper.map(githubIssue, GithubIssueData.class);

ObjectMapper 라이브러리

1
Map<String, Object> response = om.readValue(response, Map.class);

ObjectMapper λŠ” νŒ€ ν”„λ‘œμ νŠΈμ—μ„œ OAuth 인증 μ‹œ ν”Œλž«νΌ 별 μƒμ΄ν•œ JSON 을 νŒŒμ‹±ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν–ˆλ˜ κ²½ν—˜μ΄ μžˆλ‹€. (μ½”λ“œλ³΄κΈ°)

Gson 라이브러리

λ³΅μ œν•  μΈμŠ€ν„΄μŠ€λ₯Ό GsonBuilder 의 toJson() 의 νŒŒλΌλ―Έν„°λ‘œ λ„˜κ²¨μ£Όλ©΄ μƒˆλ‘œμš΄ JSON ν˜•νƒœλ‘œ λ°˜ν™˜ν•΄μ€€λ‹€. μ•„λž˜ μ½”λ“œλŠ” ν”„λ‘œμ νŠΈμ—μ„œ μ‚¬μš©ν–ˆλ˜ μ½”λ“œμ˜ 일뢀뢄이닀. (전체 μ½”λ“œλ³΄κΈ°)

1
2
3
4
5
// Result.class
@Override
public String toString() {
  return new GsonBuilder().serializeNulls().create().toJson(this);
}

Rest api λ°˜ν™˜ 객체에 toString 을 μž¬μ •μ˜ν•˜κ³  JSON 객체둜 λ¦¬ν„΄ν•˜κΈ° μœ„ν•΄ GsonBuilder λ₯Ό μ‚¬μš©ν–ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈ μͺ½ μ½”λ“œλŠ” μ•„λž˜μ™€ 같이 일반적인 toString 을 ν˜ΈμΆœν•˜λ“―μ΄ ν•˜λ©΄ JSON ν˜•νƒœλ‘œ λ°˜ν™˜ν•  수 μžˆλ‹€.

1
2
3
4
5
@PostMapping("add")
public String add(@RequestBody @Valid CodeRequestDto codeRequestDto) throws Exception {
  codeService.add(codeRequestDto);
  return new Result<>().setResultData(codeService.list(Paging.builder().build())).toString();
}

μ•„λž˜μ—μ„œ μ‚΄νŽ΄λ³Ό 직렬화 방식과 κ°™λ‹€κ³  보면 λœλ‹€.

객체λ₯Ό λ³΅μ œν•˜λŠ” λ‹€μ–‘ν•œ 방법

볡사 μƒμ„±μž

볡사 μƒμ„±μž

클래슀 내뢀에 볡사 μƒμ„±μžλ₯Ό μ •μ˜ν•˜μ—¬, ν•΄λ‹Ή 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ°›μ•„ ν•„λ“œ 값을 λ³΅μ‚¬ν•œλ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Person {
  private String name;
  private int age;

// μƒμ„±μž
public Person(String name, int age) {
  this.name = name;
  this.age = age;
}

// 볡사 μƒμ„±μž
public Person(Person other) {
  this.name = other.name;
  this.age = other.age;
}

//  // Getter κ°€ 없어도 private ν•„λ“œ 볡사 κ°€λŠ₯
//  public String getName() {
//    return name;
//  }
//
//  public int getAge() {
//    return age;
//  }


@Override
public String toString() {
  return "Person{name='" + name + "', age=" + age + "}";
}
}

public class Main {
  public static void main(String[] args) {
      Person person1 = new Person("Alice", 30);
      Person person2 = new Person(person1); // 볡사 μƒμ„±μž μ‚¬μš©

    System.out.println(person1);
    System.out.println(person2);
  }
}

직렬화

직렬화

객체λ₯Ό μ§λ ¬ν™”ν•œ ν›„ μ—­μ§λ ¬ν™”ν•˜λŠ” 방법. 이 방법은 κΈ°μ‘΄ κ°μ²΄μ™€μ˜ μ°Έμ‘°κ°€ λŠμ–΄μ Έ κΉŠμ€ 볡사λ₯Ό 보μž₯ν•œλ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.*;

public class MyClass implements Serializable {
    private int field1;
    private String field2;
    
    public MyClass deepCopy() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(this);
            
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream in = new ObjectInputStream(bis);
            return (MyClass) in.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    // 기타 λ©”μ„œλ“œ 및 μ ‘κ·Όμž
}

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” JSON.stringify() 와 JSON.parse() λ₯Ό 톡해 κ°€λŠ₯ν•˜λ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
const obj = {
  a: 1,
  b: {
    c: 2,
  },
};

const copiedObj = JSON.parse(JSON.stringify(obj));

copiedObj.b.c = 3

obj.b.c === copiedObj.b.c  //false 
νŒ©ν† λ¦¬ λ©”μ†Œλ“œ

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ

클래슀의 μ˜μ‘΄μ„±μ„ 쀄일 수 μžˆλ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface Copyable {
    Copyable copy();
}


public class MyClass implements Copyable {
    private int field1;
    private String field2;
    
    @Override
    public MyClass copy() {
        return new MyClass(this);
    }
    
    // 볡사 μƒμ„±μž
    public MyClass(MyClass other) {
        this.field1 = other.field1;
        this.field2 = other.field2;
    }
    
    // 기타 λ©”μ„œλ“œ 및 μ ‘κ·Όμž
}

정리

ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄μ€ λ‹€λ₯Έ νŒ¨ν„΄λ“€μ— λΉ„ν•΄ κ°„λ‹¨ν•˜λ‹€. 미리 λ§Œλ“€μ–΄ 놓은 ν”„λ‘œν† νƒ€μž… 객체λ₯Ό λ³΅μ œν•˜μ—¬ μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•˜λŠ” νŒ¨ν„΄μ΄λ‹€. 객체 생성 μ‹œ 맀번 DB λ₯Ό μ‘°νšŒν•΄μ•Ό ν•˜λŠ” λ“±κ³Ό 같이 생성 λΉ„μš©μ΄ 큰 경우 μ‚¬μš©ν•  수 μžˆμ„ 것 κ°™λ‹€.

κ·ΈλŸ¬λ‚˜ ν˜•νƒœλŠ” κ°„λ‹¨ν•˜μ§€λ§Œ ν˜„μ—…μ—μ„œ μ“°λ €λ©΄ clone() λ©”μ†Œλ“œλ₯Ό μ–΄λ–»κ²Œ μž‘μ„±ν•΄μ•Ό 할지 생각을 해야될 것 κ°™λ‹€. 특히 java μ—μ„œ μ§€μ›ν•˜λŠ” Cloneable 의 기본적인 κ΅¬ν˜„ 방식(super.clone())은 얕은 λ³΅μ‚¬μž„μ„ μΈμ§€ν•˜κ³  μžˆμ–΄μ•Ό ν•˜κ³ , λ§Œμ•½ κΉŠμ€ 볡사λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•˜λŠ” 경우, 객체의 λͺ¨λ“  ν•˜μœ„ 객체듀도 μ˜¬λ°”λ₯΄κ²Œ λ³΅μ œλ˜μ–΄μ•Ό ν•˜λ―€λ‘œ κ΅¬ν˜„μ΄ κΉŒλ‹€λ‘œμšΈ 수 μžˆλ‹€. λ˜ν•œ 볡제된 객체가 ν”„λ‘œν† νƒ€μž… 객체에 λ°€μ ‘ν•˜κ²Œ μ—°κ΄€λ˜μ–΄ μžˆμ–΄, λ§Œμ•½ 원본 객체의 λ‚΄μš©μ΄ λ³€κ²½λ˜λ©΄ μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ ν”„λ‘œν† νƒ€μž…μ„ κ°±μ‹ ν•΄μ•Ό ν•  μˆ˜λ„ μžˆλ‹€.

μ°Έκ³ 

λ°©λ¬Έν•΄ μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! λŒ“κΈ€,지적,ν”Όλ“œλ°± μ–Έμ œλ‚˜ ν™˜μ˜ν•©λ‹ˆλ‹€πŸ˜Š

λŒ“κΈ€λ‚¨κΈ°κΈ°