자바 의 매 거,주해 와 반사(2)
반사 란 무엇 입 니까?
반사 란 프로그램 이 실행 되 는 동안 Reflection Api 를 통 해 모든 종류의 내부 정 보 를 얻 을 수 있 고,임의의 종류의 방법 과 속성 을 직접 조작 할 수 있 는 방법 을 말한다.반 사 는 동적 언어의 관건 으로 여 겨 진다.
//
@Test
public void Test1() {
// Person
Person person = new Person("name", 78);
//
person.setAge(20);
System.out.println(person.toString());
person.show();
// Person ,
}
//
@Test
public void Test2() throws Exception {
// Person
Class classPerson = Person.class;
Constructor constructor = classPerson.getConstructor(String.class, int.class);
Object object = constructor.newInstance("Tom", 13);
Person person = (Person) object;
System.out.println(person.toString());
// Person
Field name = classPerson.getField("name");
name.set(person, "Jack");
System.out.println(person.toString());
//
Method show = classPerson.getDeclaredMethod("show");
show.invoke(person);
//
Constructor constructor1 = classPerson.getDeclaredConstructor(String.class);
constructor1.setAccessible(true);
Person person1 = (Person) constructor1.newInstance("Marry");
System.out.println(person1);
//
Method showNation = classPerson.getDeclaredMethod("showNation", String.class);
showNation.setAccessible(true);
showNation.invoke(person1, " ");
}
결과:미사 용 반사
사용 반사:
Person 류
package reflection;
/**
* user:ypc;
* date:2021-06-20;
* time: 13:55;
*/
public class Person {
public String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age) {
this.age = age;
this.name = name;
}
private Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void show() {
System.out.println("I am a person");
}
private String showNation(String nation) {
return nation;
}
}
반사 적 용도1.일상적인 제3자 응용 개발 과정 에서 특정한 유형의 특정한 구성원 변수,방법 또는 속성 이 개인 적 이거 나 시스템 응용 에 만 개방 되 는 경우 가 많다.이때 자바 의 반사 체 제 를 이용 하여 반 사 를 통 해 필요 한 개인 구성원 이나 방법 을 얻 을 수 있다.
2.반사 의 가장 중요 한 용 도 는 바로 각종 유 니 버 설 프레임 워 크 를 개발 하 는 것 입 니 다.예 를 들 어 spring 에서 우 리 는 모든 종류의 Bean 을 spring 용기 관리 에 맡 깁 니 다.XML 설정 Bean 이 든 주해 설정 이 든 용기 에서 Bean 을 가 져 와 주입 에 의존 할 때 용 기 는 설정 을 읽 습 니 다.설정 에서 주 는 것 은 바로 유형의 정보 입 니 다.spring 은 이러한 정보 에 따라 Bean 을 만들어 야 합 니 다.spring 은 이러한 종 류 를 동적 으로 만 듭 니 다.
자바 프로그램의 많은 대상 이 실 행 될 때 두 가지 유형 이 나타 납 니 다.실 행 될 때 유형(RTTI)과 컴 파일 할 때 유형,예 를 들 어 Person p=new Student();이 코드 에서 p 는 컴 파일 할 때 Person 형식 이 고 실행 할 때 Student 형식 입 니 다.프로그램 은 실행 할 때 대상 과 클래스 의 진실 한 정 보 를 발견 해 야 한다.반사 프로그램 을 사용 하면 이 대상 과 클래스 가 어떤 종류 에 속 하 는 지 판단 할 수 있다.
클래스 가 불 러 오 면 쌓 인 구역 에 Class 대상 이 생 깁 니 다.이 대상 은 이러한 종류의 모든 구조 정 보 를 포함 합 니 다.우 리 는 이 대상 을 통 해 이런 종류의 모든 정 보 를 볼 수 있다.
이 대상 은 거울 과 같 아서 이 거울 을 통 해 이런 모든 정보 구 조 를 볼 수 있다.반사 라 고 합 니 다.
정상 적 인 방식:가 져 올 패키지 의 이름 을 도입 합 니 다.->new 를 통 해 예화 합 니 다.->예화 대상 을 얻 습 니 다.
반사 방식:실례 화 대상->getClass()방법->을 통 해 완전한 패키지 클래스 의 이름 을 얻 을 수 있 습 니 다
반사 의 구체 적 인 작용
4.567917.운행 할 때 임의의 대상 이 속 한 종 류 를 판단 한다4.567917.운행 할 때 임의의 유형의 대상 을 구성한다4.567917.실행 할 때 임의의 유형의 구성원 변수 와 방법 을 판단 한다
반사의 주 API
아 날로 그 용도
4.567914.대표 클래스 의 실체,실행 중인 자바 응용 프로그램 에서 클래스 와 인 터 페 이 스 를 표시 합 니 다.
대표 클래스 의 구성원 변수/클래스 의 속성
대표 적 인 방법
대표 적 인 구조 방법
직접 new 방식 과 반 사 를 통 해 공공 구 조 를 직접 호출 할 수 있 는데 개발 할 때 어떤 것 을 사용 해 야 합 니까?
제안:new 방식 으로 대상 을 만 듭 니 다.
반 사 는 언제 사용 합 니까?
반사 적 특성:동적.컴 파일 할 때 어떤 대상 을 만 들 지 모 를 때 반사 방식 으로 대상 을 만 들 수 있다 는 것 이다.예 를 들 어 백 엔 드 에 배 치 된 서버,전단 에서 들 려 올 때 로그 인 요청 을 하면 로그 인 에 대응 하 는 대상 을 만 듭 니 다.전단 에서 등록 에 대응 하 는 요청 이 들 어 오 면 로그 인 에 대응 하 는 대상 을 만 드 는 것 이 반 사 된 동적 특성 입 니 다.
반사 적 인 메커니즘 과 포장 은 모순 되 지 않 습 니까?
포장 은 너 에 게 조절 하지 말 라 고 말 하 는 것 이 고 반 사 는 조절 할 수 있다.
클래스 클래스
Object 클래스 에서 다음 과 같은 방법 을 정 의 했 습 니 다.이 방법 은 모든 하위 클래스 에 의 해 계 승 됩 니 다.
public final Class getClass()
이상 의 방법 으로 값 을 되 돌려 주 는 유형 은 클래스 클래스 입 니 다.이것 은 자바 반사 의 원천 입 니 다.실제로 반사 라 는 것 은 프로그램의 운행 결 과 를 보면 이해 하기 쉽 습 니 다.즉,대상 을 통 해 클래스 의 이름 을 반사 적 으로 구 할 수 있 습 니 다.대상 이 반 사 를 사용 한 후에 얻 을 수 있 는 정보:특정한 유형의 속성,방법 과 구조 기,특정한 유형 이 도대체 어떤 인 터 페 이 스 를 실현 하 는 지.각 클래스 에 대해 JRE 는 변 하지 않 는 Class 형식의 대상 을 보존 합 니 다.하나의 Class 대상 은 특정한 구조(class/interface/enum/annotation/primitive type/void/[])에 대한 정 보 를 포함 하고 있 습 니 다.즉,이러한 유형 은 class 대상 이 있 을 수 있 습 니 다.class 구성원 내부 류,정적 내부 류,국부 내부 류,익명 내부 류,인터페이스,배열,매 거 진,주석,기본 적 인 데이터 유형,void 등 이 있 습 니 다.
주의:
Class 자체 도 클래스 입 니 다.
Class 대상 은 시스템 에서 만 대상 을 만 들 수 있 습 니 다.
불 러 오 는 클래스 는 JVM 에서 하나의 Class 인 스 턴 스 만 있 습 니 다.
Class 대상 은 JVM 에 불 러 온.class 파일 에 대응 합 니 다.
모든 종류의 인 스 턴 스 는 자신 이 어떤 Class 인 스 턴 스 로 생 성 되 었 는 지 기억 합 니 다.
클래스 를 통 해 클래스 에 불 러 오 는 모든 구 조 를 완전 하 게 얻 을 수 있 습 니 다.
Class 클래스 는 Reflection 의 근원 입 니 다.동적 으로 불 러 오고 실행 하고 싶 은 모든 클래스 에 대해 해당 하 는 Class 대상 을 먼저 얻어 야만 계속 할 수 있 습 니 다.
java.lang.Class 에 대한 이해:
클래스 로 딩 과정:
프로그램 은 javac.exe 명령 을 통 해 하나 이상 의 바이트 파일 을 생 성 합 니 다.이 어 자바.exe 명령 을 사용 하여 어떤 바이트 파일 에 대해 실행 을 설명 합 니 다.메모리 에 바이트 코드 파일 을 불 러 옵 니 다.이 과정 을 클래스 로 불 러 옵 니 다.메모리 에 불 러 온 클래스 를 실행 클래스 라 고 합 니 다.이 실행 클래스 를 Class 의 인 스 턴 스 라 고 합 니 다.
Class 인 스 턴 스 는 실행 중인 클래스 에 대응 합 니 다.메모리 에 불 러 오 는 실행 중인 클래스 는 캐 시 됩 니 다.이 시간 안에 실행 시 류 를 다른 방식 으로 가 져 올 수 있 습 니 다.
Class 인 스 턴 스 를 가 져 오 는 네 가지 방식
// Class
@Test
public void test3() throws ClassNotFoundException {
// 1 :.class
Class clazz1 = Person.class;
System.out.println(clazz1);
// 2
Person person = new Person();
Class clazz2 = person.getClass();
System.out.println(clazz2);
// 3 Class forName( )
Class clazz3 = Class.forName("reflection.Person");
System.out.println(clazz3);
// 4 :ClassLoader
ClassLoader classLoader = ReflectionDemo1.class.getClassLoader();
Class clazz4 = classLoader.loadClass("reflection.Person");
System.out.println(clazz4);
System.out.println(clazz1 == clazz2);
System.out.println(clazz1 == clazz3);
System.out.println(clazz1 == clazz4);
}
반 사 를 통 해 실행 중인 클래스 의 대상 을 만 듭 니 다.
package reflection;
import org.junit.Test;
import java.util.Random;
/**
* user:ypc;
* date:2021-06-21;
* time: 20:36;
*/
public class NewInstanceDemo {
@Test
public void test1() throws IllegalAccessException, InstantiationException {
Class<Person> personClass = Person.class;
/*
newInstance() ,
*/
Person person = personClass.newInstance();
System.out.println(person);
}
@Test
public void test2() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
// 。
for (int i = 0; i < 100; i++) {
int num = new Random().nextInt(3);
String classPath = "";
switch (num) {
case 0:
classPath = "java.util.Date";
break;
case 1:
classPath = "java.lang.Object";
break;
case 2:
classPath = "reflection.Person";
break;
}
Object object = getInstance(classPath);
System.out.println(object);
}
}
//
public Object getInstance(String classPath) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class clazz = Class.forName(classPath);
return clazz.newInstance();
}
}
반사 로 실행 클래스 의 속성 및 권한 수정자,변수 이름,데이터 형식 가 져 오기
@Test
public void test1(){
//getFields() public
Class clazz = Person.class;
Field[] fields = clazz.getFields();
for (Field field: fields) {
System.out.println(field);
}
System.out.println();
//getDeclaredFields():
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field:declaredFields) {
System.out.println(field);
}
}
//
@Test
public void test2(){
Class clazz = Person.class;
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field:declaredFields) {
//
System.out.println(Modifier.toString(field.getModifiers())+"\t");
//
System.out.println(field.getType()+"\t");
//
System.out.println(field.getName()+"\t");
}
}
반 사 를 통 해 운행 시 클래스 의 방법 구조 와 내부 구 조 를 얻 을 수 있 습 니 다.
package reflection2;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* user:ypc;
* date:2021-06-22;
* time: 13:32;
*/
public class MethodDemo {
@Test
public void test1() {
// public
Class clazz = Person.class;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println();
//
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
}
//@xxx
//
@Test
public void test2() {
Class clazz = Person.class;
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods) {
//
Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
System.out.print(annotation);
}
//
System.out.print(Modifier.toString(method.getModifiers()) + "\t");
//
System.out.print(method.getReturnType().getName() + "\t");
//
System.out.print(method.getName());
System.out.print("(");
//
Class[] parameterTypes = method.getParameterTypes();
if (!(parameterTypes == null && parameterTypes.length == 0)) {
for (int i = 0; i < parameterTypes.length; i++) {
if (i == parameterTypes.length - 1) {
System.out.print(parameterTypes[i].getName() + " args__" + i);
} else {
System.out.print(parameterTypes[i].getName() + " args__" + i + ",");
}
}
}
System.out.print(")");
//
Class[] exceptionTypes = method.getExceptionTypes();
if (exceptionTypes.length != 0) {
System.out.print("throws");
for (int i = 0; i < exceptionTypes.length; i++) {
if (i == exceptionTypes.length - 1) {
System.out.print(exceptionTypes[i].getName());
} else {
System.out.print(exceptionTypes[i].getName() + ",");
}
}
}
System.out.println();
}
}
}
test1():test2():
반 사 를 통 해 운행 시 클래스 의 구조 구 조 를 가 져 옵 니 다.
@Test
public void test1() {
Class clazz = Person.class;
// public
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println();
//
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
}
반 사 를 통 해 실행 중인 부류 의 부류 와 부류 의 범 형,주해,인터페이스,소재 패 키 지 를 가 져 옵 니 다.
사용 한 가방,인터페이스,클래스,주석 등 을 반사 합 니 다.👇
package reflection2;
/**
* user:ypc;
* date:2021-06-21;
* time: 21:38;
*/
public interface MyInterface {
void info();
}
package reflection2;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
@Target({TYPE, FIELD,CONSTRUCTOR,ANNOTATION_TYPE,PARAMETER,LOCAL_VARIABLE,METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "hello";
}
package reflection2;
import java.io.Serializable;
/**
* user:ypc;
* date:2021-06-21;
* time: 21:13;
*/
public class Creature<T> implements Serializable {
private char gender;
public double weight;
private void breath(){
System.out.println("creature breath");
}
public void eat(){
System.out.println("creature eat");
}
}
package reflection2;
@MyAnnotation(value = "hi")
public class Person extends Creature<String> implements Comparable, MyInterface {
private String name;
public int age;
int id;
Person() {
}
@MyAnnotation(value = "a")
private Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private String show(String nation) throws NullPointerException,CloneNotSupportedException {
System.out.println("I am form" + nation);
return nation;
}
private static void showInterests(){
System.out.println("I like programmer");
}
@MyAnnotation(value = "b")
public String show2(String publicMethod) {
return publicMethod;
}
@Override
public int compareTo(Object o) {
return 0;
}
@Override
public void info() {
System.out.println("I am a Person");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
package reflection2;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
/**
* user:ypc;
* date:2021-06-22;
* time: 15:11;
*/
public class ConstructorDemo {
@Test
public void test1() {
Class clazz = Person.class;
// public
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println();
//
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
}
@Test
public void test2() {
//
Class clazz = Person.class;
System.out.println(clazz.getSuperclass());
//
System.out.println(clazz.getGenericSuperclass());
//
System.out.println(((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0]);
System.out.println();
//
Class[] interfaces = clazz.getInterfaces();
for (Class intF : interfaces) {
System.out.println(intF);
}
System.out.println();
//
Class[] supInterfaces = clazz.getSuperclass().getInterfaces();
for (Class intF : supInterfaces) {
System.out.println(intF);
}
//
System.out.println(clazz.getPackage());
System.out.println();
//
System.out.println(Arrays.toString(clazz.getAnnotations()));
;
}
}
실행 시 클래스 의 지정 속성,방법,구조 방법 을 반사 적 으로 호출 합 니 다.
package reflection2;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* user:ypc;
* date:2021-06-22;
* time: 15:57;
* : 、 、
*/
public class ReflectionDemo {
@Test
public void test1() throws Exception {
Class clazz = Person.class;
//
Person person = (Person) clazz.newInstance();
// , public
Field id = clazz.getField("id");
id.set(person, 10001);
int fieldId = (int) id.get(person);
System.out.println(fieldId);
}
@Test
public void test2() throws Exception {
Class clazz = Person.class;
//
Person person = (Person) clazz.newInstance();
//getDeclaredField
Field name = clazz.getDeclaredField("name");
//
name.setAccessible(true);
//
name.set(person, "Tom");
System.out.println(name.get(person));
}
//
@Test
public void test3() throws Exception {
Class clazz = Person.class;
//
Person person = (Person) clazz.newInstance();
//1. getDeclaredMethod() ,
Method show = clazz.getDeclaredMethod("show", String.class);
//2.
show.setAccessible(true);
//3. invoke() ,
show.invoke(person, " CHN");
//invoke
Object returnValue = show.invoke(person, " CHN");
System.out.println(returnValue);
//
Method showInterests = clazz.getDeclaredMethod("showInterests");
showInterests.setAccessible(true);
showInterests.invoke(Person.class);
// , invoke null
System.out.println(showInterests.invoke(Person.class));
}
/*
*/
@Test
public void test4() throws Exception {
Class clazz = Person.class;
//1.
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//2.
constructor.setAccessible(true);
//3.
Person person = (Person) constructor.newInstance("Tom");
System.out.println(person);
}
}
test1():test2():
test3():
test4():
총결산
이 글 의 전반 부 는 여기까지 입 니 다.당신 에 게 도움 이 되 기 를 바 랍 니 다.또한 당신 이 우리 의 더 많은 내용 에 관심 을 가 져 주 기 를 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.