'IT > 코딩 팁' 카테고리의 다른 글

문자열 복사시 역슬래시 자동 삽입 시키기  (0) 2020.05.21

이퀄스가 트루면 해쉬코드도 무조건 같아야함

해쉬코드가 같더라도 이퀄스는 펄스 일 수 있음.

이퀄스에서 사용하는 변수는, 해쉬코드에서도 사용해야 함

https://jeong-pro.tistory.com/172

 

31이 많이 쓰이는 이유 : https://johngrib.github.io/wiki/Object-hashCode/

 

 

https://nesoy.github.io/articles/2018-06/Java-equals-hashcode

'IT > 자바' 카테고리의 다른 글

객체, 클래스, 인스턴스 용어 구분  (0) 2020.05.18
자료구조 정리 잘된 곳  (0) 2020.05.13
해쉬맵  (0) 2020.05.08
자바 디컴파일  (0) 2020.05.07
Volatile 이란?  (0) 2020.05.07

해쉬맵 정리 - https://d2.naver.com/helloworld/831311

 

해쉬테이블은 NODE객체를 담는 1차원 배열이다. (자바8 이전에는 Entry객체를 담음)

배열에 길이는 최초 16으로 할당되고, 2배씩 증가한다(2의 제곱이라는 것이 중요! 이유는 뒤에 설명)

NODE객체는 hash, key value, next 4개의 멤버변수를 담고있다.

 

Key에서 받아온 해쉬값을 가지고 저장될 인덱스를 결정하는데, 배열의 크기가 16이라면 해쉬%16 해서 나머지값을 인덱스로 두면 된다. 근데 여기서 해쉬%16이 아니라 (16-1) & hash 를 통해 인덱스를 구한다. 배열의 길이가 2의 제곱일 경우 해쉬%배열길이 = (배열길이-1)&hash 이며, and연산을 하는것이 더 빠르다(위에서 중요하다고 한 이유).

(참고: https://stackoverflow.com/questions/27230938/why-hashmap-insert-new-node-on-index-n-1-hash)

 

같은 인덱스에 또 node객체가 들어오면, 앞 노드의 next 멤버변수에 들어가는 형태(링크드 리스트임)

 

 

'IT > 자바' 카테고리의 다른 글

자료구조 정리 잘된 곳  (0) 2020.05.13
해쉬코드, 이퀄스  (0) 2020.05.08
자바 디컴파일  (0) 2020.05.07
Volatile 이란?  (0) 2020.05.07
자바 정렬  (0) 2020.04.24

javap -c -p -v 컴파일된 클래스파일.class

-v는 라인넘버

'IT > 자바' 카테고리의 다른 글

자료구조 정리 잘된 곳  (0) 2020.05.13
해쉬코드, 이퀄스  (0) 2020.05.08
해쉬맵  (0) 2020.05.08
Volatile 이란?  (0) 2020.05.07
자바 정렬  (0) 2020.04.24

출처: https://tourspace.tistory.com/11?category=788398, https://tourspace.tistory.com/12?category=788398

 

(자바 컴파일? java 파일이 class 파일로 변환되는 과정. class파일은 byte코드이다.)

설명

  • 기존에 바이트코드에서 메쏘드를 표현하기 위해 네종류의 opcode를 사용했었으나, java7부터 invokdeddynamic(indy로 표현) 이 추가되었음.
  • invokeddynamic은 java7에서 java가 아니라 jython, groovy 등 jvm에서 돌아가는 다른 언어의 람다식만 지원했던 형태같고, java파일 컴파일된 bytecode에서는 절대 사용되지 않았음.
  • 익명클래스는 컴파일시 별도의 class파일을 가지고 당연히 객체형태로 사용되며, 람다는 class파일이 생성되지는 않지만 객체형태로 호출됨.
  • 컴파일시에 바이트코드에서는 런타임에 실제 생성을 하는 방법(레시피)만 표기
    • 해당 레시피는 invokedynamic instrucion에 의해 동적/정적 인수 목록으로 encoding됨.
  • 암턴 bytecode내에서 indy가 호출되면 bootstrap 영역의 lambdafactory.metafactory()를 수행 
    • lambdafactory.metafactory(): java runtime library의 표준화 method
    • 어떤 방법으로 생설할지는 최적화된 방법으로 동적으로 결정된다.
  • java.lang.invoke.CallSite 객체를 리턴함
    • 해당 람다의 람다 팩토리
    • MethodHandle을 멤버변수로 가진다.!
    • 사용자가 작성한 람다가 변환되는 함수 인터페이스의 인스턴스를 반환
      • 한번만 생성되고 재호출시 재 사용함(이래서 익명클래스보다 빠름.)
  • CallSite 내부에는 java.lang.invoke.MethodHandle을 멤버 변수로 갖고, MethodHandle은 람다와 연결된 private method로 연결됨.
  • 작성된 람다는 private static method로 형태로 되어 호출됨(desugaring)
  • 요약: 작성된 람다는 런타임시에 구현됨.
    • 원리 -> 자바컴파일 -> 람다를 만들기 위한 레시피가 포함된 byte코드 생성 -> invokedynamic 지시자가 레시피를 참조하여 CallSite 객체를 리턴함 -> CallSite 의 멤버변수인 MethodHandle이 람다와 연결된 private method로 연결됨 -> 람다식은 desugaring되어 method형태로 되고, 이게 호출되는 방식임.

 

더 자세히는

자바 최적화 - 가장 빠른 성능을 구현하는 검증된 10가지 기법 책 읽어보는게 나을듯.

 

슈가, 디슈가링

  • Synatic Sugar : 간결하게 표현한다.  
    • 마치 익명클래스를 람다식으로 표현해서 잡다한 노이즈코드를 걷어내는 것.
  • Desugar : sugar된 문장을 원래대로 되돌린다라
  • 자바8 내부에서 람다를 해석할 때, 동적으로 슈가된 람다코드를 디슈가링해서 메쏘드 형태로 만들어 놓고, 이 메쏘드가 메쏘드 핸들에 연결되어 호출하는 방식으로 쓴다는 것.

'IT > 자바8-람다' 카테고리의 다른 글

람다 원리 및 값 캡쳐란?  (0) 2020.05.07
클로져(Closure, Close-over), 쉐도잉  (0) 2020.05.06
Identity 함수?  (0) 2020.04.29
자주쓰는 람다  (0) 2020.04.29
람다 사용법 및 규칙  (0) 2020.04.23

익명클래스는 클래스파일이 생성되지만, 람다는 생성되지 않고 람다 레시피가 생성되어 런타임에 인보크 다이나믹을 통하여 타입과 오브젝을 생성 하고, 람다 메타 팩토리라는 부트스트랩 메쏘드가 결정을 해서 오브젝을 리턴하고, 다음에 똑같은걸 요구하면 저장해놨다가 바로 넘겨주고, 상태가 없는 람다표현식(non-local variable을 사용하지 않는)은 캐쉬했던걸 바로 사용하므로 빠름. (상태가 없는 펑션은 바이트코드만 디슈가해서 사용함)

 

람다는 내부적으로 Variable 자체가 아닌 Value를 캡쳐한다고 한다.

 

 

'IT > 자바8-람다' 카테고리의 다른 글

람다 내부 구현 설명 및 슈가, 디슈가링이란?  (0) 2020.05.07
클로져(Closure, Close-over), 쉐도잉  (0) 2020.05.06
Identity 함수?  (0) 2020.04.29
자주쓰는 람다  (0) 2020.04.29
람다 사용법 및 규칙  (0) 2020.04.23

무조건 메인메모리를 쓰게함.

왜?

  • 공유되는 자원이 여러개의 쓰레드에서 접근하면 동시성 문제가 생길 수 있음
  • 예를들어 A라는 오브젝트는 공유되고, 쓰레드1에서는 계속 Re-Write함. 쓰레드2에서는 Read만함. 이때 불일치 할 수 있음.

출처

https://nesoy.github.io/articles/2018-06/Java-volatile

'IT > 자바' 카테고리의 다른 글

자료구조 정리 잘된 곳  (0) 2020.05.13
해쉬코드, 이퀄스  (0) 2020.05.08
해쉬맵  (0) 2020.05.08
자바 디컴파일  (0) 2020.05.07
자바 정렬  (0) 2020.04.24

클로져

  • 핵심은 자바스크립트나 자바에서 자신의 스코프의 범위 밖에 있는 변수에 접근하는 개념임.
    • 자바같은경우 익명클래스, 람다가 있음. 자신을 선언하는 클래스의 멤버변수나 메쏘드 지역변수등 접근 가능함. 
    • 익명클래스와 람다의 스코프에는 조금 차이가 있는데, 핵심은 익명클래스는 말그대로 익명 "객체"인 것이고, 람다는 객체가 아니다! 즉, 익명클래스 내에서 this는 자기 자신을 가리키고, 람다에서 this는 자신을 선언한 클래스를 말함.
  • Closure -> Close over한다고 해서 클로져임.
  • int i = 100; 이고 callingMethod(x -> x * 2 + i) 이런식으로 메쏘드를 호출 할때, x는 람다표현식의 파라미터이고, i는 non-local variable(free variable) 이다. (참고로 x는 local variable, 또는 bound variable이라고함)
    i 가 저 람다표현식의 close over한다고 한다. scope 자체를 외부로 확장한다.
  • 자바 8 이전에는 익명클래스의 함수에서 non-local variable에 접근하기 위해선, 이 non-local variable이 무조건 final이어야 했다.
  • 자바8에서 final 키워드가 빠져도 되지만, 값 접근은 되지만 변경은 불가능. 이것을 effectively final 이라고 부른다. 결국은 final 이지만 안보일 뿐이다.
  • 그리고 final이 안붙고, 값할당이 두번이상 된다면 이건 effectively final이 될 수 없으므로 사용 못함.
  • 외부 쓰레드에서 값이 바뀔 염려도 있고 하여, 오라클 자바8 아키텍터가 final로 했다고 함.
    • 예를들어 Object A; A변수가 있는데, 같은 클래스 내에서 A가 스코프 범위 밖의 변수(non-local variable, free variable)인데 익명클래스(클로저)나 람다식에서 A=B 이런식으로 할당이 가능해 버리면 A가 보고 있는 객체의 주소 자체가 바뀌게 되고, 이렇게 되면 사용자가 알지못하는 버그를 초래할 수 있으므로 사전에 방지하기 위함
    • 람다식에서 non-local variable 사용시 값복사를 한다고 했는데, 아무튼 A주소에 접근하는게 아니라, A객체의 얕은복사 형태로 만들어서 사용하는 듯 함.
  •  당연히 변수에서 접근하는 객체의 주소 자체를 바꿀순 없지만, 객체 내부의 값을 셋터를 통해 바꾸는것은 가능함.

 

쉐도잉

  • 함수 밖의 함수가 가려지는것을 말함. (익명클래스의 클로져 문제)
  • 예제코드
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class TestMain {
    private int A = 180;
    
    public static void main(String ...args) {        
        TestMain testMain = new TestMain();
        testMain.run();        
    }
    
    @Override
    public String toString() {return "toString 오버라이드";}
    
    public String toString(int i) {return "toString 오버로딩";}    
    
    void call1() {System.out.println("you called call1 method");}
    
    public static void call2() {System.out.println("you called call2 method");}
    
    public void noOverriding() {System.out.println("you called noOverriding method");}
    
    public void noOverriding(int i) {System.out.println("you called noOverriding method, overriding");}
    
    void run() {
        int B = 39;
        InterA interA = new InterA() {
            int A = 130;            
            @Override
            public String InterA() {
                System.out.println(TestMain.this.A);
                call2();                
                System.out.println(toString());
                
                // toString은 쉐도잉이 일어남. (스코프 범위 밖에서 오버라이딩 메쏘드 구현되어있어도 찾지못함)
                // System.out.println(toString(1));        
                
                //무조건 클래스이름.this.로 접근해야ㅐ함
                System.out.println(TestMain.this.toString(1));
                
                //noOverriding은 오버라이딩이 된 메쏘드가 아니므로 쉐도잉이 일어나지 않음.
                noOverriding();    
                noOverriding(1);        
                return null;
            }
        };        
        interA.InterA();
    }
}
 
interface InterA {
    public abstract String InterA();
 
}
 
cs

 

'IT > 자바8-람다' 카테고리의 다른 글

람다 내부 구현 설명 및 슈가, 디슈가링이란?  (0) 2020.05.07
람다 원리 및 값 캡쳐란?  (0) 2020.05.07
Identity 함수?  (0) 2020.04.29
자주쓰는 람다  (0) 2020.04.29
람다 사용법 및 규칙  (0) 2020.04.23

+ Recent posts