delpho
Java에 대하여 - 4 본문
1. 강한 결합과 느슨한 결합이 무엇인지 설명해주세요.
# 의존성
- 어떤 클래스A가 다른 클래스(B) 또는 B의 인터페이스를 이용할때 A가 B에 의존한다고 한다.
- A는 B없이 작동할 수 없음
- 여기서 A는 dependant / B는 dependency라고 함
- dependant는 자신의 dependencies들에게 의존
- 의존성이 높다는건(강하다는건) A객체를 수정했을때, 그 객체와 결합된 B에서도 코드를 수정해야되는 경우가 생기는 것
- 이때, 두 클래스는 결합(coupled)되어 있음.
- 두 클래스 사이의 결합은 강할수도, 느슨할 수도 있음
- 의존성이 강한지 약한지에 따라 달림
- 의존성, 결합은 방향이 존재
- A가 B에게 의존한다고해서 B가 A에 꼭 의존적인것은 아님!
# 결합도
- 서로 다른 모듈 간에 상호 의존하는 정도 또는 연관된 관계를 의미
# 의존도가 낮거나 결합도가 느슨할 경우
- 요구사항 변화에 자유롭다.
- 테스트 코드 작성에 유리하다.
- 코드의 중복을 줄일 수 있다.
# 강한 결합
- 어떠한 객체가 다른 객체에 강한 의존성을 가지고 있음
class SamsungTV {
public void seeing() {
System.out.println("냠냠");
}
}
class People {
SamsungTV c = new SamsungTV();
public void startSeeing() {
t.seeing();
}
}
- People 클래스는 SamsungTV 클래스가 없으면 정의 못함
- SamsungTV 클래스를 다른 tv으로 바꾸게 되면 or 메소드를 바꾸게 되면 People 클래스의 코드가 대부분 변경됨
--> 유지보수 측면에서 문제
# 느슨한 결합
- 결합되어있는 클래스간의 의존성을 약하게 만듬
- 다형성, 디자인 패턴(팩토리) 이용
- 다형성 이용
- interface 이용 + 상속 (메서드 재정의)
- 인터페이스를 이용함으로써 모든 TV 클래스가 같은 메소드들을 가질 수 밖에 없도록 강제할 수 있게 된것
- 이 메인 클래스에서는 TV 인터페이스 타입의 변수로 SamsungTV 객체를 참조한다.
- 이런 묵시적 형변환 (Promotion)을 이용해서 객체를 참조하게 되면 SamsungTV 를 LgTV 객체로 바꾸고 싶을 때,
참조하는 객체만 변경하면 되기 때문에 객체를 바꾸는게 아주 쉬워짐 - 수정이 최소화됨!
public interface TV {
public void powerOn();
}
public class SamsungTV implements TV {
public SamsungTV() {}
@Override
public void powerOn() {
System.out.println("SamsungTV----전원 켠다.");
}
}
public class LgTV implements TV {
public LgTV() {}
@Override
public void powerOn() {
System.out.println("LgTV----전원 켠다.");
}
public class TVuserPolymorphism {
public static void main(String[] args) {
TV tv = new SamsungTV();
// or TV tv = new LgTV();
tv.powerOn();
}
}
- 디자인 패턴(팩토리) 이용
- Factory 패턴은 사용할 객체 생성을 캡슐화 해서 TV.java 클래스와 TVuserPolymorphism.java 클래스 사이를 느슨한 결합 상태로 만들어줌
- Factory 를 사용하면 인터페이스를 사용할 때 보다 결합도도 훨씬 낮아지고,
- TVuserPolymorphism 클래스 내부적으로 코드의 변경이 일어날 필요 없이, Factory를 통해 값을 전달하여 원하는 객체를 받아 사용 가능
public class BeanFactory {
public BeanFactory() {}
public Object getBean(String beanName) {
if (beanName.equals("samsung")) {
return new SamsungTV();
} else {
return new LgTV();
}
}
}
public class TVuserFactory {
public static void main(String[] args) {
BeanFactory factory = new BeanFactory();
TV tv = (TV) factory.getBean("samsung");
tv.powerOn();
}
}
2. 직렬화와 역직렬화에 대해서 설명해주세요.
# 직렬화 역직렬화 필요성
- 흔히 객체를 직렬화 한다 라는 표현을 사용
- 즉, 데이터를 쓰거나 읽을 수 있게 지원하는 의미
- 디스크로의 저장 or 네크워크로의 데이터 전송에서 많이 사용
- 객체를 디스크에 저장하기 위해서
# 직렬화 (Serialization)
- 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 시스템에서도 사용할 수 있도록 연속적인 바이트 형태로 데이터 변환하는 기술
- JVM의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술
- 객체들의 데이터를 연속적인 데이터로 변형하여 Stream을 통해 데이터를 읽도록 해줌
- 주로 객체들을 통째로 파일로 저장하거나 전송하고 싶을 때 주로 사용
# 직렬화 과정
- 직렬화가 가능한 클래스에 implements Serializable 하기
- 여러가지 상황에 따라 직렬 가능한 클래스와 데이터가 결정
- Serializable 인터페이스를 implements
- Serializable 없는 경우
- 보통의 경우는 직렬화가 불가능
- Serializable을 implement한 클래스를 상속받은 경우 직렬화 가능
- transient를 이용하여 직렬화 대상에서 제외
- 보통 클래스의 멤버변수 전부 직렬화 대상에 해당
- but 멤버변수의 일부를 제외하고 싶다면 transient를 통해 지정
- 다른 객체를 멤버변수로 가지고 있는 경우
- Serializable 인터페이스를 구현한 클래스가 하나라도 없다면 직렬화불가
- 여러가지 상황에 따라 직렬 가능한 클래스와 데이터가 결정
# 역직렬화 (Deserialization)
- 바이트로 변환된 데이터를 다시 객체로 변환하는 기술
- 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 기술
- 직렬화된 파일 등을 역으로 직렬화하여 다시 객체의 형태로 만드는 것
- 저장된 파일을 읽거나 전송된 스트림 데이터를 읽어 원래 객체의 형태로 복원
3. 자바의 동시성 이슈(공유자원 접근)에 대해 설명해주세요.
# 동시성 이슈란
- 스레드 = cpu 작업의 한단위
- 멀티스레드 방식 = 멀티태스킹을 하는 방식 중, 한 코어에서 여러 스레드를 이용해서 작업을 처리하는 방식
- 멀티 스레드를 이용하면 여러 스레드가 동시에 하나의 자원을 공유하고 있기 때문에 같은 자원을 두고 교착상태(deadlock) 같은 문제가 발생하는 것
# 동시서 제어 방법
1. 암시적 Lock (synchronized)
문제가 된 메서드, 변수에 synchronized 키워드 추가
2. 명시적 Lock
직접적으로 Lock 객체를 생성하여 사용
class Count {
private int count = 0;
private Lock lock = new ReentrantLock();
public int view() {
return count++;
}
public Lock getLock(){
return lock;
};
}
3. 스레드 안전한 객체 사용
- concurrent 패키지는 각종 스레드 안전한 컬랙션을 제공
- 불변 객체 사용
4. Mutable 객체와 Immutable 객체의 차이점에 대해 설명해주세요.
# Mutable 객체
- 객체 생성 이후에도 객체의 속성이 변할 수 있음을 의미
- 불변객체와 다르게 heap영역에 생성된 객체를 변경 가능
- 대표적인 가변 객체는 List, ArrayList, HashMap,StringBuilder,StringBuffer 등
- 가변객체를 multi-thread 환경에서 사용하려면 별도의 동기화 처리를 해줘야함
- 동기화 처리된 객체중 하나가 StringBuffer
- Java에선 객체가 참조를 통해 공유되기 때문에 어떤 스레드에서 객체의 값을 변경할지 모름
- 그렇기 때문에 MUTABLE 객체는 자연스럽게 ‘thread-not-safe’
# Immutable 객체
- 객체 생성 이후에 객체의 속성이 변할 수 없음을 의미
- 힙 영역에 저장된 값을 수정할 수 없다
- new 연산자로 객체를 생성하면 heap영역에 객체가 생기고 래퍼런스 값을 가지는 변수가 stack에 생길 것이다.
- 오직 새 객체를 만들어 래퍼런스 값을 주는 재 할당만이 가능
String a = "Star";
a = a.concat("Craft");
- StarCraft라는 새로운 객체를 만들어서 a에 재할당된 것
- 대표적으로 String, Boolean, Integer, Float, Long 등이 있다
- 객체이므로 String을 제외하면 primitive의 래퍼타입
# class 불변 객체 만들기
- 클래스를 final로 선언 (클래스 상속 못하도록)
- 모든 멤버변수를 private, final로 설정
- setter 메서드를 구현 X
- 객체 생성을 위해 static 팩토리 메소드 제공 (기본생성자가 아닌 팩토리 메소드를통해 객체 생성 강요)
- 멤버변수 중 가변객체타입의 field 변수가 있을 경우, 그 가변객체 타입의 field변수에 대해 직접적으로 접근하지 못하도록 copy 객체를 생성하여 새로운 인스턴스를 반환하도록 방어적 복사본 전략을 사용
# 불변 객체 장단점
- 장점
- 객체에 대한 신뢰도가 올라간다.
- multi-thread 환경에서 동기화 처리 없이 객체를 공유 가능하다.(쓰레드에 안전하다 라고함)
- 단점
- 객체의 값이 할당될 때 마다 새로운 객체가 필요하다. 따라서 메모리 누수와 성능저하를 발생시킬 수 있다.
# Mutable vs Immutable
생성된 이후 수정 가능 | 생성된 이후 수정 불가능 |
이미 존재하는 객체에 재할당(값 변경) | 이미 존재하는 객체이더라도 새로운 객체를 생성하여 재할당 |
값을 변경할 수 있는 메소드 제공 | 값을 변경할 수 있는 메소드 제공 x |
Mutable class일 경우 Getter와 Setter 존재 | Immutable class일 경우 Getter와 Setter 미존재 |
thread safe하지 않을 수 있음(병렬처리 시 값 보장할 수 없게 됨) | thread safe(병렬처리 시 문제 없음) |
StringBuffer, StringBuilder, java.util.Date 등이 해당 | Legacy classes, Wrapper classes, String class 등이 해당 |
5. 자바에서 null을 안전하게 다루는 방법에 대해 설명해주세요.
# null 이란
- 객체가 없거나 상태가 정의되지 않은 상태
# null 참조
- 특별한 값이 없음을 나타내려고 null을 도입했고 이 값을 사용하려고 할 때 오류를 내도록 설계
- 두 참조값이 null일 때 두 참조는 동일하다고 판단
- null은 모든 타입의 멤버가 될 수 있음
- 참조 변수 사용 시 널을 확인해야 함
# null과 관련된 문제
- 런타임에 NPE(NullPointerException)라는 예외를 발생시킬 수 있습니다.
- NPE 방어를 위해서 들어간 null 체크 로직 때문에 코드 가독성과 유지 보수성이 떨어집니다.
# null을 안전하게 다루는 방법
- @NonNullApi를 패키지 레벨에 선언
- 패키지 하위의 class method의 인자 또는 리턴이 null일 경우 IDE에서 Warning으로 알려줌
- @NotNull 이나 @Nullable 어노테이션을 사용
- 메소드가 null safe인지 아닌지를 annotation을 사용하여 표시하는 것이 좋다.
- 그래야 컴파일러가 여러분이 미처 확인하지 못 한 또는 굳이 확인할 필요가 없는 부분에서 null check를 하도록 도와줄 수 있다.
- Optional 클래스 사용
- “존재할 수도 있지만 안 할 수도 있는 객체”, 즉, “null이 될 수도 있는 객체”을 감싸고 있는 일종의 래퍼 클래스
- 직접 다루기에 위험하고 까다로운 null을 담을 수 있는 특수한 그릇
- Optional 장점
- NPE를 유발할 수 있는 null을 직접 다루지 않아도 됩니다.
- 수고롭게 null 체크를 직접 하지 않아도 됩니다.
- 명시적으로 해당 변수가 null일 수도 있다는 가능성을 표현할 수 있습니다. (따라서 불필요한 방어 로직을 줄일 수 있습니다.)
- “존재할 수도 있지만 안 할 수도 있는 객체”, 즉, “null이 될 수도 있는 객체”을 감싸고 있는 일종의 래퍼 클래스
출처
https://velog.io/@huttels/%EC%9D%98%EC%A1%B4%EC%84%B1%EC%9D%B4%EB%9E%80
의존성이란
어떤 클래스A가 다른 클래스 또는 인터페이스B를 이용할때 A가 B에 의존한다고 한다.A는 B없이 작동할 수 없고 B를 재사용하지 않으면 A또한 재사용할 수 없다.이러한 상황에서 클래스A를 dependant
velog.io
https://madplay.github.io/post/coupling-and-cohesion-in-software-engineering
결합도와 응집도는 무엇일까?
낮은 결합도(Coupling)와 높은 응집도(Cohesion)를 갖도록 설계해야 하는 이유는 무엇일까?
madplay.github.io
의존성이란
의존성이란 나는 의존성 주입이라는 단어를 스프링을 공부하면서 처음 들었다. '컨테이너에서 관리될 객체를 지정해주고, 주입 받을 위치를 표시해주면 마법같은 일이 일어나 해당 객체가 들어
www.blog.ecsimsw.com
[Java] 강한 결합과 약한 결합
객체의 의존 관계에서 강한 결합이란, 어떠한 객체가 다른 객체에 강한 의존성을 가지고 있음을 뜻한다.그렇다면 의존성을 가지고 있다는 것이 무엇인가?의존성이 강하다는 것은 무엇인가?에
velog.io
https://swk3169.tistory.com/185
Coupling이란? Tight Coupling vs Loose Coupling 정리
- Coupling의 정의 coupling이란 서로 상호작용하는 시스템들간의 의존성을 의미한다. 의존성은 실질적 의존성과 인위적 의존성으로 나뉠 수 있다. 실질적 의존성은 한 시스템이 소비하는 다른 시스
swk3169.tistory.com
Java 객체 직렬화(Serialization) 와 역직렬화(Deserialization)
Java의 직렬화와 역직렬화에 대해서 알아봅시다. 정의 Java에서 말하는 직렬화(Serialization)란 과연 뭘까? 말그대로 객체를 직렬화하여 전송 가능한 형태로 만드는 것을 의미한다. 객체들의 데이터
flowarc.tistory.com
https://hanbulkr.tistory.com/14
직렬화(Serialization)와 역직렬화(Deserialization)
개요 객체를 디스크에 저장하기 위해서는 반드시 Serialize의 개념을 알고 있어야 한다. 흔히 객체를 직렬화 한다 라는 표현을 사용합니다. 즉, 데이터를 쓰거나 읽을 수 있게 지원하는 의미로 개
hanbulkr.tistory.com
https://steady-coding.tistory.com/576
[Java] 직렬화와 역직렬화
java-study에서 스터디를 진행하고 있습니다. 데이터 직렬화와 역직렬화 데이터 직렬화 메모리를 디스크에 저장하거나, 네트워크 통신에 사용하기 위한 형식으로 변환하는 것이다. 데이터 역직렬
steady-coding.tistory.com
https://codevang.tistory.com/164
직렬화와 역직렬화 (Serializable)
[ 직렬화 ] 자바의 객체를 외부 데이터로 저장하는 것 객체화된 클래스(인스턴스)의 속성과 데이터를 파일화하여 외부에 저장할 수 있음 [ 역직렬화 ] 직렬화로 저장된 파일을 다시 자바의 객체
codevang.tistory.com
https://cantcoding.tistory.com/41
Immutable,mutable 객체
자바의 객체의 타입에는 Immutable 타입과 mutable타입이 있다. 객체들은 기본적으로 heap영역에 할당되고 stack영역에 래퍼런스 값을 갖는 참조 변수들로 접근 가능하다. immutable(불변) 객체 이름에서
cantcoding.tistory.com
https://choiblack.tistory.com/47
[Java] Mutable과 Immutable
자바의 객체는 기본적으로 힙 영역에 할당되고 스택 영역에 참조값을 갖는 참조 타입 변수를 통해 데이터에 접근한다. 이러한 객체는 Mutable(가변) 객체와 Immutable(불변) 객체로 나눌 수 있다. Immut
choiblack.tistory.com
https://velog.io/@guswlsapdlf/Java%EC%9D%98-Mutable%EA%B3%BC-Immutable
Java의 Mutable과 Immutable
정리하면 Mutable은 객체의 수정을 허용하나, Immutable인 경우 객체의 수정을 허용하지 않는다. 수정이 필요할 경우 Mutable 객체는 기존의 객체에 수정사항을 곧바로 반영한다. 하지만 Immutable 객체의
velog.io
https://www.daleseo.com/java8-optional-after/
자바8 Optional 2부: null을 대하는 새로운 방법
Engineering Blog by Dale Seo
www.daleseo.com
Full of Troves, Blog
초보 개발자의 블로그
eastglow.github.io
Java 에서 널을 안전하게 다루기
null 과 null 로 인해 발생하는 문제 null pointer 와 null reference 널 포인터(null pointer)는 유효한 객체를 참조하지 않는 포인터를 나타내기 위해 예약된 값을 갖는다. 널 포인터는 널 값과는 다른 의미를
ncucu.me
'CS' 카테고리의 다른 글
DB에 대하여 - 1 (0) | 2022.06.19 |
---|---|
Spring에 대하여 - 5 (0) | 2022.06.19 |
Java에 대하여 - 3 (0) | 2022.06.10 |
Java에 대하여 - 2 (0) | 2022.06.08 |
Java에 대하여 - 1 (0) | 2022.06.08 |