일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 디자인 패턴
- Dispatchers
- 리사이클러뷰풀
- flutter
- http 역사
- appcompatacitivity
- 뷰홀더
- NestedScrollView
- 데코레이터 패턴
- Android
- Kotlin
- DiffUtil
- viewModelScope
- AAC
- 안드로이드
- 리사이클러뷰
- appcompatactivity
- apk 빌드 과정
- 프로세스
- recyclerview
- AsyncListDiffer
- 물리 메모리
- 플로이드워셜
- GetX
- http발전과정
- 상태관리
- 절대 주소
- 자이고트
- 운영체제
- 내부 단편화
- Today
- Total
hong's android
[Java] 자바 정리 본문
래퍼 클래스로 계산하면 안될까? 원시 타입이 필요한이유
래퍼클래스 참조타입이기때문에 원시타입보다 크다.
원시형의 데이터를 가져오는것보다 래퍼 클래스 형태의 객체를 가져오는것이 비효율적이고 더 느리다. 그 이유는 래퍼 클래스는 객체이다. 래퍼클래스로 된 객체를 메모리에 저장하기 위한 데이터들은 아래와 같습니다. (32비트 기준)
아래와 같습니다.
- housekeeping 정보로 구성된 12 bytes의 object header 공간이 있습니다.
- primitive fields는 각자 정해진 크기만큼 차지합니다.
- reference fields는 4 bytes를 차지합니다.
- array 배열은 16 bytes가 필요합니다. object 공간 12 bytes + array length 공간 4 bytes
- object 크기는 항상 8의 배수만큼의 byte 공간을 차지합니다. '8-byte alignment', 'object alignment' 라고 합니다. 8의 배수만큼의 byte 공간을 맞춰주기 위해 padding 공간을 붙여줍니다.
원시 자료형으로 계산을 하는경우 stack에 있는 value만 가지고 오면되기 때문에 연산을 하기위해 위와 같이 연산에 불필요한 데이터들을 가져올 필요가 없습니다. 그렇기 때문에 원시 자료형이 필요합니다. 스택 오버 플로우의 글을 참고했습니다.
https://stackoverflow.com/questions/14477743/why-are-there-primitive-datatype-in-java
why are there Primitive datatype in Java?
Possible Duplicate: When we have wrappers classes, why primitives are supported? If there are Wrapper classes which make Java pure object-oriented language, then why are there Primitive dataty...
stackoverflow.com
익명 클래스 왜 사용할까?
익명 클래스는 이름이 없는 객체의 선언과 초기화를 함께 할 수 있다. 한번만 사용하는 객체의 경우 새로 클래스를 만들고 구현을 하는것이 번거로운 작업이다. 그렇기에 상속이나 인터페이스 구현을 하는 클래스를 한번만 사용하는 경우 익명 클래스를 사용한다.
예를들어, onclickListener에 리스너 인터페이스 같은 경우 매번 다른 구현을 해야할때가 많으므로 새로운 클래스를 만들고 해당 구현을 하고 객체를 만드는것이 번거롭다. 그렇기 때문에 인터페이스 구현 객체를 선언과 초기화를 동시에 할 수 있는 익명 클래스를 사용하는것이 효율적이다.
한줄 정리 익명 클래스를 사용하는 가장 큰 목적은 부모 클래스를 상속받는 서브 클래스를 생성하지 않고도, 단일 객체를 만들어서 부모 클래스에 정의된 동작에서 행위를 추가할 수 있다는 것이다.
내부 클래스 사용 이유?
하나의 클래스와 논리적 연결이 되는 상황이라면 내부 클래스를 이용할 수 있다. (클래스를 논리적으로 연결).
final 사용 이유는?
변수는 read-only하게 만들 수 있다. 변하지 않는 상수 값에 사용할수있다. 메소드에 붙일 경우 자식 클래스에서 상속이 불가능하다.
변경되면 안되는 값을 만들 수 있고 디버깅에 도움이 된다. String클래스의 내부를보면 final로 배열을 선언해서 불변 형태를 만들었다.
캡슐화란?, 캡슐화 하는 이유는?
관련이 있는 변수와 메소드들을 한 클래스안으로 묶는다. 캡슐화의 핵심은 정보를 외부로 부터 은닉한다. 은닉할때 자바의 접근 제한자를 사용한다. 캡슐화를 통해 외부에선 내부의 동작 방식을 알 필요가 없고 드러나지 않는다. 정보를 은닉화 함으로써 메소드의 동작이 외부에서 변경되는것을 막는다. 변수의 값 또한 마찬가지이다.
접근 제한자 사용이유?
예상치 못한 값 변경으로 인한 Side-effect를 줄일 수 있다. 값이 변경되는 경우의 수를 줄일 수 있어 디버깅에 도움이 된다.
외부에서 접근이 불가능 해야하는(값이 외부에서 함부로 변경이 되면 안되는) 변수들이 값이 변경되면 추적하기가 어렵다.
메모리 할당 시점?
클래스 변수(=static) 해당 클래스를 참조할때 클래스 로더에 의해서 클래스 정보들이 적재되는데 이때 메소드 영역에 적재된다.
인스턴스 변수 인스턴스가 생성될때 힙 영역에 생성된다.
지역 변수/ 매개 변수 메소드가 해당 변수를 호출할때 스택 영역에 생성되는데 메소드가 종료되면 스택 영역에서 제거된다.
아래 블로그를 참고했습니다.
https://inpa.tistory.com/entry/JAVA-☕-그림으로-보는-자바-코드의-메모리-영역스택-힙
[JAVA] ☕ 그림으로 보는 자바 코드의 메모리 영역(스택 & 힙)
자바의 메모리 영역 이번 포스팅에선 자바(JAVA)를 사용하는 입장에서 알아야 할 메모리 구조 및 특징에 대해서 알아보려고 한다. 자바 프로그램이 실행되면 JVM(자바 가상 머신)은 OS로부터 메모
inpa.tistory.com
직렬화란?
Jvm기준으로 객체를 외부에 전송을 해야할때 필요하다. 객체를 바이트 코드로 변환해준다.
serializeVerstionUID 선언 이유는?
직렬화 버전을 선언해준다. serializeVerstionUID을 초기화 하지 않으면 자동으로 생성된다. 만약 이전 직렬화를 할때와 변수의 개수나 종류가 변경되면 serializeVerstionUID 도 변경이 되는데 서버와 통신할때 해당 객체를 받을때 직렬화 했던 상태와 다른 상태인지 확인을 하고 역직렬화를 할 수 있다. 그렇게 된다면 형태가 다른, 잘못된 객체를 받아서 역직렬화를 진행해 오류가 나는 상황을 막는다.
데이터 입출력을 할때 java.io 패키지와 java.nio의 차이점?
스트림 기반으로 입출력하지 않고 버퍼, 채널 기반으로 입출력한다. 버퍼는 처음에 한번에 읽을 데이터들을 버퍼에넣고 스트림은 매번 시스템 콜을해서 불러온다. io는 동기/ 블로킹 nio는 비동기/논블로킹 (블로킹/논블로킹 둘다됨)
io는 동기, 블로킹 방식이기 때문에 한번에 여러개의 처리를 효과적으로 해내기 어렵다. nio는 버퍼 방식으로 데이터 입출력을 하기 때문에 버퍼의 크기가 제한 된다면 한번에 많은 크기의 데이터를 받을 수 없는 경우가 있다. 그렇기 때문에
읽어야할 데이터가 많고 여러 처리를 한꺼번에 하지 않아도 되는경우는 java.io 패키지 사용하는게 효율적이다.
Exception 클래스 구조
exception 하위 클래스는 checked exception과 unchecked exception으로 나뉜다.
.Checked Exception | Unchecked Exception | |
처리 여부 | 반드시 예외 처리 해야함 | 예외 처리 하지 않아도됨 |
트랜잭션 Rollback 여부 | Rollback 안됨 | Rollback 진행 |
대표 Exception | IOException, SQLException | NullPointerException, IllegalArgumentException |
println()이 NullPointerException일어나지 않는 이유는?
그대로 출력하는게 아니라 내부적으로 valueof()를 호출하기 때문에 NullPointerException에러가 발생하지 않는다.
Enum 사용 이유는?
Enum은 같은속성을 가진 상수들을 묶을때 필요함.
따로 하나하나 선언하거나 interface,class를 통해서 상수들을 관리할수 있음.
하지만 가독성이 떨어지거나 서로 다른 개념을 가진 상수를 구분 할 수 없다. 예를을어 comapny.banana == 2와 school.banana ==2 구분이 불가능(인터페이스, 클래스), enum은 comapny.banana와 school.banana를 구분 할 수 있다.
Solid 원칙
소스코드를 읽기 쉽고 확장하기 편하게 하기 위해서 적용할 수 있는 설계 지침이다.
1.SRP(단일 책임 원칙)
클래스는 하나의 책임만 갖는다.
클래스가 여러개의 역할을 수행하게되면 하나의 클래스에 코드가 몰려서 가독성이 좋지 않을 뿐 아니라 여러 역할을 수행하다 보니
다양한 다른 객체들과 의존성이 생길수있고 유지보수가 어려워진다.
2.OCP(개방-폐쇄 원칙)
소프트 웨어 요소는 확장에 열려 있어야 하지만 변경에는 닫혀 있어야한다.
클래스 내부를 변경할 수 있다면 해당 클래스 객체를 사용하는 곳에 영향이 간다. 또한 그 코드를 재사용하기 힘들어진다.
3.LSP(리스코프 치환 원칙)
자식 객체가 부모 객체를 완전히 대체 할 수 있어야한다. (부모 객체와 자식 객체의 일관성)
객체가 가지는 속성을 잘못이해하고 잘못된 확장을 할 경우 상속관계가 불명확해지고 기능이 예상했던것과 다르게 동작할 확률이 높다고 생각한다. 유지보수에 어려움.
4.ISP(인터페이스 분리 원칙)
여러개의 인터페이스를 구현하는것이 범용적인 인터페이스를 구현하는것보다 낫다.
사용하지 않는 인터페이스의 기능을 구현하는것보다 인터페이스를 역할단위로 나눠서 사용하는것만 구현을 한다. 분리된 인터페이스가 확장성이 더 좋기 때문에
5.DIP(의존 역전 원칙)
자주 변화가 일어나는곳에 의존하기보다 변화가 없는곳에 의존한다.
구체화된 클래스는 구체화 되어있기 때문에 변화에 취약하다. 그렇기 때문에 변화가 많은 구체화된 클래스 보다 인터페이스, 추상 클래스를 의존하는게 낫다.
'Develop > Java' 카테고리의 다른 글
[Java] 리플렉션 (0) | 2023.01.16 |
---|---|
[Java] Garbage Collector (0) | 2023.01.02 |
[Java] Map 인터페이스 (0) | 2022.12.31 |
[Java] 자바와 Jvm에 대해서 (0) | 2022.12.26 |
[Java] DeadLock (0) | 2022.12.20 |