자바 에서 반사 메커니즘 탐색

바 쁜 와 중 에 틈 을 내 서 반사 메커니즘 중의 테스트 를 했 는데...
문제 1:비 동시 다발 적 인 상황 에서 도 단일 모델 은 단일 사례 를 보장 할 수 있 습 니까?
먼저 가장 간단 한 단일 모드 를 하 겠 습 니 다.

public class Singleton {

	private static Singleton instance = new Singleton();
	private Singleton() {
	}

	public static Singleton getInstance(){
		return instance;
	}
}

테스트 클래스:

import java.lang.reflect.Constructor;

public class TestSingleton {
	public static void main(String[] args) {
		try {
			Constructor<?> con = Class.forName(Singleton.class.getName()).getDeclaredConstructor();
			con.setAccessible(true);
			Singleton single1 = (Singleton)con.newInstance();
			Singleton single2 = (Singleton)con.newInstance();
			System.out.println("single1.equals(single2):"+single1.equals(single2));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

결과:

single1.equals(single2):false

결론:반 사 된 상황 에서 단일 모드 가 효력 을 잃 는 것 은 반 사 를 통 해 개인 속성 을 얻 을 수 있 고 해당 하 는 setAccessible()방법 을 호출 하면 private 속성 을 효력 을 잃 을 수 있 기 때문이다.그렇다면 어떻게 확실히 하나의 실례 만 있 을 수 있 습 니까?만약 에 어떤 프로그램 이 고의로 반 사 를 통 해 단일 사례 의 제한 을 피한다 면 악성 프로그램 이 든 논리 적 오류 든 runtime Exception 을 버 리 고 프로그램 을 종료 시 킬 수 있다 고 생각 합 니 다.그렇지 않 으 면 여러 개의 인 스 턴 스 가 생 성 되면 결 과 는 통제 할 수 없습니다.개인 개선 사항 은 다음 과 같 습 니 다.

public class Singleton {

	private static Singleton instance = new Singleton();
	private static boolean flag = true;
	private Singleton() {
		if(flag){
			//other code here.....
			flag = !flag;
			return;
		}else{
			throw new RuntimeException("dulpicated instance of "+ Singleton.class.getName());
		}
	}

	public static Singleton getInstance(){
		return instance;
	}
}
test 프로그램 을 다시 실행 한 결 과 는 다음 과 같 습 니 다.

Exception in thread "main" java.lang.ExceptionInInitializerError
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:169)
	at test1.TestSingleton.main(TestSingleton.java:8)
Caused by: java.lang.RuntimeException: dulpicated instance of test1.Singleton
	at test1.Singleton.<init>(Singleton.java:13)
	at test1.Singleton.<clinit>(Singleton.java:5)
	... 3 more

이렇게 하면 하나의 실례 만 보장 할 수 있 습 니 다.물론 더 좋 은 방안 이 있다 면 어서 오 세 요~~
문제 2:반사 할 때 내 가 직접 사유 방법 을 사용한다 면 어떤 상황 이 발생 할 까?
코드:

public class Reflection {
		private void test(){
			System.out.println("test1 private private method");
		}
		public void test2(){
			System.out.println("test2 public sssssssssssssss");
		}
		public static void test3(){
			System.out.println("test333333 sttic sssssssssssssss");
		}
}
     :
public class TestReflection {
	public static void main(String[] args) {
		try {

			Class<?> clazz = Class.forName(Reflection.class.getName());
			Method m = clazz.getDeclaredMethod("test");
			Reflection ref = new Reflection();
			m.invoke(ref);
                     } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

테스트 결과:
[java.lang.IllegalAccessException: Class test1.TestReflection can not access a member of class test1.Reflection with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
	at java.lang.reflect.Method.invoke(Method.java:588)
	at test1.TestReflection.main(TestReflection.java:13)

개 선 된 테스트 코드:
m.invoke(ref)를 실행 하기 전에 m.setAccessible(true)을 호출 합 니 다.즉,

m.setAccessible(true);
m.invoke(ref);

문제 3:만약 방법 중 두 가지 과부하 방법 이 있다 면,각각 test(int a),test(Integer a),어떻게 반 사 를 통 해 해당 하 는 test 방법 을 호출 합 니까?
코드:

public class Reflection {
		public void test(int a){
			System.out.println(a+"int parameter method");
		}
		public void test(Integer a){
			System.out.println(a+"Integer parameter method");
		}
}

구현 코드:

import java.lang.reflect.Method;

public class TestReflection {
	public static void main(String[] args) {
		try {

			Class<?> clazz = Class.forName(Reflection.class.getName());
			Method m1 = clazz.getDeclaredMethod("test",Integer.class);
			Method m2 = clazz.getDeclaredMethod("test",int.class);
			System.out.println(int.class);
			System.out.println(Integer.class);
			Reflection ref = new Reflection();
			Integer in = Integer.valueOf(3);
			m1.invoke(ref,1);
			m1.invoke(ref,in);
			m2.invoke(ref,1);
			m2.invoke(ref,in);
			
			ref.test(1);
			ref.test(in);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

결과 출력:

int
class java.lang.Integer
1Integer parameter method
3Integer parameter method
1int parameter method
3int parameter method
1int parameter method
3Integer parameter method

결론 1:int 와 Integer 대상 은 자동 으로 전환 할 수 있 지만 반사 상황 에서 매개 변수 로 서 두 가 지 는 서로 다른 유형 이다.
결론 2:test(int i)와 test(Integer in)가 동시에 존재 하 는 상황 에서 호출 된 방법 이 Integer 대상 이 라면 자동 으로 가방 을 뜯 지 않 고 test(Integer in)방법 을 직접 호출 합 니 다.그렇지 않 으 면 자동 으로 가방 을 뜯 어 test(int i)방법 을 호출 합 니 다.즉:

Integer in = Integer.valueOf(2);
ref.test(in)//    test(Integer in),           test(int i).

이상 은 반사 에 대한 학습 입 니 다.잘못된 점 이 있 으 면 벽돌 을 찍 는 것 을 환영 합 니 다~

좋은 웹페이지 즐겨찾기