Java Reflection-2021 인터뷰 질문 시리즈 튜토리얼 (답변 분석 포함)-언어 해석 -JavaPub 버전
머리말
머리말
프레임 워크의 높이에 관계없이 플레이하려면 견고한 기초가 필요하며, 자주 인터뷰 질문은 기초에서 자주 발생하는 실제 전투의 핵심입니다.
독자에게 적합
자바 학습자 및 애호가, 특정 업무 경험이있는 기술 인력, 예비 면접관 등
제안 읽기
이 튜토리얼은 Java 기초, JVM, 컨테이너, 멀티 스레딩, 리플렉션, 예외, 네트워크, 객체 복사, JavaWeb, 디자인 패턴, Spring-Spring MVC, Spring Boot / Spring Cloud, Mybatis / Hibernate, Kafka, RocketMQ를 포함한 일련의 튜토리얼입니다. , Zookeeper, MySQL, Redis, Elasticsearch, Lucene. 길을 잃지 않도록 구독하십시오, 2021 Orly는 제공합니다.
微信搜:JavaPub,阅读全套系列面试题教程
[꼭지]
이야기
머리말
1. 반사 란 무엇입니까?
Baidu 백과 사전 :
Java의 리플렉션 메커니즘은 프로그램의 실행 상태에서 모든 클래스의 객체를 구성 할 수 있고, 객체가 속한 클래스를 이해할 수 있으며, 모든 클래스의 멤버 변수 및 메서드를 이해할 수 있으며, 개체의 속성 및 메서드. 프로그램 정보를 동적으로 획득하고 객체를 동적으로 호출하는 기능을 Java 언어의 반영 메커니즘이라고합니다. 반영은 동적 언어의 핵심으로 간주됩니다.
Java 런타임 환경에서 모든 클래스에 대해 클래스에 어떤 속성과 메소드가 있는지 알 수 있습니까? 모든 개체에 대해 해당 메서드를 호출 할 수 있습니다.
Java 리플렉션 메커니즘은 주로 다음 기능을 제공합니다.
- 런타임에 객체가 속한 클래스를 결정합니다.
- 런타임에 모든 클래스의 객체를 생성합니다.
- 런타임에 모든 클래스의 멤버 변수와 메서드를 판단합니다.
- 런타임에 개체의 메서드를 호출합니다.
JavaPub 참조 거대 : https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html
이 시점에서 여전히 Java 리플렉션에 대한 의문이 있으시면 JavaPub 공식 계정으로 돌아가 더 자세한 설명을 드리겠습니다.
2. Java 직렬화 란 무엇입니까? 어떤 상황에서 직렬화가 필요합니까?
직렬화와 역 직렬화는 Java에서 가장 기본적인 지식 포인트이며 누구나 쉽게 잊을 수 있으며 매일 사용하지만 명확하게 설명하지 못할 수도 있습니다. 많은 친구들이 개념과 키워드 (Serializable)가 몇 개 밖에 없다고 생각하는데, 직렬화와 역 직렬화가 어떻게 구현되는지, 사용 시나리오 등에 대해 문의하면 헤매게 될지도 모릅니다. 면접관으로서 Java의 기본 사항을 검토 할 때마다 Java 기본 사항을 측정하기 위해 일반적으로 직렬화 및 역 직렬화에 대한 지식을 묻습니다. Java 직렬화가 무엇인지 물으면 역 직렬화 란 무엇입니까? 어떤 시나리오에서 사용됩니까? 사용하지 않으면 어떤 문제가 생기나요? 일반적으로 모든 사람의 대답은 몇 가지 간단한 개념에 불과합니다. 몇 년 동안 일한 지원자는 개념을 명확하게 설명하지 못하고 지루해 보입니다.
직렬화 및 역 직렬화 란?
序列化是指将Java对象转换为字节序列的过程,而反序列化则是将字节序列转换为Java对象的过程。
Java对象序列化是将实现了 Serializable 接口的对象转换成一个字节序列,能够通过网络传输、文件存储等方式传输 ,传输过程中却不必担心数据在不同机器、不同环境下发生改变,也不必关心字节的顺序或其他任何细节,并能够在以后将这个字节序列完全恢复为原来的对象(恢复这一过程称之为反序列化)。
对象的序列化是非常有趣的,因为利用它可以实现轻量级持久性,“持久性”意味着一个对象的生存周期不单单取决于程序是否正在运行,它可以生存于程序的调用之间。通过将一个序列化对象写入磁盘,然后在重新调用程序时恢复该对象,从而达到实现对象的持久性的效果。
本质上讲,序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态。
간단히 말해, 다양한 객체의 상태를 메모리 (즉, 메서드가 아닌 인스턴스 변수)에 저장하고 저장된 객체 상태를 읽는 것입니다. 다양한 방법을 사용하여 객체 상태를 저장할 수 있지만 Java는 객체 상태를 저장하는 데 자신보다 나은 메커니즘, 즉 직렬화를 제공합니다.
직렬화가 필요한 상황
- 메모리의 개체 상태를 파일 또는 데이터베이스에 저장하려는 경우
- 소켓을 사용하여 네트워크에서 개체를 전송하려는 경우;
- RMI를 통해 개체를 전송하려는 경우;
직렬화 및 역 직렬화를 사용해야하는 이유
서로 다른 프로세스 / 프로그램 간의 원격 통신을 할 때 텍스트, 사진, 오디오, 비디오 등 다양한 유형의 데이터가 서로에게 전송 될 수 있으며 이러한 데이터는 바이너리 형태로 네트워크에서 전송됩니다. 순서.
그렇다면 두 개의 Java 프로세스가 통신 할 때 프로세스 간의 객체 전송이 실현 될 수 있습니까? 물론 가능합니다! 어떻게하나요? 이를 위해서는 Java 직렬화 및 역 직렬화를 사용해야합니다. 송신자는이 Java 오브젝트를 바이트 시퀀스로 변환 한 다음 네트워크에서 전송해야하며 수신자는 바이트 시퀀스에서 Java 오브젝트를 복원해야합니다.
Java 직렬화 및 역 직렬화를 사용해야하는 이유를 이해 한 후 자연스럽게 Java 직렬화의 이점을 생각합니다.
데이터의 지속성 실현 직렬화를 통해 데이터를 하드 디스크에 영구적으로 저장 (예 : 파일에 저장)하여 개체를 영구적으로 보존 할 수 있습니다.
직렬화를 사용하여 원격 통신, 즉 네트워크에서 개체를 전송하는 기능을 수행합니다.
JavaPub 참조 거인 : https://xcbeyond.blog.csdn.net/article/details/100046212
3. 동적 프록시 란 무엇입니까? 응용 프로그램은 무엇입니까?
동적 프록시 : 런타임에 대상 클래스를 만들고 대상 클래스의 메서드를 호출하고 확장 할 수 있습니다.
자바에서 역학을 실현하는 방법 : JDK의 동적 프록시 및 자바 클래스 라이브러리 CGLib.
다음과 같은 애플리케이션 시나리오 :
-
각 API 요청의 시간 소비량 계산
-
통합 로그 출력
-
호출 된 API가 로그인되어 있고 인증이 승인되었는지 확인
- Spring의 AOP 함수 모듈은 aspect 프로그래밍을 실현하기 위해 동적 프록시 메커니즘을 사용합니다.
JavaPub 참조 거인 : https://www.cnblogs.com/aheizi/p/4861422.html
4. 동적 프록시를 구현하는 방법은 무엇입니까?
Java 필드에는 일반적으로 사용되는 두 가지 동적 프록시 구현 방법이 있습니다. 하나는 JDK 리플렉션 메커니즘을 사용하여 프록시를 생성하는 것이고 다른 하나는 CGLIB 프록시를 사용하는 것입니다.
JDK 프록시는 인터페이스를 제공해야하지만 CGLIB는 클래스를 직접 프록시 할 필요가 없습니다. 아래에 예가 나와 있습니다.
1. JDK 동적 프록시 :
public interface People {
public void sayHello();
}
public class Chinese implements People {
@Override
public void sayHello() {
System.out.println("Chinese say hello.");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PeopleInvocationHandler implements InvocationHandler{
private Object peolple;
Intermediary(Object people){
this.people = people;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable { Object invoke = method.invoke(people, args);
System.out.println("-------- end ---------");
return invoke;
}
}
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
People chinese = new People();
PeopleInvocationHandler invocationHandler = new PeopleInvocationHandler(chinese);
People proxy = (People) Proxy.newProxyInstance(chinese.getClass().getClassLoader(), chinese.getClass().getInterfaces(), invocationHandler);
proxy.sayHello();
}
}
2. CGLIB 동적 에이전트
需要引入CGLIB相关Jar包
public class Chinese {
public void sayHello(){
System.out.println("Chinese say hello");
}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ChinesePoxy implements MethodInterceptor {
@Override
public Object intercept(Object object, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {
Object intercept = methodProxy.invokeSuper(object, args);
System.out.println("-------- end ---------");
return intercept;
}
}
import net.sf.cglib.proxy.Enhancer;
public class Test {
public static void main(String[] args) {
ChineseProxy chineseProxy = new ChineseProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Chinese.class);
enhancer.setCallback(chineseProxy);
Chinese proxy = (Chinese) enhancer.create();
proxy.sayHello();
}
}
JavaPub 참조 거인 : https://www.cnblogs.com/xifengxiaoma/p/9377261.html
Java의 리플렉션을 사용하는 방법?
- 정규화 된 클래스 이름을 사용하여 개체 만들기
-
Class.forName ( "Full class name"); 예 : com.mysql.jdbc.Driver Driver 클래스가 jvm에로드되었으며 클래스 초기화가 완료되었습니다.
-
Class name.class; Get Class <? > clz 객체
- Object.getClass ();
- 생성자 객체를 가져오고 생성자를 통해 객체 생성 new
- Clazz.getConstructor ([String.class]);
- Con.newInstance ([매개 변수]);
- 클래스 객체를 통해 인스턴스 객체를 만듭니다 (새 클래스 이름 () 인수없는 생성자와 동일 함).
- Cls.newInstance ();
- 클래스 개체를 통해 속성 개체 얻기
-
필드 c = cls.getFields () : 상위 클래스의 필드를 포함하여 특정 클래스의 모든 공용 (공용) 필드를 가져옵니다.
- Field c = cls.getDeclaredFields () : public, private 및 protected를 포함하여 특정 클래스의 선언 된 모든 필드를 가져 오지만 부모 클래스의 선언 된 필드는 포함하지 않습니다.
- 클래스 개체를 통해 메서드 개체 얻기
-
Cls.getMethod ( "메서드 이름", class …… parameaType); (공개 항목 만 얻을 수 있음)
-
Cls.getDeclareMethod ( "method name"); (임의로 장식 된 메서드 가져 오기, private 실행 불가)
- M.setAccessible (true); (개인 메서드를 실행 가능하게 함)
- 메소드 실행
- Method.invoke (obj 인스턴스 객체, obj 변수 매개 변수); ----- (반환 값 있음)
2021 面试题,认准 JavaPub。