자바 에서 반사 메커니즘 탐색
6105 단어 자바Singleton반사reflectaccessible
문제 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).
이상 은 반사 에 대한 학습 입 니 다.잘못된 점 이 있 으 면 벽돌 을 찍 는 것 을 환영 합 니 다~
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.