자바 고급 특성 - 반사: 코드 에 죽지 않 고 어떻게 new 대상?
10139 단어 자바
오픈 소스 프레임 워 크 에 서 는 같은 알고리즘 으로 서로 다른 데이터 구조 에 대응 하 는 경우 가 많다.예 를 들 어 Spring 의 의존 주입, 우 리 는 자신의 new 대상 을 필요 로 하지 않 습 니 다. 이 일 은 Spring 에 게 맡 깁 니 다.
그러나 우 리 는 new 대상 을 원한 다 면 코드 에 써 야 한다.하지만 스프링 은 우리 클래스 의 이름 을 알 아 맞 히 지 못 할 것 이다. 그러면 스프링 은 어떻게 상 대 를 new 에 게 주 었 을 까?
이것 은 반사 와 떨 어 질 수 없다.
반사 적 의미 와 작용
자바 는 두 가지 조작 방식 이 있 는데 그것 이 바로 비 반사, 반사 이다.
먼저 첫 번 째 방식, 비 반사.
비반 사 는 코드 에 따라 정적 으로 클래스 를 조작 하 는 것 이다.예 를 들 어 다음 코드 는:
public class Application {
public static void main(String[] args) {
//
ClientUser client = new ClientUser();
}
}
이 main () 방법 은 매우 간단 합 니 다. 바로 사용자 대상 을 만 드 는 것 입 니 다.전체 과정 은 이 렇 습 니 다. JVM 이 실행 되 기 전에 어떤 대상 을 만 들 지 먼저 생각 한 다음 코드 에 쓰 고 마지막 으로 main () 방법 을 실행 해 야 합 니 다. JVM 은 사용자 대상 을 만 듭 니 다.
쉽게 말 하면 코드 를 써 서 JVM 에 버 리 고 실행 하면 없어 집 니 다.
이런 상황 에서 프로그래머 는 모든 것 을 통제 해 야 한다. 어떤 대상 을 만 들 려 면 코드 에 미리 써 야 한다.예 를 들 어, 나 는 상점 대상 을 하나 더 만 들 려 면 코드 를 바 꿔 야 한다.
public class Application {
public static void main(String[] args) {
//
ClientUser client = new ClientUser();
//
ShopUser shop = new ShopUser();
// new
}
}
이런 식 으로 라면 수요 가 바 뀌 면 프로그래머 가 코드 를 바 꿔 야 해 작업 효율 이 낮다.예 를 들 어 복잡 한 프로젝트 를 만 났 을 때 대상 을 만 들 뿐만 아니 라 set 구성원 변수 도 있어 야 합 니 다.이렇게 되면 대상 을 새로 추가 할 때마다 너 는 코드 를 한 무더기 고 쳐 야 한다. 조만간 피곤 해 죽 을 것 이다.
그럼 이 일 들 을 간소화 할 수 있 습 니까?
이것 은 두 번 째 조작 류 의 방식 으로 반사 해 야 한다.반 사 는 동적 조작 류 의 메커니즘 이다.예 를 들 어 저 는 대상 을 만 들 려 고 합 니 다. 코드 에 미리 쓰 지 않 고 설정 파일 이나 데이터 베이스 에 두 고 프로그램 이 실 행 될 때 설정 파일 생 성 대상 을 읽 습 니 다.
아니면 위의 코드 가 반사 적 으로 개조 되 어 이렇게 되 었 습 니까?
public class Application {
//
private static Set configs = new HashSet<>();
static {
configs.add("com.jiarupc.reflection.ShopUser");
configs.add("com.jiarupc.reflection.ClientUser");
//
}
public static void main(String[] args) throws Exception {
//
for (String config : configs) {
// , Class
Class clazz = Class.forName(config);
//
Object object = clazz.newInstance();
System.out.println(object);
}
}
}
main () 방법 을 실행 할 때 프로그램 은 설정 파일 을 읽 은 다음 설정 파일 에 따라 대상 을 만 듭 니 다.반 사 를 사용 한 후에 당신 은 일이 가 벼 워 진 것 을 발견 하 였 습 니까?일단 대상 을 새로 추가 하면, 우 리 는 프로필 을 한 줄 만 추가 하면 다른 곳 을 움 직 일 필요 가 없다.
이곳 을 보 니, 너 는 어떤 개원 틀 이 생각 나 지 않 니?예 를 들 어 Spring 의 의존 주입 이다.
// ,Spring
@Service
public class UserService {
// ...
}
어떤 종류 에 주 해 를 한 줄 더 하면 Spring 이 이 종 류 를 인수 할 수 있 습 니 다. 대상 을 어떻게 만 드 는 지 신경 쓰 지 마 세 요.스프링 이 당신 같은 종 류 를 맡 을 수 있 었 던 것 은 자바 의 반 사 를 이 용 했 기 때 문 입 니 다.
쉽게 말 하면 우리 가 반 사 를 잘 사용 하면 중복 되 는 코드 를 많이 줄 일 수 있다.
이제 반사 가 무엇 을 할 수 있 는 지 살 펴 보 자 ~
반사 획득 클래스 정보
만약 당신 이 종 류 를 조작 하고 싶다 면, 이러한 정 보 를 알 아야 합 니 다.예 를 들 어 어떤 변수 가 있 고 어떤 구조 기 가 있 으 며 어떤 방법 이 있 습 니까? 이런 정보 가 없 으 면 코드 도 쓸 수 없고 반 사 는 말 할 것 도 없습니다.
편폭 에 한 하여 우 리 는 클래스 의 대상, 구성원 변수, 방법 을 어떻게 얻 는 지 에 대해 이야기 합 니 다.
Class 대상 은 JVM 만 만 들 수 있 습 니 다. 그 안에 구성원 변수, 방법, 구조 기 등 모든 정보 가 있 습 니 다.
클 라 스 대상 을 만 드 는 것 은 JVM 이 니 상관 하지 않 아 도 된다 는 얘 기다.그러나 반 사 를 통 해 한 종 류 를 조작 하려 면 먼저 이런 종류의 Class 대상 을 받 아야 한다. 이것 은 세 가지 방식 이 있다.
1. Class.forName(" ")
2. .getClass()
3. .class
너 는 아래 의 코드 를 볼 수 있다.
public class User {
public static void main(String[] args) throws Exception {
// 1. Class.forName(" ")
Class clazz1 = Class.forName("com.jiarupc.reflection.User");
// 2. .getClass()
User user = new User();
Class clazz2 = user.getClass();
// 3. .class
Class clazz3 = ClientUser.class;
}
}
이 세 가지 방식 을 통 해 클 라 스 대상 을 얻 으 면 반사 적 으로 정 보 를 얻 을 수 있다.
Field 대상 대표 클래스 의 구성원 변수 입 니 다.우 리 는 클래스 의 구성원 변 수 를 얻 고 싶 습 니 다. 클래스 대상 의 네 가지 방법 을 호출 할 수 있 습 니 다.
1. Field getField(String name) -
2. Field[] getFields() -
3. Field getDeclaredField(String name) -
4. Field[] getDeclaredFields() -
모든 구성원 변 수 를 가 져 오 려 고 시도 합 니 다. 코드 논 리 는 다음 과 같 습 니 다. User 류 의 전체 제한 이름 을 통 해 Class 대상 을 가 져 온 다음 getDeclared Fields () 방법 을 사용 하여 User 류 의 모든 구성원 변 수 를 가 져 오고 마지막 으로 변수 이름, 유형 을 콘 솔 에 출력 합 니 다.
public class User {
//
private Long id;
//
private String username;
public static void main(String[] args) throws Exception {
// Class
Class clazz = Class.forName("com.jiarupc.reflection.User");
//
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String msg = String.format(" :%s, :%s", field.getName(), field.getType());
System.out.println(msg);
}
}
}
Method 대상 대표 클래스 의 방법.하나의 방법 을 얻 으 려 면 Class 대상 도 네 가지 방법 을 제공 합 니 다.
1. Method getMethod(String name, Class[] params) - 、 ,
2. Method[] getMethods() -
3. Method getDeclaredMethod(String name, Class[] params) - 、 ,
4. Method[] getDeclaredMethods() -
마찬가지 로 우 리 는 모든 방법 을 얻 으 려 고 시도 합 니 다. 먼저 User 류 의 전체 제한 이름 을 통 해 Class 대상 을 얻 은 다음 에 getDeclared Methods () 방법 을 호출 하여 User 류 의 모든 구성원 방법 을 얻 고 마지막 으로 방법 명, 형 삼 수량 을 콘 솔 에 출력 합 니 다.
public class User {
//
private Long id;
//
private String username;
public static void main(String[] args) throws Exception {
// Class
Class clazz = Class.forName("com.jiarupc.reflection.User");
//
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
String msg = String.format(" :%s, :%s", method.getName(), method.getParameterCount());
System.out.println(msg);
}
}
}
여 기 를 보면 반사 로 이런 정 보 를 얻 는 방법 을 알 수 있 을 것 이다.
우선, 클래스 를 가 져 오 는 Class 대상 은 세 가지 방식 이 있 습 니 다.그리고 클래스 의 구성원 변 수 를 가 져 옵 니 다. 이것 은 Field 대상 에 대응 합 니 다.마지막 으로 클래스 를 가 져 오 는 방법 은 Method 대상 에 대응 합 니 다.
그러나 반 사 는 이런 정 보 를 얻 을 수 있 을 뿐만 아니 라 조작 류 도 얻 을 수 있다.
반사 조작 류
반 사 는 많은 수작 을 부 릴 수 있 지만 가장 중요 한 것 은 대상 을 만 들 고 호출 하 는 방법 이 라 고 생각 합 니 다.
창설 대상 은 모든 전제 조건 이다.반사 적 으로 대상 을 만 들 지 않 았 다 면 우 리 는 이런 정 보 를 볼 수 밖 에 없 었 을 것 이다.예 를 들 어 어떤 구성원 변수 가 있 고 어떤 방법 이 있 는 지 등 이다.클래스 를 조작 하고 싶다 면, 첫 번 째 단 계 는 대상 을 만 드 는 것 이다.
대상 을 만 들 려 면 클래스 의 구조 기 를 호출 해 야 합 니 다.이것 은 두 가지 상황 으로 나 뉘 는데 가장 간단 한 것 은 네가 한 가지 종 류 를 썼 지만 구조 기 를 쓰 지 않 았 다 는 것 이다. 그러면 이런 종 류 는 인삼 이 없 는 구조 기 를 가지 고 있 으 니 쉽게 할 수 있다.
public class User {
//
private Long id;
//
private String username;
public static void main(String[] args) throws Exception {
// Class
Class clazz = Class.forName("com.jiarupc.reflection.User");
//
Object object = clazz.newInstance();
System.out.println(object);
}
}
클래스 의 Class 대상 을 먼저 가 져 온 다음 new Instance () 를 호출 합 니 다.
하지만 자바 가 가 져 온 구조 기 를 쓰 지 않 고 스스로 쓰 는 경우 도 있다.이러한 상황 은 좀 복잡 할 것 입 니 다. 전 송 된 매개 변수의 유형 을 지정 해 야 합 니 다. 먼저 구조 기 를 가 져 온 다음 에 new Instance () 방법 을 호출 해 야 합 니 다.
public class User {
//
private Long id;
//
private String username;
// 1
public User(Long id) {
this.id = id;
this.username = null;
}
// 2
public User(Long id, String username) {
this.id = id;
this.username = username;
}
public static void main(String[] args) throws Exception {
// Class
Class clazz = Class.forName("com.jiarupc.reflection.User");
// , ,
Constructor constructor = clazz.getConstructor(Long.class, String.class);
Object object = constructor.newInstance(1L, "jiarupc");
System.out.println(object);
}
}
우 리 는 처음부터 id 와 username 을 설정 하려 고 합 니 다. 그러면 매개 변수 유형 을 입력 하고 먼저 찾 아야 합 니 다
2-constructor
.그리고 id 와 username 을 constructor.newInstance()
방법 으로 전송 하면 사용자 대상 을 얻 을 수 있 습 니 다.구조 기 를 가 져 와 대상 을 만 든 후에 우 리 는 대상 의 방법 을 호출 할 수 있다.
대상 을 호출 하 는 방법 은 두 단계 로 나 뉜 다. 첫 번 째 단계, 방법 찾기;두 번 째 단계, 호출 방법.이것 은 듣 기 에 매우 간단 하고, 사실상 매우 간단 하 다.너 는 아래 의 코드 를 볼 수 있다.
public class User {
//
private Long id;
//
private String username;
// .. set/get
public static void main(String[] args) throws Exception {
// Class
Class clazz = Class.forName("com.jiarupc.reflection.User");
//
Object object = clazz.newInstance();
System.out.println(object);
// 、 , -setUsername
Method method = clazz.getMethod("setUsername", String.class);
// object setUsername()
method.invoke(object, "JerryWu");
//
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String msg = String.format(" :%s, :%s", field.getName(), field.get(object));
System.out.println(msg);
}
}
}
우 리 는 방법 명 - setUsername, 매개 변수 유형 - string 을 통 해 setUsername 방법 을 찾 습 니 다.그리고 인자 - username 을 method. invoke () 에 전송 하여 setUsername 방법 을 실행 합 니 다.마지막 으로 모든 구성원 변 수 를 출력 하여 결 과 를 검증 합 니 다.
마지막 에 쓰다
반 사 는 동적 조작 류 의 메커니즘 으로 두 가지 용도 가 있다.
첫 번 째 용 도 는 반 사 를 통 해 우 리 는 구성원 변수, 방법, 구조 기 등 과 같은 정 보 를 얻 을 수 있다.
두 번 째 용 도 는 반 사 를 통 해 우 리 는 하나의 종 류 를 조작 할 수 있다. 이 는 대상 을 만 들 고 대상 을 호출 하 는 방법, 대상 의 구성원 변 수 를 수정 하 는 것 을 포함한다.
프레임 워 크 는 같은 알고리즘 으로 서로 다른 데이터 구조 에 대응 해 야 하기 때문이다.그래서 개원 프레임 워 크 는 반 사 를 많이 사용 했다.예 를 들 어 Spring 의 의존 주입 은 반사 와 떨 어 질 수 없다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.