Java

Java์—์„œ ๋ถˆ๋ณ€ ๊ฐ์ฒด

joaa 2024. 2. 21. 17:53

๐ŸŽˆ ๋ถˆ๋ณ€(immutable) ๊ฐ์ฒด๋ž€?

๊ฐ์ฒด ์ƒ์„ฑ ์ดํ›„์—๋Š” ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ๊ฐ์ฒด

 

 

๐ŸŽˆ ๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ์žฅ์ 

1. ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค ๊ฐœ๋ฐœ์— ๋„์›€์ด ๋œ๋‹ค

2. map, set, cache์— ์“ฐ๊ธฐ์— ์ ์ ˆํ•˜๋‹ค. 

 

์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ

Set<RGB> myRGBs = new HashSet<>();

RGB green = new RGB(0, 128, 0);
myRGBs.add(green);

RGB invertedGreen = green.invert();

System.out.println(myRGBs.contains(invertedGreen)); //์˜ˆ์ƒ: false, ๊ฒฐ๊ณผ: false
System.out.println(myRGBs.contains(green)); //์˜ˆ์ƒ: true, ๊ฒฐ๊ณผ: false

RGB greenAgain = new RGB(0, 128, 0);
System.out.println(myRGBs.contains(greenAgain)); //์˜ˆ์ƒ: true, ๊ฒฐ๊ณผ: false
public class RGB {
    private int r, g, b;
    
    public RGB(int r, int g, int b){
    	this.r = r; this.g = g; this.b = b;
    }
    
    public int hashCode() {
    	return r << 16 + g << 8 + b;
    }
    
    public boolean equals(Object obj) {
    	RGB o = (RGB) obj;
        return r == o.r && g == o.g && b == o.b;
    }
    
    //๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ฐ”๊ฟ”์„œ ํ•ด์‹œ์…‹์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๊ฒŒ๋งŒ๋“œ๋Š” ๋ถ€๋ถ„
    public RGB invert() {
    	r = 255 - r; g = 255 - g; b = 255 - b;
        return this;
    }
}

 

 

์ด๋Ÿฐ ์‹์œผ๋กœ ๋ฐ”๊ฟ” ํ•ด๊ฒฐํ•œ๋‹ค. 

private final int r, g, b;
...
public RGB invert() {
	RGB inv = new RGB(255-r, 255-g, 255-b);
    return inv;
}

 

 

3. (์ผ๋ฐ˜์ ์œผ๋กœ) thread-safe ํ•˜๋‹ค.

4. ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ํ•„๋“œ๋กœ ์“ฐ๋ฉด ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. 

 

  ๋ชจ๋“  ๊ฒƒ์„ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ํ‘œํ˜„ํ•  ์ˆœ ์—†์ง€๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•จ. 

 

 

 

 

 

 

Java์˜ String

String์€ Java์˜ ๋Œ€ํ‘œ์ ์ธ ๋ถˆ๋ณ€ ๊ฐ์ฒด

String easyCode = "์‰ฌ์šด์ฝ”๋“œ"
String sameRef = easyCode;
System.out.println(easyCode == sameRef); //true

easyCode = "๋”์‰ฌ์šด์ฝ”๋“œ" //์•„์˜ˆ ์ƒˆ๋กœ์šด ๋ฌธ์ž์—ด์„ ํ• ๋‹นํ•œ๋‹ค. 
System.out.println(easyCode == sameRef); //false

 

 

 

 

 

๐ŸŽˆ Java์—์„œ ๋ถˆ๋ณ€ ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ

1. ์ƒ์„ฑ์ž๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ƒํƒœ๋ฅผ ๋ฐ”๊ฟ€๋งŒํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐ

2. ๋ชจ๋“  ํ•„๋“œ๋ฅผ private final๋กœ ์ง€์ •

 

ํด๋ž˜์Šค๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด๋„

public class Person {
    private final String name;
    
    public Person(String name) {
    	this.name = name;
    }
    
    public String getName() {
    	return name;
    }
}

 

 

๋‹ค์Œ๊ณผ ๊ฐ™์ด getter๋ฅผ ์žฌ์ •์˜ํ•˜์—ฌ ๊ฐ€๋ณ€ ๊ฐ์ฒด์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ

public class NewPerson extends Person {
    private String newName;
    
    public NewPerson(String name) {
    	super(name);
        newName = name;
    }
    
    public void setName(String name) {
    	this.newName = name;
    }
    
    public String getName() {
    	return this.newName;
    }
}
Person person = new NewPerson("messi");
System.out.println(person.getName()); //messi

NewPerson newPerson = (NewPerson) person;
newPerson.setName("wow");

System.out.println(person.getName()); //wow

 

 

→ 3. ์ž๋…€ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ override ๊ธˆ์ง€. ์ฆ‰, ํด๋ž˜์Šค ์ƒ์† ๊ธˆ์ง€

- ํด๋ž˜์Šค ์•ž์— final ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ด๊ฑฐ๋‚˜

- ์ƒ์„ฑ์ž์˜ ์ ‘๊ทผ์ œ์–ด์ž๋ฅผ public private์œผ๋กœ ๋ฐ”๊พธ๊ณ  static factory method๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ

 

 

 

๋งŒ์•ฝ ๊ฐ์ฒด์˜ ํ•„๋“œ ์ค‘์—  ๊ฐ€๋ณ€(mutable) ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด?

 

→ 4. mutable ๊ฐ์ฒด์˜ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๊ณต์œ ํ•ด์„œ ์‚ฌ์šฉํ•˜์ง€ ๋ง ๊ฒƒ.

์ด๋ฅผ ์œ„ํ•ด ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ํ™œ์šฉ

public final class Person {
    private final String name;
    private final RGB rgb; //RGB is mutable. RGB๊ฐ€ ๊ฐ€๋ณ€ ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ๋ฅผ ๊ฐ€์ •
    
    public Person(String name, RGB rgb) {
        this.name = name;
        this.rgb = new RGB(rgb.r, rgb.g, rgb.b); //๋ฐฉ์–ด์  ๋ณต์‚ฌ
        //this.rgb = rgb; RGB๊ฐ€ ๊ฐ€๋ณ€ ๊ฐ์ฒด์˜€๋‹ค๋ฉด ๋ฐฉ์–ด์  ๋ณต์‚ฌ ํ•„์š” ์—†์Œ. 
    }
    
    public String getName() {
    	return name;
    }
    
    public RGB getRGB() {
    	//return rgb; RGB๊ฐ€ ๊ฐ€๋ณ€ ๊ฐ์ฒด์˜€๋‹ค๋ฉด ๋ฐฉ์–ด์  ๋ณต์‚ฌ ํ•„์š” ์—†์Œ. 
    	return new RGB(rgb.r, rgb.g, rgb.b); //๋ฐฉ์–ด์  ๋ณต์‚ฌ
    }
}
RGB green = new RGB(0, 128, 0);

Person person = new Person("messi", green);
System.out.println(person.getRGB().g); //128

RGB myRGB = person.getRGB();
myRGB.g = 0;
System.out.println(person.getRGB().g); //128

 

 

 

 

๐ŸŽˆ List๋ฅผ ํ•„๋“œ๋กœ ๊ฐ€์ง„๋‹ค๋ฉด?

List์™€ List์— ์žˆ๋Š” mutable ๊ฐ์ฒด ๋ชจ๋‘ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ํ•ด์•ผํ•œ๋‹ค. 

public final class Person {
    private final String name;
    private final List<RGB> rgbs; //RGB is mutable
    
    public Person(String name, List<RGB> rgbs) {
    	this.name = name;
        this.rgbs = copy(rgbs);
    }
    
    public String getName() {
    	return name;
    }
    
    public List<RGB> getRGBs() {
    	return copy(rgbs);
    }
    
    private List<RGB> copy(List<RGB> rgbs) {
    	List<RGB> cps = new ArrayList<RGB>();
        rgbs.forEach(o -> cps.add(new RGB(o.r, o.g, o.b)));
        return rgbs;
        //๋งŒ์•ฝ RGB๊ฐ€ immutable ๊ฐ์ฒด์˜€๋‹ค๋ฉด rgb๋ฅผ ์–•์€ ๋ณต์‚ฌํ•ด๋„ ๊ด€๊ณ„์—†์œผ๋ฏ€๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฒ˜๋ฆฌ
        //return new ArrayList<>(rgbs); 
        //๋˜๋Š” ์ƒ์„ฑ์ž์—์„œ
        //this.rgbs = Collections.unmodifiableList(rgbs); ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด return rgbs;๋กœ ๋ฐ”๋กœ return
    }
}

 

 

 

 

 

 

immutable์˜ ๋ฏธ๋ฌ˜ํ•œ ์˜๋ฏธ ์ฐจ์ด

์™ธ๋ถ€์— ๋…ธ์ถœ๋˜๋Š” ์ƒํƒœ ์ •๋ณด๋Š” immutableํ•˜์ง€๋งŒ ๋‚ด๋ถ€์—์„œ๋งŒ ๊ด€๋ฆฌ๋˜๋Š” ์ƒํƒœ๋Š” mutableํ•œ ๊ฒฝ์šฐ์—๋„ immutable ๊ฐ์ฒด๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ ํ•œ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” immutable ๊ฐ์ฒด๋„ thread-safeํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ. 

ํŒŒ์ด์ฌ์—์„œ๋Š” mutableํ•œ ํ•„๋“œ๋ฅผ ๊ฐ€์ง„ immutable ํด๋ž˜์Šค๋„ immutableํ•œ ๊ฐ์ฒด๋ผ๊ณ  ์ •์˜ํ•จ. 

 

 

 

 

์ถœ์ฒ˜: https://www.youtube.com/watch?v=EOGOJdBy2Rg&list=PLcXyemr8ZeoT-_8yBc_p_lVwRRqUaN8ET&index=27