2월, 2017의 게시물 표시

(JPA) @MappedSuperClass

부모클래스는 테이블과 매핑하지 않고 부모 클래스를 상속받는 자식 클래스에서 매핑 정보만 제공하고 싶으면 @MappedSuperclass를 사용하면 된다. @Entity는 실제 테이블과 매핑되지만 @MapeedSuperclass는 실제 테이블과 매핑되지 않는다. 단순히 매핑정보를 상속할 목적으로만 사용한다.

(Effective Java) 리플렉션 대신 인터페이스를 이용하라

* java.lang.reflect의 리플렉션 기능을 이용하면 메모리에 적재된(load) 클래스의 정보를 가져오는 프로그램을 작성할 수 있다. 또한 리플렉션을 이용하면, 소스코드가 컴파일 될 당시에는 존재하지도 않았던 클래스를 이용할 수 있다. 하지만 이런 능력에는 댓가가 따른다. 컴파일 시점에 자료형을 검사함으로써 얻을 수 있는 이점들을 포기해야 한다.(예외검사 Exception Checking 포함). 리플렉션을 통해 존재하지 않는, 또는 접근 할 수 없는  메소드를 호출하면 실행도중에 오류가 발생할 것이다.  리플렉션 기능을 이용하면 코드는 보기 싫은데다 장황하다. 영리한 코드와는 거리가멀고, 가독성도 떨어진다. 성능이 낮다. 리플렉션을 통한 메소드 호출 성능은, 일반적인 메소드 호출에 비해 훨씬낮다.  * 명심할 것은, 일반적인 프로그램은 프로그램 실행중에 리플렉션을 통해 객체를 이용하려 하면 안된다는 것이다. * 리플렉션을 아주 제한적으로만 사용하면 오버헤드는 피하면서도 리플렉션의 다양한 장점을 누릴 수 있다.  컴파일 시점에 존재하지 않는 클래스를 이용해야 하는 프로그램 가운데 상당수는, 해당 클래스 객체를 참조하는데 사용할 수 있는 인터페이스나 상위클래스는 컴파일 시점에 이미 갖추고 있는 경우가 많다. 그럴때는, 객체생성은 리플렉션으로 하고 객체 참조는 인터페이스나 상위 클래스르 통하면 된다.

(Effective Java) 객체를 참조할 때는 그 인터페이스를 사용하라

만일 적당한 인터페이스가 있다면 인자나 반환값, 변수, 그리고 필드의 자료형은 클래스 대신 인터페이스로 선언하자. 객체의 실제 클래스를 참조할 필요가 있는 유일한 순간은, 생성자(constructor)로 객체를 생성할때다. 예) //인터페이스를 자료형으로 사용하고 있는 바람직한 예제 List<Subscriber> subscriber = new Vector<Subscriber>(); //클래스를 자료형으로 사용하는 나쁜예제  Vector<Subscriber> subscribers = new Vector<Subscriber>(); * 인터페이스를 자료형으로 쓰는 습관을 들이면 프로그램은 더욱 유연해진다. * 한가지 주의점은 만일 원래 구현이 인터페이스의 일반 규약에 없는 특별한 기능을 제공하고 있었고 원래 코드가 그 기능을 사용하고 있었다면, 새로운 구현도 같은 기능을 제공해야 한다. 가령 위의 예에서 원래코드가 Vector의 동기화 정책을 이용하고 있었을 때, Vector를 ArrayList로 바꿔버리면 곤란하다. * 적당한 인터페이스가 없는 경우에는 객체를 클래스로 참조하는 것이 당연하다.

(Java) ThreadLocal

이미지
ThreadLocal이란? 일반 변수의 수명은 특정 코드 블록(예, 메서드 범위, for 블록 범위 등) 범위 내에서만 유효하다. {     int a = 10;     ...    // 블록 내에서 a 변수 사용 가능 } // 변수 a는 위 코드 블록이 끝나면 더 이상 유효하지 않다. (즉, 수명을 다한다.) 반면에 ThreadLocal을 이용하면 쓰레드 영역에 변수를 설정할 수 있기 때문에, 특정 쓰레드가 실행하는 모든 코드에서 그 쓰레드에 설정된 변수 값을 사용할 수 있게 된다. 아래 그림은 쓰레드 로컬 변수가 어떻게 동작하는 지를 간단하게 보여주고 있다. 위 그림에서 주목할 점은 동일한 코드를 실행하는 데, 쓰레드1에서 실행할 경우 관련 값이 쓰레드1에 저장되고 쓰레드2에서 실행할 경우 쓰레드2에 저장된다는 점이다. ThreadLocal의 기본 사용법 ThreadLocal의 사용방법은 너무 쉽다. 단지 다음의 네 가지만 해 주면 된다. ThreadLocal 객체를 생성한다. ThreadLocal.set() 메서드를 이용해서 현재 쓰레드의 로컬 변수에 값을 저장한다. ThreadLocal.get() 메서드를 이용해서 현재 쓰레드의 로컬 변수 값을 읽어온다. ThreadLocal.remove() 메서드를 이용해서 현재 쓰레드의 로컬 변수 값을 삭제한다. 아래 코드는 ThreadLocal의 기본적인 사용방법을 보여주고 있다. // 현재 쓰레드와 관련된 로컬 변수를 하나 생성한다. ThreadLocal<UserInfo> local = new ThreadLocal<UserInfo>(); // 로컬 변수에 값 할당 local.set(currentUser); // 이후 실행되는 코드는 쓰레드 로컬 변수 값을 사용 UserInfo userInfo = local.get(); 위 코드만으로는 ThreadLocal이 어떻게 동작하는 지 잘 ...

(Effective Java) 객체화된 기본자료형 대신 기본 자료형을 이용하라

* 객체화된 기본자료형은 언제 사용해야하나? 1. 컬렉션의 요소, 키, 값으로 사용할 때다. 컬렉션에는 기본자료형을 넣을 수 없기 때문이다. 2. 형인자 자료형의 형인자로는 객체화된 기본 자료형을 써야 한다. 형인자로는 기본자료형을 사용할 수 없다. 다시 말해, ThreadLocal<int> 같은 변수는 선언할 수 없다.

(Effective Java) 지역 변수의 유효범위를 최소화하라

이미지
* 지역 변수의 유효범위를 최소화하면 가독성(readability)과 유지보수성(maintainability)이 좋아지고, 오류 발생 가능성도 줄어든다. 1. 지역 변수의 유효범위를 최소화하는 가장 강력한 기법은, 처음으로 사용하는 곳에서 선언하는 것이다. 2. 거의 모든 지역 변수 선언에는 초기값이 포함되어야 한다. //컬렉션을 순회할 때는 이 숙어대로 하는 것이 바람직 for (Element e : c){  doSomething(e); } * while문 보단 for문을 쓰는 것이 좋다. ---> 두번째 순환문에는 코드를 복사해서 붙여 넣다보니 생긴 버그가 있다. 새로운 순환문 변수 i2를 초기화 했으나 실제로는 옛날 변수 i를 써버린것이다. i가 아직도 유효범위 안에 있는 관계로, 이 코드는 컴파일이 잘 될 뿐만아니라 예외도 없이 실행되지만 이상하게 동작한다. 하지만 복사해서 붙여넣기 버그가 for문이나 for-each문에서도 생길까? 컴파일조차 되지 않을 것이므로 어려울것이다. 또한 for문은 while문보다 코드 길이가 짧아서 가독성이 좋다. 3. 마지막 전략은 메소드의 크기를 줄이고 특정 기능에 집중하라는 것이다.

(Effective Java) null 대신 빈 배열이나 컬렉션을 반환하라

이미지
---> null 대신 빈 리스트를 반환하라.

(Effective Java) varargs는 신중히 사용하라

이미지
자바 1.5 부터는 공식적으로 가변 인자 메소드라고 부르는 varargs 메소드가 추가되었다. 이 메소드는 지정된 자료형의 인자를 0개 이상 받을 수 있다. 동작원리는 이렇다. 우선 클라이언트에서 전달한 인자수에 맞는 배열이 자동생성되고, 모든 인자가 해당 배열에 대입된다. 그리고 해당 배열이 메소드에 인자로 전달된다. 오버헤드가 크다. ->java.util.Arrays 클래스에 있는 asList메소드 이다. 이 메소드는 가변인자를 받고 있다.

(Effective Java) 필요하다면 방어적 복사본을 만들어라 !!!!!!!!!!!!!!!!중요!!!!!!!!!!!!!!!!!!!!!!

이미지
->얼핏보면 변경이 불가능할것처럼 보이지만 Date start = new Date(); Date end = new Date(); Period p = new Period(start, end); end.setYear(78); 하지만 Date가 변경 가능 클래스라는 점을 이용하면 불변식을 깨뜨릴 수 있다. 따라서 Period객체의 내부를 보호하려면 생성자로 전달되는변경 가능 객체를 반드시 방어적으로 복사 그러나 Period p = new Period(start, end); p.end().setYear(78); //p의 내부를 변경하게 된다. -> 길이가 0 아닌 배열은 항상 변경 가능하다는 사실을 기억하자. 그러니 내부 배열을 클라이언트에게 전달할 때는 방어적 복사본을 만들어야 한다. 우리가 배워야 할 진짜 교훈은, 객체의 컴포넌트로는 가능하다면 변경 불가능 객체를 사용해야 한다는 것이다. 그래야 방어적 복사본에 대해서는 신경 쓸 필요가 없다는 것이다.

(Effective Java) 자료형을 정의할 때는 인터페이스를 사용하라

*표식 인터페이스는 아무 메소드도 선언하지 않는 인터페이스다. 클래스를 만들때 표식 인터페이스를 구현하는 것은 해당 클래스가 어떤 속성을 가지고 있다는것을 표시하는 것이다. 그 예로 Serializable이다. 그러면 여기서 궁금증이 생긴다. 표식 어노테이션을 사용하면 되는 것이 아닌가? 가장 중요한 첫번째 장점은, 표식 인터페이스는 결국 표식 붙은 클래스가 만드는 객체들이 구현하는 자료형이라는 점이다. 표식 어노테이션은 자료형이 아니다. 즉, 표식 인터페이스는 자료형이므로, 표식 어노테이션을 쓴다면 프로그램 실행 중에나 발견하게 될 오류를 컴파일 시점에 발견할 수 있다. 두번째 장점은, 적용 범위를 좀 더 세밀하게 지정할 수 있다는 것이다. 어노테이션 자료형을 선언할 때 target을 ElementType.TYPE으로 지정하면 해당 어노테이션은 어떤 클래스나 인터페이스에도 적용 가능하다. 그런데 특정한 인터페이스를 구현한 클래스에만 적용하고자한다면 표식인터페이스를 사용해야 한다.

(Effective Java) Override 어노테이션은 일관되게 사용하라

* 상위 클래스에 선언된 메소드를 재정의 할때는 반드시 선언부에 Override어노테이션을 붙여야 한다.

(Java) EnumMap vs HashMap

*enumMap의 index 는 Enum의 내부 순서를 이용하므로 hashMap의 Hashing을 통한 index보다 효율적이다. HashMap의 경우 일정한 이상의 자료가 저장 되면, 자체적으로 resizing을 한다. 그로 인해 성능저하가 발생한다. 그러나 EnumMap은 Enum의 갯수로 제한하므로 Resizing에 대한 성능저하가 없다. put/get에 있어서 O(1)의 복잡도를 보장한다.

(Effective Java) 멤버 클래스는 가능하면 static으로 선언하라.

* 중첩 클래스에는 4가지 종류가 있다. 1. 정적 멤버 클래스 2. 비-정적 멤버클래스 3. 익명 클래스 4. 지역 클래스 -> 첫번째를 제외한 나머지는 전부 내부 클래스다. 문법적으로 보자면 정적멤버 클래스와 비-정적 멤버 클래스의 차이는 멤버 클래스 앞에 static이라는 키워드가 붙는 것이다. * 바깥 클래스 객체에 접근할 필요가 없는 멤버 클래스를 정의할 때는 항상 선언문 앞에 static 을 붙여서 비-정적 멤버 클래스 대신 정적멤버 클래스로 만들자.

(Java) JVM 성능 글

http://d2.naver.com/helloworld/1329 http://d2.naver.com/helloworld/37111 http://d2.naver.com/helloworld/329631 http://d2.naver.com/helloworld/184615 http://d2.naver.com/helloworld/1326256

(Java) Garbage Collection 튜닝

GC 튜닝을 꼭 해야 할까? 본격적으로 GC 튜닝을 살펴보기 전에 다음 질문에 대해 생각해 보자. "모든 Java 기반의 서비스에서 GC 튜닝을 해야 할까?" 결론부터 이야기하면 모든 Java 기반의 서비스에서 GC 튜닝을 진행할 필요는 없다. GC 튜닝이 필요 없다는 이야기는 운영 중인 Java 기반 시스템의 옵션과 동작이 다음과 같다는 의미이다. -Xms 옵션과 –Xmx 옵션으로메모리크기를지정했다. -server 옵션이포함되어있다. 시스템에 Timeout 로그와같은로그가남지않는다. 다시 말하면, 메모리 크기도 지정하지 않고 Timeout 로그가 수도 없이 출력된다면 여러분의 시스템에서 GC 튜닝을 하는 것이 좋다. 그런데 한 가지 꼭 명심해야 하는 점이 있다. GC 튜닝은 가장 마지막에 하는 작업이라는 것이다. GC 튜닝을 하는 이유가 무엇인지 근본적인 원인을 생각해 보자. Java에서 생성된 객체는 가비지 컬렉터(Garbage Collector)가 처리해서 지운다. 생성된 객체가 많으면 많을수록 가비지 컬렉터가 가 처리해야 하는 대상도 많아지고, GC를 수행하는 횟수도 증가한다. 즉, 여러분이 운영하고 만드는 시스템이 GC를 적게 하도록 하려면 객체 생성을 줄이는 작업을 먼저 해야 한다. "티끌 모아 태산"이라는 말이 있듯이, String대신 StringBuilder나 StringBuffer를 사용하는 것을 생활화하는 것부터가 시작이라고 보면 된다. 그리고, 로그를 최대한 적게 쌓도록 하는 것이 좋다. 하지만 어쩔 수 없는 현실도 있다. 경험상 XML과 JSON 파싱은 메모리를 가장 많이 사용한다. 아무리 String을 최대한 사용 안 하고 Log 처리를 잘 하더라도, 10~100 MB짜리 XML이나 JSON를 파싱하면 엄청난 임시 메모리를 사용한다. 그렇다고 XML과 JSON을 사용하지 않기는 어렵다. 그냥 현실이 그렇다는 것만 알아주기 바란다. 만약 애플리케이션 메...

(Java) 가비지 컬렉션

이미지
GC에 대해서 알아보기 전에 알아야 할 용어가 있다. 바로 'stop-the-world'이다. stop-the-world란, GC을 실행하기 위해 JVM이 애플리케이션 실행을 멈추는 것이다. stop-the-world가 발생하면 GC를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춘다. GC 작업을 완료한 이후에야 중단했던 작업을 다시 시작한다. 어떤 GC 알고리즘을 사용하더라도 stop-the-world는 발생한다. 대개의 경우 GC 튜닝이란 이 stop-the-world 시간을 줄이는 것이다. Java에서는 개발자가 프로그램 코드로 메모리를 명시적으로 해제하지 않기 때문에 가비지 컬렉터(Garbage Collector)가 더 이상 필요 없는 (쓰레기) 객체를 찾아 지우는 작업을 한다 이 가비지 컬렉터는 두 가지 가설 하에 만들어졌다(사실 가설이라기보다는 가정 또는 전제 조건이라 표현하는 것이 맞다). 대부분의 객체는 금방 접근 불가능 상태(unreachable)가 된다 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다. 이러한 가설을 'weak generational hypothesis'라 한다. 이 가설의 장점을 최대한 살리기 위해서 HotSpot VM에서는 크게 2개로 물리적 공간을 나누었다. 둘로 나눈 공간이 Young 영역과 Old 영역이다. Young 영역(Yong Generation 영역): 새롭게 생성한 객체의 대부분이 여기에 위치한다. 대부분의 객체가 금방 접근 불가능 상태가 되기 때문에 매우 많은 객체가 Young 영역에 생성되었다가 사라진다. 이 영역에서 객체가 사라질때 Minor GC가 발생한다고 말한다. Old 영역(Old Generation 영역): 접근 불가능 상태로 되지 않아 Young 영역에서 살아남은 객체가 여기로 복사된다. 대부분 Young 영역보다 크게 할당하며, 크기가 큰 만큼 Young 영역보다 GC는 적게 발생한다. 이 영역에서 객체가...

(Effective Java) 추상클래스 대신 인터페이스를 사용하라

* 인터페이스는 믹스인을 정의하는데 이상적이다. -> 믹스인은 주 자료형 의외에 추가로 구현할 수 있는 자료형으로, 어떤 선택적 기능을 제공한다는 사실을 선언하기 위해 쓰인다. 예를들어, Comparable이다. * 인터페이스 안에는 메소드 구현을 둘 수 없지만, 그렇다고 프로그래머가 사용할 수 있는 코드를 제공할 방법이 없는 건 아니다. 추상골격구현 클래스를 중요 인터페이스마다 두면, 인터페이스의 장점과 추상 클래스의 장점을 결합할 수 있다. -> 인터페이스로는 자료형을 정의하고, 구현하는 일은 골격 구현 클래스에 맡기면 된다. 관습적으로 골격 구현 클래스의 이름은 AbstractInterface와 같이 정한다. * 다양한 구현을 허용하는 자료형을 추상 클래스로 정의하면 인터페이스보다 나은 점이 한가지 있는데, 인터페이스 보다는 추상클래스가 발전시키기 쉽다는 것이다.

(CleanCode) 의미있는 이름

이미지
1. 의도를 분명히 밝혀라 다음코드의 목적은 무엇인가? public List<int[]> getThem(){   List<int[]> list1 = new ArrayList<int[]>();   for(int[] x : theList)    if(x[0] == 4)      list1.add(x);    return list1; } ====> 코드가 하는 일을 짐작하기 어렵다. 왜일까? 여기서 문제는 코드의 단순성이 아니라 코드의 함축성이다. 코드 맥락이 코드자체에 명시적으로 드러나지 않는다. 1. theList에 무엇이 들었는가? 2. theList에서 0번째 값이 어째서 중요한가? 3. 값 4는 무슨의미인가? 4. 함수가 반환하는 리스트 list1을 어떻게 사용하는가? 2. 그릇된 정보를 피하라 그릇된 단서는  코드 의미를 흐린다. 나름대로 널리 쓰이는 의미가 있는 단어를 다른 의미로 사용해도 안된다. 예를들어, hp, aix, sco는 변수 이름으로 적합하지 않다. 유닉스 플랫폼이나 유닉스 변종을 가리키는 이름이기 때문이다. *서로 흡사한 이름을 사용하지 않도록 주의한다. 한 모듈에서XYZControllerForEfficientHandlingOfStrings라는 이름을 사용하고, 조금 떨어진 모듈에서 XYZControllerForEfficientHandlingStorageOfStrings라는 이름을 사용한다면? 두 단어는 겁나게 비슷하다. *유사한 개념은 유사한 표기법을 사용한다. 자동완성기능 사용!!! * 주의점 대문자 O와 소문자 l사용 주의 왜냐하면 숫자 0과 1과비슷하다. * 불용어를 추가한 이름 역시 아무런 정보도 제공하지 못한다. ->Product라는 클래스가 있다고 가정하자. 다른 클래스를 ProductInfo, ProductData라 ...

(CleanCode) 클린코드

이미지
* 장인정신을 익히는 법 1. 장인에게 필요한 원칙, 패턴, 기법, 경험이라는 지식을 습득 2. 열심히 일하고 연습해 지식을 몸과 마음으로 체득 나쁜코드를 양산하면 오히려 기한을 맞추지 못한다. 나쁜 코드로 속력이 즉각 늦어져서 기한을 놓친다. 기한을 맞추는 방법, 그러니깐 빨리가는 유일한 방법은, 언제나 코드를 깨끗히 유지하는 것이다. <클린코드란?> by C++ 창시자 창문이 깨진 건물은 누구도 상관하지 않는다는 인상을 품긴다. 그래서 사람들도 관심을 끊는다. 창문이 더 깨져도 상관하지 않는다. 마침내 자발적으로 창문을 깬다. 외벽에 그려진 낙서를 방치하고 차고에 쓰레기가 쌓여도 치우지 않는다. 일단 창문이 깨지고 나면 쇠퇴하는 과정이 시작된다.  세세한 사항까지 꼼꼼하게 신경을 쓰라는 소리다. 프로그래머들이 대충 넘어가는 부분중 하나가 오류처리다. 메모리 누수, 경쟁상태, 일관성 없는 명명법이 또 다른 예다. 잘쓴 코드란 자신이 좋아했던 책을 읽었던 기억을 떠올려봐라. 마치 책을 읽는동안 단어가 사라지고 이미지가 떠오르는 듯한 코드!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! <간단한 코드 규칙> 모든 테스트를 통과한다. 중복이 없다.  시스템 내 모든 설계 아이디어를 표현한다. 클래스, 메소드, 함수 등을 최대한 줄인다. * 프로그램은 아주 유사한 요소로 이루어 졌다.  한 가지 예가 '집합에서 항목 찾기'이다. 직원 정보가 저장된 데이터베이스든 키/값 쌍이 저장된 해시 맵이든, 여러 값을 모아놓은 배열이든 이런상황이 발생하면 추상메소드나 추상클래스를 만들어서 실제 구현을 감싼다. 그러면 장점이 생긴다.  실제 기능은 아주 간단한 방식으로, 예를들어 해시맵으로, 구현해도 괜찮다.  다른 코드는 추상 클래스나 추상 메소드가 제공하는 기능을 사용하므로 실제...

(Effecitve Java) 계승하는 대신 구성하라

이미지
-> 계승은 하위클래스가 상위클래스의 하위자료형이 확실한 경우에만 바람직하다. 다시말해 클래스 B는 클래스 A와 "IS-A" 관계가 성립할 때만 A를 계승해야 한다. 만약 '아니다' 라는 대답이 나오면 B안에 A객체를 참조하느 private 필드를 두고 B에는 더 작고 간단한 API를 구현해야 한다.

(Effective Java) 변경가능성을 최소화 하라

이미지
* 변경 불가능(immutable) 클래스는 그 객체를 수정할 수 없는 클래스다. 객체 내부의 정보는 객체가 생성될 때 주어진 것이며, 객체가 살아있는 동안 그대로 보존된다. 예) String, 기본자료형 클래스, BigInteger, BigDecimal 등이다. 이러한 클래스를 만드는 이유는 설계하기 쉽고, 구현하기 쉽고, 오류가능성도 적고, 더 안전하다. * 변경 불가능 클래스를 만들 때 5가지 규칙 1. 객체 상태를 수정하는 메소드(수정자mutator 메소드 등)를 제공하지 않는다. 2. 계승할 수 없도록 한다. : 보통 클래스를 final로 선언하면 된다. 3. 모든 필드를 final로 선언한다. : 새로 생성된 객체에 대한 참조가 동기화(synchronization)없이 다른 스레드로 전달되어도 안전하다. 4. 모든 필드를 private으로 선언한다. 5. 변경가능 컴포넌트에 대한 독점적 접근권을 보장한다. : 클래스에 포함된 변경 가능 객체에 대한 참조를 클라이언트는 흭득할 수 없어야 한다. -> this 객체를 변경하는 대신 새로운 Complex객체를 만들어 반환하도록 구현되어있다. 대부분의 변경 불가능 클래스가 따르는 패턴이다. 이러한 방법을 함수형접근법이라하고,  변경불가능성을 보장하므로 장점이많다. * 또한 변경 불가능한 객체는 스레드에 안전(thread-safe)할 수 밖에 없다. 어떤 동기화도 필요없으며, 여러 스레드가 동시에 사용해도 상태가 훼손될 일이 없다. 따라서 변경 불가능한 객체는 자유롭게 공유할 수 있다. 변경 불가능 클래스는 클라이언트가 기존 객체를 재사용하도록 적극 장려해서 충분히 살릴 필요가 있다. 첫번째. public static final Complex zero =new Complex(0, 0); 두번째. 변경 불가능한 클래스는 자주 사용하는 객체를 캐시(cache)하여 이미 있는 개체가 거듭 생성되지 않도록 정적팩토리를 제공할 수 있다. 이런 정적팩토리...

(Effective Java) 클래스와 인터페이스

*정보은닉이 중요한 이유는, 정보은닉이 시스템을 구성하는 모듈 사이의 의존성을 낮춘다.(decouple) * 각 클래스와 멤버는 가능한 한 접근 불가능하도록 만들라 * 객체 필드는 절대로 public으로 선언하면 안된다. * 변경가능 public 필드를 가진 클래스는 다중 스레드에 안전하지 않다. 변경 불가능 객체를 참조하는 final 필드라 해도 public 으로 선언하면 클래스의 내부 데이터 표현 형태를 유연하게 바꿀수없게된다. 공개 API의 일부가 되어버리므로, 삭제하거나 수정할 수 없게된다. 공개 API의 일부가 되어버리므로, 삭제하거나 수정할 수 없게 되는 것이다. 이 말은 static에도 해당된다. 단, 어떤 상수들이 클래스로 추상화된 결과물의 핵심적 부분을 구성한다고 판단되는 경우, 해당 상수들을 public static final 필드들로 선언하여 공개할수 있다. 이런 필드들은 대문자로 구성된 이름을 가지며, 이름을 구성하는 단어들은 밑줄 기호로 구분한다.

(Effective Java) clone을 재정의 할때는 신중하라

이미지
* Cloneable 인터페이스에는 clone 메소드가 없으며, Object의 clone 메소드는 protected로 선언되어 있다. *Cloneable 인터페이스에 아무런 메소드가 없다면 대체 Cloneable이 하는일은 무엇인가? ->protected로 선언된 Object의 clone 메소드가 어떻게 동작할지 정한다. -> 만일 어떤 클래스가 Cloneable을 구현한다면, Object의 clone메소드는 해당 객체를 필드단위로 복사한 객체를 반환한다. *일반적으로 인터페이스를 구현한다는 것은 클래스가 무슨 일을 할 수 있는지 클라이언트에게 알리는 것이다. 그런데 Cloneable의 경우에는 상위 클래스의 protected멤버가 어떻게 동작할지 규정하는 용도로 쓰이고 있다. *clone 메소드의 일반규약은 느슨하다. java.lang.Object 명세를 보면 다음과 같다. 객체의 복사본을 만들어서 반환하다. "복사"의 정확한 의미는 클래스마다 다르다. 일반적으로는 다음의 조건이 충족되어야 한다. 객체 x가 있다고 하자. -> x.clone() != x는 참이어야 한다. x.clone().getClass() == x.getClass() 는 참이 되겠지만, 반드시 그래야 하는것은 아니다. x.clone().equals(x)  이것도 실행한 결과가 true가 되겠지만, 반드시 그래야 하는것은 아니다. * 사실상 clone 메소드는 또 다른 형태의 생성자다. 원래 객체를 손상시키는 일이 없도록 해야하고, 복사본의 불변식(invariant)도 제대로 만족시켜야 한다. 만약 스택을 복사하려면 스택의 내부구조도 복사해야 한다. -> elements.clone() 호출 결과를 Object[] 로 형변환 할 필요가 없음에 유의하자. 릴리즈 1.5버전부터는 배열에 clone을 호출하면 반환되는 배열의 컴파일 시점자료형은 복제 대상 배열의 자료형과 같다. 위의 해법...

(Effective Java) toString은 항상 재정의하라

* toString 일반 규약에는 이런 구절이 있다. "모든 하위 클래스는 이 메소드를 재정의함이 바람직하다." * toString 메소드를 재정의하면 해당 객체만 혜택을 보는 것이 아니라 해당 객체에 대한 참조를 유지하는 객체들, 특히 컬렉션까지 혜택을 본다. 맵을 출력했을 때, "{Jenny=PhoneNumber@163b91}" 것보다 "{Jenny=(707)867-5309}" 이것이 나을 것이다. *가능하다면 toString 메소드는 객체 내의 중요정보를 전부 담아 반환해야 한다.

(Effective Java) equals를 재정의할 때는 반드시 hashCode도 재정의 하라

* equals를 재정의할 때는 반드시 hashCode도 재정의 해야 한다. 그렇지 않으면 Object.hashCode의 일반 규약을 어기게 되므로, HashMap, HashSet, HashTable같은 해시(hash) 기반 컬렉션과 함께 사용하면 오작동하게 된다. <Object 클래스 명세에서 복사해 온 일반 규약> 응용프로그램 실행 중에 같은 객체의  hashCode를 여러 번 호출하는 경우, equals가 사용하는 정보들이 변경되지 않았다면, 언제나 동일한 정수(Integer)가 반환되어야 한다. 다만 프로그램이 종료되었다가 다시 실행되어도 같은 값이 나올 필요는 없다. equals(Object)메소드가 같다고 판정한 두 객체의 hashCode값은 같아야 한다. equals(Object)메소드가 다르다고 판정한 두 객체의 hashCode값은 꼭 다를 필요는 없다. 그러나 서로 다른 hashCode값이 나오면 해시테이블(hashTable)의 성능이 향상될 수 있다. <이상적인 해시 함수를 만드는 방법> 1. 17과 같은 0 아닌 상수를 result라는 이름의 int 변수에 저장한다. 2. 객체 안에 있는 모든 중요필드 f에 대해서(equals 메소드가 사용하는 필드를 말한다) 아래의 절차를 시행한다. A. 해당필드에 대한 int 해시 코드 c를 계산한다. 필드가 boolean 이면(f?1:0)을 계산한다. 필드가 byte, char, short, int 중 하나면 (int)f 를 계산한다. 필드가 long이면 (int)(f^(f>>>32))를 계산한다. 필드가 float이면 Float.floatToIntBits(f)를 계산한다. 필드가 double이면 Double.doubleToLongBits(f)를 계산하고 그 결과로 얻은 long값을 위의절차 3에 따라 해시코드로 변환한다. 필드가 객체 참조이고 equals 메소드가 해당 필드의 equals메소드를...

(Effective Java) equals를 재정의 할 때는 일반 규약을 따르라

이미지
*  Object.equals 를 재정의 하는 것이 바람직할 때는 언제인가? -> 객체 동일성이 아닌 논리적 동일성의 개념을 지원하는 클래스 일 때,그리고 상위 클래스의  equals가 하위 클래스의 필요를 충족하지 못할 때 재정의 해야 한다. 값 클래스(value class)는 대체로 그 조건에 부합한다. 값 클래스는 Integer나 Date처럼, 단순히 어떤 값을 표현하는 클래스다. 값 객체에 대한 참조를 비교하는 프로그래머는 두 객체가 같은 값을 나타내는지를 알기 위해 equlals를 사용하지 , 동일한 객체인지 보려고  equals를 호출하지 않는다. <equals 메서드를 정의할 때 준수해야 하는 일반 규약(general Contract)> ->equals메소드는 동치 관계(equivalence relation)를 구현한다. 다음과 같은 관계를 동치관계라 한다. 반사성(reflexive) : null이 아닌 참조 x가 있을 떄, x.equals(y)는 true를 반환한다. 대칭성(symmetric) : null 이 아닌 참조 x와 y가 있을 때, x.equals(y) 는 y.equals(x)가 true일 때만 true를 반환한다. 추이성(transitive): null 이 아닌 참조 x,y,z가 있을때, x.equals(y) 가 true이고 y.equals(z)가 true이면 x.equals(z)도 true이다. 일관성(consistent): null이 아닌 참조 x와 y가 있을 때, equals를 통해 비교되는 정보에 아무런 변화가 없다면, x,.equals(y) 호출결과는 호출횟수에 상관없이 항상 같아야 한다. null이 아닌 참조 x에 대해서, x.equals(null)은 항상 false이다. ->이것은 CaseInsetiveString의 equals에서는 String객체에 대해서는 알지만 String의 equals메소드는  CaseInsen...

(Java) 자바 메모리 모델

이미지
* Java의 메모리 모델이란 Java의 쓰레드가 메모리에 액세스 할 떄 어떤 일이 일어나는지 규정하는 것이다. * 자바 메모리 모델과 친해지기 위한 지침 복수 쓰레드에서 공유하는 필드는 synchronized 또는 volatile로 보호하라 불변 필드는 final하라 생성자안에서 this를 놓치지 말라 1. reorder 2. visibility 3. 공유메모리와 액션 4. synchronized 5. volatile 6. final 7. Double-Checked Locking 패턴 1.  reorder -> reoreder란 최적화를 위해 컴파일이나 Java 가상머신이 프로그램의 처리순서를 바꾸는 것을 말한다. reorder는 수행능려을 높이는데 널리 사용되지만 그 사실을 프로그래머가 의식하는 경우는 거의 없다. 실제 싱글 쓰레드 프로그램에서는 reorder가 이뤄지고 있는지 판단할 수 없다. 그러나 멀티쓰레드 프로그램에서는 reorder가 원인이 되어 이상 작동을 하는 경우가 있다. 자바의 컴파일러는 자바 코드를 바이트 코드로 컴파일 하면서 정해진 범위 내에서 자유롭게 최적화를 수행할 수 있다. 이런 최적화에는 단순히 코드의 특정 구문을 보다 효율적인 다른 구문으로 치환하는 경우도 있지만, 때론 중복된 구문을 삭제하거나 구문 간의 순서를 재배치함으로써 소기의 목적을 달성하기도 한다. 뿐만 아니라 CPU의 연산 시에도 인스트럭션을 재배열하거나 보다 작은 마이크로 인스트럭션으로 나눠서 처리할 수도 있기 때문에 자바로 작성된 프로그램의 정확한 수행 순서를 예측하기란 쉽지가 않다. 자바는 앞서 설명한 happens-before 관계를 보장함으로써 일반적인 단일 스레드 환경에서의 수행 순서를 보장하고 있지만, 멀티스레딩 환경에선 최적화에 따른 재배열(reordering)이 예상치 못한 가시성의 문제를 일으키지 않도록 보장하기 위해 명시적으로 동기화를 처리해 happens-bef...

(Java멀티쓰레드 디자인패턴) Single Threaded Execution

* SharedResource(공유자원) 역할 -> SharedResource 역할을 하는 클래스는 복수의 쓰레드에서 액세스한다. SharedResource는 몇개의 메소드를 가지는데 대체로 2종류로 분류된다. safeMethod : 복수의 쓰레드에서 호출해도 아무런 문제가 없는 메소드 unsafeMethod : 복수의 쓰레드가 호출하면 안되기 때문에 가드(Guard)가 필요한 메소드 자바에서는 unsafeMethod를 synchronized 로 함으로써 가드한다. 싱글쓰레드로 동작시켜야 하는 범위를 크리티컬 섹션이라한다. ------------------------------------------------------------------------------------------------- <적용가능성> 멀티쓰레드 복수의 쓰레드가 액세스 할 때 : 멀티쓰레드 프로그램이더라도 모든 쓰레드가 독립적으로 동작하고 있다면 SingleThreaded Execution 패턴을 사용할 필요가 없다. 상태가 변화할 가능성이 있을 때 : 인스턴스가 만들어진 후에 상태가 변화할 가능성이 전혀 없다면 Single Threaded Execution 을 사용할 필요가 없다. 이것이 Immutable패턴이다.  안전성을 확보할 필요가 없을 때  * Single Threaded Execution의 문제점은 데드락을 일으킬 수 있다는 것이다 <크리티컬 섹션의 크기와 수행능력> 락을 취득하는데 시간이 걸리기 때문 ->synchronized메소드에 들어갈 때에는 객체의 락을 취하게 되는데 이 처리에는 시간이 걸리게 된다.      2. 쓰레드의 충돌로 대기하게 되기 때문 -> 쓰레드 A가 크리티컬 섹션에서 처리를 실행하고 있는 동안 크리티컬 섹션에 들어가려고 했던 쓰레드 B는 블록한다. 이러한 상황을 쓰레드의 충돌...

(Java 멀티쓰레드 디자인패턴) 멀티쓰레드 프로그램 평가기준

1. 안전성(safety) : 객체를 망가뜨리지 않는 것. (즉, 객체의 필드가 예상외의 값을 갖지 않는 것) 또한 복수의 쓰레드가 이용해도 안전성이 유지되는 클래스를 쓰레드 세이프 클래스라 부른다. 2. 생존성(liveness) : 필요한 처리가 언젠가 반드시 이루어지는 것을 말함. 한편 안전성과 생존성은 서로 상반되기도 한다. 예를들어, 안전성만 중시하다가 생존성을 잃을 수도 있다. 그 사례가 데드락이다. 이것은 복수의 쓰레드가 서로 상대편에서 락을 해제하기를 기다리는 상황이다. 3. 재사용성(reusability) : 클래스를 다시 사용할 수 있는 것. 필수는 아니지만 품질을 높이는데 중요하다. java.util.concurrent 패키지에서는 멀티쓰레드 프로그래밍에 편리한 재사용성이 높은 클래스를 제공한다. 4. 쓰루풋(throughput) : 단위시간당 처리수 5. 응답성(responsiveness) : 요구를 한뒤 반응이 나타날때까지 걸리는 식ㄴ ---------------------------------------------------------------------------------------------------

정규표현식

^ : 문자열의 시작 $ : 문자열의 종료 . : 임의의 한 문자 | : or를 나타냄 ? : 앞 문자가 없거나 하나 있음 + : 앞 문자가 하나 이상임 * : 앞 문자가 없을 수도 무한정 많을 수도 있음 {n, m} : 앞 문자가 n개 이상 m개 이하. {0,1}은 ?와 같은 의미다. {n, } : 앞 문자가 n개 이상. 위의 형태에서 m이 생략된 형태이다. {0, } 이면 * 와 같고, {1, } 이면 +와 같은 의미이다. 기본적인 정규식 [0-9]*$ : 숫자 [a-zA-Z]*$ : 영문자 [가-힣]*$ : 한글 [a-zA-Z0-9]*$ : 영어/숫자 참고 : http://www.nextree.co.kr/p4327/

(성능개선) 캐시, 병렬/비동기, AJAX와 DOM을 이용한 비동기 처리

* HTTP에서 성능개선을 위해 캐시를 사용할 수 있으며, 크게 브라우저 캐시와 서버캐시로 나뉜다. 1. 브라우저 캐시 1) HTTP 응답 크기를 줄이는 캐시방식 2) HTTP 요청 수를 줄이는 캐시 방식 -> Cache-Control속성을 이용해 HTTP 요청 자체를 하지 않도록 줄이는 방식이다. 예) Cache-Control : max-age = 2592000초 인 경우 back.gif를 내려받은 이후 30일 동안은 back.gif를 사용하더라도 HTTP요청을 하지 말고 브라우저 캐시에 있는 것을 사용하라는 의미다. 2. 병렬/비동기 처리 1) 네트워크 연결 증가 브라우저는 한 페이지 내에서 한 도메인에 대해 네트워크 연결갯수가 제한되어 있다. 따라서 컨텐츠를 동시에 내려 받을 수 있는 병렬 처리 개수에 한계가 있다. 그래서 도메인 갯수를 증가시키거나 스레드 수 설정을 증가시킨다. 2) AJAX와 DOM을 이용한 비동기처리 역동적인 화면 구성이 가능하고 화면내의 콘텐츠도 자유자재로 제어할 수 있게 됐다. AJAX와 DOM을 효과적으로 이용하면 서버 부하 감소뿐 아니라 클라이언트 측면의 성능개선도 가능하다. 2-1) 화면 내 일부를 비동기처리 전체화면 내용에 차지하는 비중은 작지만 서버 처리에 오래 걸리는 항목에 적용하면 효과적이다. 또한 보여지는 부분만 먼저 처리하고 나머지는 서버에서 내용이 처리되도록 구성하면 초기화 시간을 개선할 수 있다. 2-2) 트랜잭션의 비동기 분리 현재는 입력, 수정, 삭제 같은 데이터 변경 트랜잭션은 AJAX로 비동기 처리하고, 목록에 반영하는 작업은 DOM처리를 통해 수정하는 것이 가능하다. * 기타 성능 개선 1. CSS와 자바스크립트는 병렬처리를 고려해서 배치한다. -> CSS를 다운로드 하는 동안 자바스크립트 파일을 다운로드 할 수 있지만 자바스크립트를 다운로드 하는 동안에는 CSS를 다운로드 할 수 없다. 그러므로 CSS 파일을 자바스크립트 파...

(SpringSecurity) 암호화 알고리즘

참고 사이트 : http://d2.naver.com/helloworld/318732 참고:  https://github.com/infinitefire/IssueTrackingSystem/wiki/Spring-Security에-대한-이해

(HTML5) hidden 필드

히든 필드는 화면상의 폼에는 보이지 않지만 사용자가 입력을 마치고 폼을 서버로 전송할 때 서버로 함께 전송되는 요소이다. 보통 사용자가 굳이 보여 줄 필요가 없디만 관리자가 알아야 하는 것을 히든 필드로 입력한다. <input type="hidden" name="이름" value="서버로 넘길 값">

(서버엔지니어링)

0. 동접 10만명을 예상한다면? 1. 서버가 몇대? 2. 언제 증설해야하는가? *Amdahl`s law 프론트 엔드: 인터렉션은 최대, 뒤에서는 많은 일 <퍼포먼스엔지니어링> Objective : 무엇을 측정/검증/개선할것인가? Merices : 측정 결과, 무엇을 얻을것인가? Workload : 어떤 행위를 측정할 것인가? --------------------------------------------------------------------------(위는 준비과정) 퍼포먼스테스트 벨리데이션 개선 <Response Time을 쪼개봄> * 스카우터 툴 * 제니퍼 툴 * 핀포인트 * 서버엔지니어링, GC튜닝 책 * 비주얼 vm (자바) TDA : 자바의 락을 분석하는 도구 jvisualvm : 자바 분석도구 리눅스에서 cpu부하량 보기 >mpstat -P ALL 1 %usr은 애플리케이션에서 비즈니스로직이 담당하는 부분 %sys는 패킷이 나가는 부분 %soft는 받는 쪽

(자바) EffectiveJava int 상수대신 enum을 사용

* int enum 상수는 컴파일 시점 상수 이기 때문에 상수를 사용하는 클라이언트 코드와 함께 컴파일 된다. * 상수의 int값이 변경되면 클라이언트도 다시 컴파일 해야 한다. * 자바의 enum은 C, C++, C#과 같은 언어에서 제공하는 enum자료형과 비슷해보이지만 그렇진 않다. 자바의 enum 자료형은 완전한 기능을 갖춘 클래스로 다른언어의 enum보다 강력하다. 다른언어들의 enum은 int값이지만 자바는 public static final int이다. 즉, 클라이언트가 접근할 수 있는 생성자가 없기 때문에 클라이언트의 enum 자료형으로 새로운 객체를 생성하거나 계승을 통해 확장할 수 없다. * enum자료형은 싱글턴 패턴을 일반화 한것과 같다. * 상수를 추가하거나 순서를 변경해도 클라이언트는 다시 컴파일 할 필요없다. 상수를 제공하는 필드가 enum 자료형과 클라이언트 사이에서 격리계층 구실을 하기 때문이다. 또한, toString()메소드 호출 가능 *또한 enum자료형은 메소드나 필드를 추가할 수 있다. 그 잉는 Applie과 Orange자료형의 경우 과일의 색이나 사진을 반환하는 메소드를 추가하면 좋은 아이디어 이기 떄문이다. * enum은 원래 변경 불가능 하므로 (immutable) 모든 필드는 final로 선언되어야 한다. * enum 은 int 상수와 성능 면에서 비등하다. 자료형을 메모리에 올리고 초기화하는 공간적/시간적 비용 때문에 약간 손해를 보긴한다. 그러나 휴대전화나 토스터기 처럼 시스템 자원에 민감한 기기에 돌릴 프로그램이 아니라면, 실제로는 별 차리를 느낄 수 없다.

오픈소스 만들기

@Temporal(TemporalType.Date)는 Java.utils.Date와 Java.utils.Calendar만 인식된다. LocalDate는 인식되지않는다./

(스프링) 스프링MVC 아키텍처

이미지

(스프링) 메타에노테이션

참고 : http://lng1982.tistory.com/89

문제점

이슈 클래스의 labels가 1대 다 관계 또한 label 클래스의 이슈도 1대다 관계

(자바ORM) 양방향 매핑의 규칙

* 양방향 연관관계 매핑 시 지켜야 할 규칙이 있는데 두 연관관계 중 하나를 연관관계의 주인으로 정해야 한다. 연관관계의 주인만이 데이터베이스 연관관계와 매핑되고 외래키를 관리(등록, 수정, 삭제) 할 수 있다. 반면에 주인이 아닌 쪽은 읽기만 할 수 있다. 어떤연관관계를 주인으로 정할지는 mappedby 속성을 사용하면 된다. 주인은 mappedby 속성을 사용하지 않는다. 주인이 아니면 mappedby속성을 사용해서 속성의 값으로 연관관계의 주인을 지정해야 한다. < 연관관계의 주인은 외래 키가 있는 곳> 예를들어) 회원과 팀 두 테이블의 관계에서 회원이 team이라는 객체를 참조하고 이것이 외래키이므로 이때 주인은 회원으로 한다. 대신 팀 테이블에서 List<Member> members; 에다가 @OneToMany(mappedby="team")을 해주어 자신이 주인이 아님을 표시한다. < 양방향 연관관계의 주의점 > 양방향 연관관계를 설정하고 가장 흔히 하는 실수는 연관관계의 주인에는 값을 입력하지 않고, 주인이 아닌 곳에만 값을 입력하는 것이다. 데이터베이스에 외래 키 값이 정상적으로 저장되지 않으면 이것을 의심해보자. *MappedBy에 대한 설명 ->MappedBy signals hibernate that the key for the relationship is on the other side. This means that although you link 2 tables together, only 1 of those tables has a foreign key constraint to the other one. MappedBy allows you to still link from the table not containing the constraint to the other table * 양방향은 외래 키가 있는 ...