delpho

Java에 대하여 - 3 본문

CS

Java에 대하여 - 3

delpho 2022. 6. 10. 00:44

1. SOLID(객체지향 5대원칙)에 대해서 설명해주세요.

 

 

# 객체지향 프로그래밍의 5가지 설계 원칙 (SOLID)

  • SOLID = 객체지향 프로그래밍을 하면서 지켜야하는 5대 원칙
    • SRP(단일 책임 원칙), OCP(개방-폐쇄 원칙), LSP(리스코프 치환 원칙), DIP(의존 역전 원칙), ISP(인터페이스 분리 원칙)
  • SOLID 원칙을 철저히 지킨다면?
    • 시간이 지나도 변경 용이
    • 유지보수와 확징이 쉬운 프로그램 개발 가능

 

 

1. SRP (단일 책임 원칙, Single Responsibility Principle)

  • 하나의 모듈은 한 가지 책임을 가져야 한다는 것
    • 즉, 모듈이 변경되는 이유가 한가지여야 함
  • 어떤 클래스가 단 하나의 책임 만을 갖고 있다면, 특정 액터로부터 변경을 특정할 수 있으므로 해당 클래스를 변경해야 하는 이유와 시점이 명확해짐!
    • 만약 어떤 모듈이 여러 액터에 대해 책임을 가지고 있다면 여러 액터들로부터 변경에 대한 요구가 올 수 있으므로, 해당 모듈을 수정해야 하는 이유 역시 여러 개가 될 수 있다
    • 시스템이 커질수록 극대화되는데, 시스템이 커지면서 서로 많은 의존성을 갖게되는 상황에서 변경 요청이 오면 딱 1가지만 수정하면 되기 때문이다.

 

@Service
@RequiredArgsConstructor
public class UserService {

	private final UserRepository userRepository;

	public void addUser(final String email, final String pw) {
		final StringBuilder sb = new StringBuilder();

		for(byte b : pw.getBytes(StandardCharsets.UTF_8)) {
			sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
		}

		final String encryptedPassword = sb.toString();
		final User user = User.builder()
				.email(email)
				.pw(encryptedPassword).build();

		userRepository.save(user);
	}
}
  • 해당 UserSevice의 addUser의 기능 = 사용자 정보 받은 후, 비밀번호 암호화하여 DB에 저장
    • 여러 상황으로부터 코드 수정이 발생할 수 있음!
      • 기획팀 : 사용자 추가 시 Role에 대한 정의 필요
      • 보안팀 : 암호화 방식 개선 필요
      • 등등
  • 따라서, UserService가 가지고 있는 비밀번호 암호회 책임 분리 필요!
    • 별도의 클래스를 만들어 기능 분리!

 

@Component
public class SimplePasswordEncoder {

	public void encryptPassword(final String pw) {
		final StringBuilder sb = new StringBuilder();

		for(byte b : pw.getBytes(StandardCharsets.UTF_8)) {
			sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
		}

		return sb.toString();
	}
}

@Service
@RequiredArgsConstructor
public class UserService {

	private final UserRepository userRepository;
	private final SimplePasswordEncoder passwordEncoder;

	public void addUser(final String email, final String pw) {
		final String encryptedPassword = passwordEncoder.encryptPassword(pw);

		final User user = User.builder()
				.email(email)
				.pw(encryptedPassword).build();

		userRepository.save(user);
	}
}

 

 

 

 

2. OCP (개방-폐쇄 원칙, Open-Closed Principle)

  • 확장에 대해 열려있고 수정에 대해서는 닫혀있어야 한다는 원칙

 

 

3. LSP (리스코프 치환 원칙, Liskov Substitution Principle)

  • 하위 타입은 상위 타입을 대체할 수 있어야 한다는 것
    • 해당 객체를 사용하는 클라이언트는 상위 타입이 하위 타입으로 변경되어도, 차이점을 인식하지 못한 채 상위 타입의 퍼블릭 인터페이스를 통해 서브 클래스를 사용할 수 있어야 한다는 것

 

4. DIP (의존 역전 원칙, Dependency Inversion Principle)

  • 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 되며, 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 한다는 것

 

5. ISP (인터페이스 분리 원칙, Interface segregation principle)

  • 목적과 관심이 각기 다른 클라이언트가 있다면 인터페이스를 통해 적절하게 분리

 

 

 

 

 

 


2. 동일성(identity)와 동등성(equality)에 대해 설명해주세요. (equals(), ==)

 

 

 

# 동등성 (equality)

  • 두 개의 객체(변수)가 같은 정보(값)을 가지고 있는 경우
  • 예를들어, 두 변수의 값이 같고 주소값이 다를때, 두 객체는 동등하다.

 

 

# 동일성 (identity)

  • 두 개의 객체(변수)가 완전히 같은 경우
    • 두 객체가 사실상 하나의 객체로 봐도 무방할 경우 (주소값이 같을때)
  • 원시 타입(Primitive)은 객체가 아니기때문에 주소가 없으므로 값이 같다면 동일하다. (==)

 

 

# String의 특이한점

  1. 참조타입이지만 원시타입처럼
    • String은 정확하게는 reference 타입이지만 new 가 아닌 primitve 타입처럼 초기화 가능! (String st = "aaa";)
    • 자바에서 문법적으로 허락 (특별대우)
String st1 = "aaa";
String st2 = "aaa";

System.out.println(st1==st2);

 

 

2. String Constant Pool

  1. 리터럴 값으로 초기화할 경우
    • Heap 영역안에 특별한 메모리 공간인 String Constant pool에 저장됨
      • String constant pool에 존재하는 리터럴 값 사용하면, 해당 참조값 그대로 사용
  2. new  키워드를 통해 초기화할 경우
    • 일반 객체와 같이 Heap 영역에 동적으로 메모리 공간이 할당됨
      • 같은 문자열이더라도 새롭게 생성됨

String strA = "abc";
String strB = new String("abc");
String strC = "abc";
String strD = new String("abc");

System.out.println(strA==strB); //false
System.out.println(strA==strC); //true
System.out.println(strB==strD); //false

 

 

  • 결과는 true
  • 문자열 상수에 대해서 문자열이 동일할 경우 하나의 인스턴스만 생성하고, 이를 공유하도록 함
  • "aaa"라는 문자열이 메모리에 생성되면서 st1에 주소값을 넘겨주었고, st2를 생성하는데 이미 생성된 "aaa" 문자열과 똑같으므로 새로 메모리에 생성하지 않고 기존에 생성된 "aaa" 문자열의 주소를 돌려줘서 공유하게 하는 것!
  • String만 특별대우 해주는 이유!
    • 문자열 이라는 특성 때문
    • 인스턴스의 생성이란 사실 시스템에 부담이 되는 요소!!
      • 그런데 문자열을 표현할 때 마다 인스턴스가 생성되니, 이를 줄일 필요가 있었던 것

 

 

 


3. 원시타입과 참조타입의 차이에 대해 설명해주세요.

 

 

# 원시타입

  • 정수, 실수, 문자, 논리 리터럴 등 실제 데이터 값을 저장하는 타입
  • 장점
    • 접근 속도가 빠르다
      • 원시 타입은 스택 공간에 값이 존재
      • 참조 타입은 하나의 인스턴스이기 때문에 참조 변수는 스택 영역에, 실제 객체는 힙 공간에 존재
        • 따라서, 과정이 하나 더 추가되니 접근속도 차이 발생

 

 

 

# 참조 타입 (reference 타입)

  • 우리가 흔히 사용하는, new 연산자로 생성할 수 있는 객체
  • 기본 타입을 제외한 타입들을 말한다. 객체의 주소를 저장하는 타입 
    • new 연산자란 간단히 클래스의 객체를 생성하는 연산자라고 표현할 수 있지만
    • 좀 더 상세하게 얘기하면 클래스의 객체를 생성하여 메모리에 올리고, 그 참조변수를 반환해주는 연산자
  • 원시 타입과의 차이점 = 참조변수
    • 참조변수 = 메모리에 올라간 객체를 가리키는 주소값
    • reference 타입 자료형을 비교할 때는 primitive 타입 변수와는 달리, 값의 비교가 두 가지의 의미를 가지게 됨
      • 동등성, 동일성

 

 

 

따라서,

 

# 원시타입, 참조 타입 차이점

 

1. Null을 담을 수 있는가?

  • 기본 타입은 null을 담을 수 x
  • 참조 타입은 가능

 

2. 제네릭 타입에서 사용할 수 있는가?

  • 기본 타입은 제네릭 타입에서 사용할 수 x
  • 참조 타입은 가능

 

3. 값의 비교 시 주소값을 참고하는가

  • 기본 타입은 참고 x
  • 참조 타입은 참고 o

 

4. 접근 속도, 메모리 양

  • 기본 타입이 참조타입에 비해 접근 속도가 훨씬 빠르고 메모리 양도 훨씬 적게 사용한다.

 

 



4. String, StringBuilder, StringBuffer 각각의 차이에 대해 설명해주세요.

 

1. String은 불변 객체, StringBuilder, StringBuffer는 가변 객체

  • String의 불변성으로 인해, 문자열 수정시 메모리 낭비가 생김
    • 이를 해결하기 위해 StringBuilder, StringBuffer 등장

 

2. StringBuilder는 동기화 미지원, StringBuffer는 동기화 지원

  • StringBuilder
    • 동기화를 미지원해서 멀티스레드 환경에 사용은 부적합
    • 대신, 단일 스레드에서의 성능은 StringBuffer보다 뛰어남
  • StringBuffer
    • 동기화를 지원해서 멀티스레드 환경에서 안전 (내부 메서드 별로 synchronized 키워드가 선언)
    • 동기화 작업을 거쳐야하기때문에 속도 성능은 떨어짐.
  • String
    • 불변 객체이기때문에 멀티스레드 환경에서 안전

 

따라서...

String                :  문자열 연산이 적고 멀티쓰레드 환경일 경우
StringBuffer     :  문자열 연산이 많고 멀티쓰레드 환경일 경우
StringBuilder   :  문자열 연산이 많고 단일쓰레드이거나 동기화를 고려하지 않아도 되는 경우  

 

 

 



5. Checked Exception과 Unchecked Exception에 대해 설명해주세요.

 

# 예외

  • 입력 값에 대한 처리가 불가능하거나, 프로그램 실행 중에 참조된 값이 잘못된 경우 등 정상적인 프로그램의 흐름을 어긋나는 것

 

# 예외 종류

  • Checked Exception
    • RuntimeException을 상속하지 않는 클래스
    • Compile 시점에서 Exception 발생
    • 반드시 에러 처리를 해야함 (try/catch or throw)
    • ex. FileNotFoundException, ClassNotFoundException
  • Unchecked Exception
    • RuntimeException을 상속하는 클래스
    • Runtime 시점에서 Exception 발생이 확인
    • 에러 처리를 강제하지 않음
    • ex. NullPointerException, ClassCastException

 

 

 

# RuntimeException

  • 말그대로 런타임 중에 발생
  • 명시적으로 예외 처리를 하지 않아도 되는 exception
  • ex. System 환경적으로나, Input Value가 잘못된 경우, 의도적으로 개발자가 설정한 조건을 위배했을 때 throw 되게 하는 등

 

 

 

 

 


 

 

출처

https://mangkyu.tistory.com/194

 

[OOP] 객체지향 프로그래밍의 5가지 설계 원칙, 실무 코드로 살펴보는 SOLID

이번에는 객체 지향 프로그래밍의 5가지 핵심 원칙인 SOLID에 대해 알아보고자 합니다. 실제로 애플리케이션을 개발할 때 어떻게 적용할 수 있을지 구체적인 예시를 들어 살펴보고자 합니다. 아

mangkyu.tistory.com

https://joont.tistory.com/143

 

동일성, 동등성

두 변수의 값을 비교하기 위해, 우리는 == 연산자를 사용했습니다. 하지만 이 연산자를 이용한 비교는, primitive(원시) 타입의 자료형에만 해당하는 사항입니다. ( primitive 타입 자료형이란 int, doubl

joont.tistory.com

https://siyoon210.tistory.com/139

 

Java에서 원시타입 vs 참조타입 어떤 걸 사용해야 할까?

[개요] 자바에서 숫자를 다루기 위한 타입들은 크게 두 가지로 분류할 수 있습니다. 하나는 '원시 타입(primitive type)'이고, 또 다른 하나는 참조 타입(reference type)'입니다. 원시 타입은 (int, double, boo

siyoon210.tistory.com

https://week-year.tistory.com/141

 

[Java] 기본 타입 vs 참조 타입 (feat. heap, stack 영역)

1. 기본 타입 (Primitive type) 정수, 실수, 문자, 논리 리터럴을 저장하는 타입을 말하고 원시 타입이라고도 부른다. 정수형 : byte, short, int, long 실수형 : float, double 문자형 : char 논리형 : boolean..

week-year.tistory.com

https://velog.io/@heoseungyeon/StringBuilder%EC%99%80-StringBuffer%EB%8A%94-%EB%AC%B4%EC%8A%A8-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EC%9E%88%EB%8A%94%EA%B0%80

 

StringBuilder와 StringBuffer는 무슨 차이가 있는가?

Java에서 String 클래스는 불변성을 갖습니다. 그래서 변하지 않는 문자열을 자주 사용하는 경우엔 좋은 성능을 기대할 수 있습니다. 하지만 문자열에 대한 변경이 자주 일어나는 프로그램에서 Stri

velog.io

https://ifuwanna.tistory.com/221

 

[Java] String, StringBuffer, StringBuilder 차이 및 장단점

Java 에서 문자열을 다루를 대표적인 클래스로 String , StringBuffer, StringBuilder 가 있습니다. 연산이 많지 않을때는 위에 나열된 어떤 클래스를 사용하더라도 이슈가 발생할 가능성은 거의 없습니다

ifuwanna.tistory.com

https://madplay.github.io/post/java-checked-unchecked-exceptions

 

자바 예외 구분: Checked Exception, Unchecked Exception

자바에서 예외는 어떻게 구분할까? Checked Exception과 Unchecked Exception의 차이는 무엇일까?

madplay.github.io

https://velog.io/@gillog/JavaException-Error%EC%9D%98-%EC%B0%A8%EC%9D%B4

 

'CS' 카테고리의 다른 글

Spring에 대하여 - 5  (0) 2022.06.19
Java에 대하여 - 4  (0) 2022.06.10
Java에 대하여 - 2  (0) 2022.06.08
Java에 대하여 - 1  (0) 2022.06.08
Spring에 대하여 - 3  (0) 2022.06.04