레이블이 effective-java인 게시물을 표시합니다. 모든 게시물 표시
레이블이 effective-java인 게시물을 표시합니다. 모든 게시물 표시

2021-12-08

1208 스트림은 주의해서 사용하라

 스트림을 이용하여 이중 for 문을 구현할수있다. 

스트림.of메서드를 사용하여 해당 리스트를 스트림으로 만든다. Arrays.stream() 메서드와 같은 역할을 한다. 



2021-12-05

1205 타입안전이종컨테이너를 고려하라

 


상속할경우- 런타임에도 해당 클래스의 타입이 지워지지 않고 남는다!! 

1205 제네릭과 가변인수를 함께 쓸때에는 신중하라

 

결국엔 List.of 메소드(varargs를 받는) 도 내부적으로 Object[] 배열을 만들어서 하나씩 넣고있다.

새로운 원소를 추가 삭제하는 것이 아니라 단순히 변환하여 전달하는 용도로 쓰여지고 있으므로 safe하다고 말할수있을것이다

근데 웃기는거는 12개? 까지는 of메서드 다 만들어뒀더라 ㅋㅋㅋㅋ 귀엽ㅋㅋㅋ성능최적화인듯 ㅋㅋ

1205 제네릭과 가변인수를 함께 쓸 때는 신중하라

 



가변인수를 받을경우

배열이 내부적으로 생성된다. (Object[])

해당 Object타입의 배열에는 어떠한 타입이든 들어갈수있으므로(배열은 공변)

힙오염이 발생하게 되고

class cast exception이 발생한다.!!


2021-12-04

1204 이왕이면 제네릭 메서드로 만들라

 

제네릭 메서드를 활용하여 타입안전한 메서드를 클라이언트에게제공한다!!!!

1204 이왕이면 제네릭 타입으로 만들라

 제네릭 타입의 stack만들기 

1번 : generic E타입을 받는 배열을 내부적으로 만들고

supressWarnings("unchecked")를 이용.

Object배열을 만든다음에 형변환한다



2번: 내부적으로 Object[] 배열을 만들고

원소를 내보낼떄 (pop()메소드) 에서 E타입으로 캐스팅하는 메소드 만든다



1204 로타입은 사용하지 말라

 

뭐야 결국엔 타입안전 안하다는 거 아니야?? 어이가. 없네??

2021-12-03

1203 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라

 




오버라이드 한 메서드가 부모 클래스의 생성자에서 불리고 있었다.
-> 결과, 하위클래스의 생성자가 불리기도 전에 해당 메소드가 불리게 된다.
해당 오버라이드한 메서드가 하위클래스의 인스턴스를 조작하는 행위를 하고있었기때문에-
NPE가 발생했다!!
호움!!
비슷하게 주의해야 하는경우.
오버라이드한 메소드가 상위클래스 내부의 private메소드를 사용하여 무언가 작업을 하는경우.
상위클래스의 구현변경에 의해 하위클래스가 영향을 받는다!!
ex ) Set클래스를 extends 해서 addAll 메서드를 조작했더니, 영향을 받음...

2021-11-30

1130 finalize 와 cleaner 사용을 피하라 2

 Cleaner manages a set of object references and corresponding cleaning actions.

Cleaning actions are registered to run after the cleaner is notified that the object has become phantom reachable. The cleaner uses PhantomReference and ReferenceQueue to be notified when the reachability changes.

Each cleaner operates independently, managing the pending cleaning actions and handling threading and termination when the cleaner is no longer in use. Registering an object reference and corresponding cleaning action returns a Cleanable. The most efficient use is to explicitly invoke the clean method when the object is closed or no longer needed. The cleaning action is a Runnable to be invoked at most once when the object has become phantom reachable unless it has already been explicitly cleaned. Note that the cleaning action must not refer to the object being registered. If so, the object will not become phantom reachable and the cleaning action will not be invoked automatically.


cleaner 를 우선 만든다.

cleaner객체에게 clean할 객체를 등록한다(register) -> cleanable 객체를 반환해준다. 

혹여나 객체가 수거되지 않을경우 - 안전성을 가한다는 측면에서 , (굳이)  명시적으로 clean을 불러서 해당 객체를 수거할 수 있게된다..는 것같다!!!!!?!!?

이를테면, Autoclosable을 구현한 객체는 close()를 부르면 수거가 된다.

그런데 어떠한 원인에서 이 close()가 호출되지 않았을때, cleaner에게 이 객체를 clean해달라고 register해두면, cleaner가 이 객체를 수거해줄 것이다. (그러나, 완전하지는 않다. 자바는 이러한 객체수거를 개발자가 직접적으로 조절하기를 바라지 않는것같다.)

cleaner의 clean()메서드는 Runnable을 구현하는 스레드이다.  이 스레드를 커스터마이징 한 Runnable & clean할 객체참조를 함께 넘겨주면서 register한다.



2021-11-29

1129 finalizer 와 cleaner 사용을 피하라

 Cleaner 도 finalizer와 비슷하다 (조금 더 낫다고 함? 스레드를 할당할수있다?)

finalize() -> 객체에 대한 참조가 없어졌을때 가비지 컬렉터에 의해 자동적으로 불려지는 메서드


inner class 를 사용하는 것을 자제한다 - static inner class 로 만들자.

-> 왜냐? inner class 를 사용할 경우 - 만약에 외부 클래스가 참조를 잃어버려 필요가 없어진 상황에서도 inner class 가 외부객체의 참조를 유지하기때문에 계속 메모리 회수가 되지 않은 채로 남게 된다. 

심지어 Cleaner 클래스는 system.exit 이 되어 JVM이 메모리에서 내려가야 하는 순간에서도 - 메모리 회수를 보장해주지 않는다...


1129 WeakHashMap과 가비지컬렉션



일반적인 HashMap 의 경우 가지고 있는 key 값이 없어져도 해당 참조 를 유지한다 
그러나 WeakHashMap은 키값없어질경우 참조를 유지하지 않고 - 가비지 컬렉션의 대상에 포함해 버린다.
그래서 아래와 같이 {} 로 빈 해쉬맵이 생겨있는 것을 볼수있음?

알쏭달쏭.. 알듯말듯....

1129 불필요한 객체 생성을 피하라

 

박싱하는 비용으로 무려 5배이상 연산속도에 차이가 나는것을 확인할 수 있다!!!

근데. new Boolean 이거 이상하다- 계속 똑같은 객체 리턴하던데 뭐시여. 이펙티브 자바가 틀린것이여?

1129 동일 인스턴스 equals & hashcode

 

동일한 인스턴스일경우, 해쉬코드 값은 동일

이 해쉬코드 값을 기준으로 equals를 판단한다

equals에서 같다 == 해쉬코드가 같다. 

readResolve() 를 구현하거나 혹은 / enum 타입의 싱글턴일경우, 같은 객체임이 보장되므로 -> 같은 해쉬코드 값을 반환한다. 


1129 java deserialize 메서드

 와!!! 신기한걸 알았다!!!

readResolve() 메서드의 비밀!!!



우선 자바는 기본적으로 - 역직렬화를 할때, new instance를 reflection을 사용해서 생성한다. 

따라서 역직렬화시 항상 새로운 인스턴스객체가 반환되게 된다. 



그러나 readResolve() 메서드를 가지고 있는경우, 해당 readResolve() 메서드가 반환하는 인스턴스로 역직렬화시 반환되는 인스턴스를 대체한다.

그러면 위에서 new instance로 만든 인스턴스는 참조값을 가지지 않으므로, 가비지 컬렉터에 의해서 자동으로 수거가 될것이고 - 우리는 싱글톤 객체를 유지할 수 있게 되는 것이다!!

1129 생성자나 열거타입으로 싱글톤임을 보장하라 2

 



implements serializable 을 구현할시 readObject 에서 반환하는 객체는 항상 다르게 되어 싱글톤이 깨지게 된다--

궁금한거

1 이넘은그럼 똑같다는 건가?

2 readObject에서 return 하는 값을 instance객체로 반환하면 달라지나??






!!!!!!
엥 신기하다... readResolve() 메소드 추가한 것 만으로. true 가 된다...모냐....무슨 비밀이 있는겨?





enum 으로 만든 싱글톤 역시 역직렬화를 해도 싱글톤임이 보장된다!!!

2021-11-28

1128 private 생성자나 열거타입으로 싱글턴임을 보장하라

 getConstructor 로 찾았더니 ->런타임 예외발생했다.

getConstructor는 public으로 만든 생성자만 불러올수있기 때문이다

그런데 getDeclaredConstructor는 이런제한상관없이 private도 다 가져온다!!

그래서 getDeclaredConstructor로 생성자 떙겨오면 . 인스턴스 변수 맘대로 만들수있따@! 후후.



1128 생성자에 매개변수가 많다면 빌더를 고려하라

<문제상황> : 선택적 매개변수가 너무 많다

-> 실수로 다른 값이랑 다른값이랑 헷갈려서 순서 바꿔서 넘겨준다면?!!버그발생!

### 해결방법01 : 점층적 생성자 패턴

- this()불러가면서 점점점 늘려간다

- 코드 졸라늘어나고 클라이언트쪽에서 실수로 잘못 넘겨줄수있다..

- 넘겨주는 매개변수가 무엇인지 생성자에서는 알수가 없으니(지금이야 뭐 인텔리제이가 보여준다고 쳐도) 실수하기쉽다

### 해결방법02 : setter사용

- 일단 기본 디폴트 생성자 하나 부르고 -> set계~ 속부르면서 필요한 매개변수 넘겨주는 패턴

- 자바빈즈 패턴이라고 한다

- set하면서 불안정한 상태에 놓이게 된다

- setter를 공개하기 싫은데... 어떻게 해결. 

-> 가장 큰 문제 : 불변하지 않다는 점. 

setter를 열어두는 순간 = 이 객체는 가변하다는 것.

즉 어디선가에서 객체의 상태가 변경될 가능성이 있다는 것이다. 

그렇다는 것은? 런타임에서 클라이언트가 해당 객체 상태값을 바꿔버릴수있고 -> 나는 어디에서 이 값이 변경되었나를 찾아야 한다......

- 근데 언제 바꿨는지 모르니까 결국에 버그가 발견되는 것은 한~ 참 후가 될 수있고. 추적이 쉽지않게 될 것이다. 

- 가격 막 setter로 바꿔버렸다가 다시 돌려놨다가. -> 버그 나고. 찾으라고 해?? -> 언제 바꾼겨~~ 막이래. ㅜㅜ -> 그래서 왠만~ 하면 불변객체로 해서(상태값 인스턴스변수는 전부다 private으로) setter 안열어두고 . 필요한 옵션값은 change어쩌구.. 이런 메서드 따로 제공해서 추적을 하든. 

### 해결방법03 : 빌더 사용.

- builder 객체를 호출( 보통 해당 클래스의 정적 클래스 ) -> 필요한 매개변수들 셋팅 -> build()를 불러서 원하는 클래스 호출. 

- 안전성 & 가독성 두마리토끼를 동시에!

1128 생성자 대신 정적 팩터리 메서드를 고려하라

 1.  이름을 가진 생성자를 제공하여 의미를 보다 명확하게 할 수 있다

2. 인스턴스 개수를 캐싱하여 성능을 향상시킬 수 있다

3. 인스턴스 하위타입으로 반환하여 유연한 설계가 가능하다

4. 자바 8부터는 인터페이스가 static 메서드를 가지는 것이 가능하다

-> 이 이전에는 이것이 불가능했기 때문에 . Collection -> Collections이런식으로 구현 타입을 따로 알아서 써야했음

만약에 static으로 이제 가능하다면. 인터페이스 메서들에 일케 두고. 클라이언트 사용하는 쪽에서는 해당 인터페이스 메서드만 부르면서 하위타입(구현타입)은 신경안쓴채 좀더 유연하게 프로그래밍 할 수 있었을 것이다.. 

0328 fdisk, mkfs, mount, fstab

 1. 하드디스크를 붙인다. 2. fdisk -l로 하드디스크를 확인한다.  - interactiive한 커맨드모드 사용하여 (m) 붙인 하드디스크의 파티셔닝을 한다.  - 마지막에 w를 해야 실제로 반영이 된다.  3. mkfs를 하여 어떤 파일시스...