한 편의 글 은 자바 단일 모드 를 실현 하기 위해 매 거 진 을 사용 하 는 것 을 가 르 칩 니 다.

4684 단어 자바매 거일례
전통 적 인 단일 표기 법 은 어떤 문 제 를 해결 하 였 습 니까?
우선,대부분의 경우(면접 포함 되 지 않 음)전통 적 인 단일 표기 법 은 이미 충분히 사용 할 수 있다.synchronized 키 워드 를 통 해 다 중 스 레 드 병행 사용 을 해결 하 였 습 니 다.

    public synchronized static SingleClassV1 getInstance(){
        if(instance == null){
            instance = new SingleClassV1();
        }
        return instance;
    }
매번 단일 대상 을 가 져 올 때마다 자 물 쇠 를 추가 하고 자 물 쇠 를 풀 어야 한 다 는 것 을 고려 합 니 다.또 누군가가 이중 잠 금 검사+volatile 키워드 모드 를 발명 했다.

    private static volatile SingleClassV2 instance;
    public static SingletonV2 getInstance() {
         if(instance == null){
             synchronized (SingletonV2.class){
                 if(instance == null){
                     instance = new SingletonV2();
                 }
             }
         }
         return instance;
     }
또 하나의 사례 가 중복 되 고 초기 화 되 는 것 을 해결 하기 위 한 쓰기:클래스 를 이용 하면 한 번 만 초기 화 되 는 특성 을 이용 하여 내부 사례 의 쓰기 도 발명 되 었 다.

     private static class SingletonHolder {
         private static final SingletonV3 INSTANCE = new SingletonV3();
     }
     public static final SingletonV3 getInstance() {
         return SingletonHolder.INSTANCE;
     }
여전히 존재 하 는 문제
자바 에는 반사 API 라 는 변태 가 존재 하기 때문에 상기 모든 사유 구조 방법 은 반사 앞에서 모두 이슬비 이다.

    Class<?> clazzV2 = Class.forName(SingleClassV2.class.getName());
    Constructor<?> constructor = clazzV2.getDeclaredConstructors()[0];
    constructor.setAccessible(true);
    Object o = constructor.newInstance();
보아하니 사유 방법 은 군 자 를 막 고 소인 을 막 지 않 는 것 같다.
왜 매 거 하면 문제 가 없 습 니까?
매 거 에 기초 한 단일 사례 가 어떤 지 먼저 살 펴 보 자.

public enum SingleClassV4 {
    INSTANCE;
    public String doSomeThing(){
        return "hello world";
    }
}
물론 자바 코드 에 서 는 어떤 단서 도 찾 아 볼 수 없습니다.자바 p 를 사용 하여 바이트 코드 를 보 세 요.

public final class git.frank.SingleClassV4 extends java.lang.Enum<git.frank.SingleClassV4>
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
매 거 진 유형 은 자바.lang.Enum 류 를 자동 으로 계승 하 는 데 도움 을 줄 수 있 습 니 다.또한,flags 에 이 종 류 는 ACC 가 추가 되 었 습 니 다.ENUM 표식.그리고 매 거 류 의 구조 방법 을 살 펴 보 자.

  private git.frank.SingleClassV4();
    descriptor: (Ljava/lang/String;I)V
    flags: ACC_PRIVATE
    Code:
      stack=3, locals=3, args_size=3
         0: aload_0
         1: aload_1
         2: iload_2
         3: invokespecial #6                  
         // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
         6: return
      LineNumberTable:
        line 3: 0//  Java      :756584822      
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       7     0  this   Lgit/frank/SingleClassV4;
    Signature: #29                          // ()V
매 거 류 도 구조 방법 이 있어 야 하고 일반 류 와 다 르 지 않 으 며 반 사 를 통 해 얻 을 수 있다.

다음은 반사 invoke 를 통 해 그의 구조 방법 을 살 펴 보 자.

constructor.newInstance();
결 과 는 다음 과 같다.
Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
new Instance 방법 코드 를 보면 이 유 를 쉽게 알 수 있 습 니 다.

    public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
    {//  Java      :756584822      
        ...
        if ((clazz.getModifiers() & Modifier.ENUM) != 0)
            throw new IllegalArgumentException("Cannot reflectively create enum objects");
        ...
        T inst = (T) ca.newInstance(initargs);
        return inst;
    }
자바 의 반사 API 는 생 성 대상 인 스 턴 스 에서 현재 클래스 가 매 거 진 형식 인지 아 닌 지 를 판단 합 니 다.그렇지 않 으 면 이상 을 던 집 니 다.
총결산
전통 적 인 사례 쓰기 에서 사유 구조 방법 은 외부 에서 인 스 턴 스 를 만 드 는 것 을 완전히 막 을 수 없 기 때문에 엄 밀 히 말 하면 그 사례 의 실현 방식 에 구멍 이 존재 한다.
자바 의 반사 API 는 이미 죽음 을 쓰 는 방식 으로 매 거 진 형식 에 인 스 턴 스 를 만 들 수 없 도록 제한 되 었 기 때문에...됐 습 니 다.해결 되 었 습 니 다.아이고,이 물건 도 면접 에서 물 어 본 거 야.정상 인 이 누가 반사 라 는 걸 로 단 례 를 돌파 하 겠 어.
이 글 은 여기까지 입 니 다.당신 에 게 도움 을 줄 수 있 기 를 바 랍 니 다.또한 당신 이 우리 의 더 많은 내용 에 관심 을 가 져 주 실 수 있 기 를 바 랍 니 다!

좋은 웹페이지 즐겨찾기