반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 자바
- 카카오 면접
- java
- Effective Java
- 스프링 핵심원리
- kubernetes
- 스프링
- 이펙티브자바
- 알고리즘정렬
- 클린아키텍처
- 엘라스틱서치
- 오블완
- k8s
- 이펙티브 자바
- Spring
- 티스토리챌린지
- 스프링핵심원리
- 알고리즘
- JavaScript
- 예제로 배우는 스프링 입문
- 자바스크립트
- 이차전지관련주
- Effective Java 3
- 카카오
- ElasticSearch
- effectivejava
- 코딩테스트
- Sort
- 김영한
- 스프링부트
Archives
- Today
- Total
Kim-Baek 개발자 이야기
자바에서 코틀린 - 5장 빈에서 값으로 본문
POJO?
Plain Old Java Object
public class CoffeePOJO {
public String name;
private List<String> ingredients;
public CoffeePOJO(String name, List<String> ingredients) {
this.name = name;
this.ingredients = ingredients;
}
void addIngredient(String ingredient) {
ingredients.add(ingredient);
}
}
자바 빈(Java Bean)
공식 자바 빈 문서에 따르면 자바 빈은 아래의 조건을 모두 충족하는 POJO이다. (DTO라고도 한다함)
- 모든 객체 변수는 Private 제한자를 가지며 getter 와 setter 함수를 통해서 접근 가능하다.
- 아무런 입력값을 받지 않는 생성자(constructor)가 존재하여야 한다.
public class CoffeeBEAN implements Serializable {
private String name;
private List<String> ingredients;
public CoffeeBEAN() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getIngredients() {
return ingredients;
}
public void setIngredients(List<String> ingredients) {
this.ingredients = ingredients;
}
}
- 책에서 말하는 값 이란 불변데이터를 말함
- 불변 객체의 장점
- 스레드 세이프
- copy시 안정성
- 맵 같은 곳에서 쓰기 좋음
- 키가 변경되면 동작 보장 x
- 불변 객체의 장점
package travelator.mobile;
import java.util.Currency;
import java.util.Locale;
public class UserPreferences {
private String greeting;
private Locale locale;
private Currency currency;
public UserPreferences() {
this("Hello", Locale.UK, Currency.getInstance(Locale.UK));
}
public UserPreferences(String greeting, Locale locale, Currency currency) {
this.greeting = greeting;
this.locale = locale;
this.currency = currency;
}
public String getGreeting() {
return greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
public Currency getCurrency() {
return currency;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}
}
- 설정 정보
package travelator.mobile;
public class Application {
private final UserPreferences preferences;
public Application(UserPreferences preferences) {
this.preferences = preferences;
}
public void showWelcome() {
new WelcomeView(preferences).show();
}
public void editPreferences() {
new PreferencesView(preferences).show();
}
}
- UserPreferences로 웰컴화면이나 에디트 화면을 준다.
package travelator.mobile;
import java.util.Currency;
import java.util.Locale;
public class PreferencesView extends View {
private final UserPreferences preferences;
private final GreetingPicker greetingPicker = new GreetingPicker();
private final LocalePicker localePicker = new LocalePicker();
private final CurrencyPicker currencyPicker = new CurrencyPicker();
public PreferencesView(UserPreferences preferences) {
this.preferences = preferences;
}
public void show() {
greetingPicker.setGreeting(preferences.getGreeting());
localePicker.setLocale(preferences.getLocale());
currencyPicker.setCurrency(preferences.getCurrency());
super.show();
}
protected void onGreetingChange() {
preferences.setGreeting(greetingPicker.getGreeting());
}
protected void onLocaleChange() {
preferences.setLocale(localePicker.getLocale());
}
protected void onCurrencyChange() {
preferences.setCurrency(currencyPicker.getCurrency());
}
}
class GreetingPicker {
private String greeting;
public String getGreeting() {
return greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
}
class LocalePicker {
private Locale locale;
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
}
class CurrencyPicker {
private Currency currency;
public Currency getCurrency() {
return currency;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}
}
- 값을 변경한다.
- 두 개의 뷰가 활성화 된 경우 welcomeView 의 상태가 현재 값과 달라질 수 있다.
코틀린으로 변환
package travelator.mobile
class Application(
//가변 객체에 대한 불변 참조
private val preferences: UserPreferences // 변경 불가 value
) {
fun showWelcome() {
WelcomeView(preferences).show()
}
fun editPreferences() {
PreferencesView(preferences).show()
}
}
5.5
package travelator.mobile
import java.util.*
class UserPreferences @JvmOverloads constructor(
var greeting: String = "Hello", // 변경가능
var locale: Locale = Locale.UK,
var currency: Currency = Currency.getInstance(Locale.UK)
)
- @JvmOverloads 를 통해서 여러 생성자르 만들 수 있음
- 비공개로 getter / setter 다 있음
5.6
package travelator.mobile
import java.util.*
class PreferencesView(
//가변 객체에 대한 불변 참조
private val preferences: UserPreferences
) : View() {
private val greetingPicker = GreetingPicker()
private val localePicker = LocalePicker()
private val currencyPicker = CurrencyPicker()
override fun show() {
greetingPicker.greeting = preferences.greeting
localePicker.locale = preferences.locale
currencyPicker.currency = preferences.currency
super.show()
}
protected fun onGreetingChange() {
preferences.greeting = greetingPicker.greeting
}
protected fun onLocaleChange() {
preferences.locale = localePicker.locale
}
protected fun onCurrencyChange() {
preferences.currency = currencyPicker.currency
}
}
internal class GreetingPicker {
var greeting: String = TODO()
}
internal class LocalePicker {
var locale: Locale = TODO()
}
internal class CurrencyPicker {
var currency: Currency = TODO()
}
5.7
package travelator.mobile
import java.util.*
class PreferencesView(
//가변 객체에 대한 불변 참조
private val preferences: UserPreferences
) : View() {
private val greetingPicker = GreetingPicker()
private val localePicker = LocalePicker()
private val currencyPicker = CurrencyPicker()
//상태 변경을 막기 위해 변경한 내용을 적용한 복사본을 돌려주도록 할 것
fun showModal(): UserPreferences {
greetingPicker.greeting = preferences.greeting
localePicker.locale = preferences.locale
currencyPicker.currency = preferences.currency
show()
return preferences
}
protected fun onGreetingChange() {
preferences.greeting = greetingPicker.greeting
}
protected fun onLocaleChange() {
preferences.locale = localePicker.locale
}
protected fun onCurrencyChange() {
preferences.currency = currencyPicker.currency
}
}
internal class GreetingPicker {
var greeting: String = ""
}
internal class LocalePicker {
var locale: Locale = Locale.UK
}
internal class CurrencyPicker {
var currency: Currency = Currency.getInstance(Locale.UK)
}
- 원본 객체의 상태를 막기 위해서, 변경한 내용을 갖는 복사본을 돌려주게 할 것이다.
- 현재는 기존의 값을 동일하게 리턴한다.
5.8
package travelator.mobile
class Application(
//가변 객체에 대한 불변 참조
private val preferences: UserPreferences // 변경 불가 value
) {
fun showWelcome() {
WelcomeView(preferences).show()
}
fun editPreferences() {
PreferencesView(preferences).show()
}
}
=============================================
class Application(
// 가변 객체에 대한 가변 참조로 변경
private var preferences: UserPreferences // <1>
) {
fun showWelcome() {
WelcomeView(preferences).show()
}
fun editPreferences() {
preferences = PreferencesView(preferences).showModal()
}
}
- 복사본을 줄 것이기 때문에, 불변 참조가 아닌 가변 참조로 바꾼다. ( val → var )
5.9
package travelator.mobile
import java.util.*
class PreferencesView(
private var preferences: UserPreferences
) : View() {
private val greetingPicker = GreetingPicker()
private val localePicker = LocalePicker()
private val currencyPicker = CurrencyPicker()
fun showModal(): UserPreferences {
greetingPicker.greeting = preferences.greeting
localePicker.locale = preferences.locale
currencyPicker.currency = preferences.currency
show()
return preferences
}
protected fun onGreetingChange() {
preferences = UserPreferences(
greetingPicker.greeting,
preferences.locale,
preferences.currency
)
}
protected fun onLocaleChange() {
preferences = UserPreferences(
preferences.greeting,
localePicker.locale,
preferences.currency
)
}
protected fun onCurrencyChange() {
preferences = UserPreferences(
preferences.greeting,
preferences.locale,
currencyPicker.currency
)
}
}
internal class GreetingPicker {
var greeting: String = ""
}
internal class LocalePicker {
var locale: Locale = Locale.UK
}
internal class CurrencyPicker {
var currency: Currency = Currency.getInstance(Locale.UK)
}
- 이제 프로퍼티가 변경되면 새로운 UserPreferences 를 만든다.
- 기존의 값을 변경하던 setter 가 사라짐
package travelator.mobile
import java.util.*
data class UserPreferences(
val greeting: String,
val locale: Locale,
val currency: Currency
)
- 기존의 값을 바꾸지 않으니, UserPreferences를 data 클래스로 바꾼다.
- val (value) 로 프로퍼티가 있으면 setter가 생성 안됨
5.11
package travelator.mobile
import java.util.*
class PreferencesView : View() {
private val greetingPicker = GreetingPicker()
private val localePicker = LocalePicker()
private val currencyPicker = CurrencyPicker()
fun showModal(preferences: UserPreferences): UserPreferences {
greetingPicker.greeting = preferences.greeting
localePicker.locale = preferences.locale
currencyPicker.currency = preferences.currency
show()
return UserPreferences(
greeting = greetingPicker.greeting,
locale = localePicker.locale,
currency = currencyPicker.currency
)
}
}
internal class GreetingPicker {
var greeting: String = ""
}
internal class LocalePicker {
var locale: Locale = Locale.UK
}
internal class CurrencyPicker {
var currency: Currency = Currency.getInstance(Locale.UK)
}
- 프로퍼티에 가변 참조로 두는것도 별로니, 참조를 제거한다.
5.12
class Application(
//가변 객체에 대한 불변 참조
private val preferences: UserPreferences // 변경 불가 value
) {
fun showWelcome() {
WelcomeView(preferences).show()
}
fun editPreferences() {
PreferencesView(preferences).show()
}
}
=============================================
class Application(
// 가변 객체에 대한 가변 참조로 변경
private var preferences: UserPreferences // <1>
) {
fun showWelcome() {
WelcomeView(preferences).show()
}
fun editPreferences() {
preferences = PreferencesView(preferences).showModal()
}
}
=============================================
class Application(
private var preferences: UserPreferences
) {
fun showWelcome() {
WelcomeView(preferences).show()
}
fun editPreferences() {
preferences = PreferencesView().showModal(preferences)
}
- 가변 객체의 위험을 더 윗단으로 올린다.
- 나머지를 다 불변으로 만들어서, 한곳에서 관리하도록 한다.
- 가변 객체에 대한 불변 참조 → 불변 객체에 대한 가변 참조로 변경!
반응형
'개발 > java basic' 카테고리의 다른 글
제네릭이란 무엇일까 (0) | 2024.11.12 |
---|---|
자바에서 코틀린 - 6장 자바에서 코틀린 컬렉션으로 (0) | 2023.04.17 |
자바 기본 ( 18 ) - 예외처리 (0) | 2020.11.03 |
자바 기본 (17) - 추상, 인터페이스 (0) | 2020.10.08 |
자바 기본 (16) - 상속, 다형성 (0) | 2020.10.07 |
Comments