Java Reflection-2021 인터뷰 질문 시리즈 튜토리얼 (답변 분석 포함)-언어 해석 -JavaPub 버전

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 지식 목록

微信搜:JavaPub,阅读全套系列面试题教程

wx

[꼭지]

이야기

머리말

1. 반사 란 무엇입니까?

Baidu 백과 사전 :

Java의 리플렉션 메커니즘은 프로그램의 실행 상태에서 모든 클래스의 객체를 구성 할 수 있고, 객체가 속한 클래스를 이해할 수 있으며, 모든 클래스의 멤버 변수 및 메서드를 이해할 수 있으며, 개체의 속성 및 메서드. 프로그램 정보를 동적으로 획득하고 객체를 동적으로 호출하는 기능을 Java 언어의 반영 메커니즘이라고합니다. 반영은 동적 언어의 핵심으로 간주됩니다.

Java 런타임 환경에서 모든 클래스에 대해 클래스에 어떤 속성과 메소드가 있는지 알 수 있습니까? 모든 개체에 대해 해당 메서드를 호출 할 수 있습니다.

Java 리플렉션 메커니즘은 주로 다음 기능을 제공합니다.

  1. 런타임에 객체가 속한 클래스를 결정합니다.
  2. 런타임에 모든 클래스의 객체를 생성합니다.
  3. 런타임에 모든 클래스의 멤버 변수와 메서드를 판단합니다.
  4. 런타임에 개체의 메서드를 호출합니다.

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는 객체 상태를 저장하는 데 자신보다 나은 메커니즘, 즉 직렬화를 제공합니다.

직렬화가 필요한 상황

  1. 메모리의 개체 상태를 파일 또는 데이터베이스에 저장하려는 경우
  2. 소켓을 사용하여 네트워크에서 개체를 전송하려는 경우;
  3. 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의 리플렉션을 사용하는 방법?

  • 정규화 된 클래스 이름을 사용하여 개체 만들기
  1. Class.forName ( "Full class name"); 예 : com.mysql.jdbc.Driver Driver 클래스가 jvm에로드되었으며 클래스 초기화가 완료되었습니다.

  2. Class name.class; Get Class <? > clz 객체

  3. Object.getClass ();
  • 생성자 객체를 가져오고 생성자를 통해 객체 생성 new
  1. Clazz.getConstructor ([String.class]);
  2. Con.newInstance ([매개 변수]);
  • 클래스 객체를 통해 인스턴스 객체를 만듭니다 (새 클래스 이름 () 인수없는 생성자와 동일 함).
  1. Cls.newInstance ();
  • 클래스 개체를 통해 속성 개체 얻기
  1. 필드 c = cls.getFields () : 상위 클래스의 필드를 포함하여 특정 클래스의 모든 공용 (공용) 필드를 가져옵니다.

  2. Field c = cls.getDeclaredFields () : public, private 및 protected를 포함하여 특정 클래스의 선언 된 모든 필드를 가져 오지만 부모 클래스의 선언 된 필드는 포함하지 않습니다.
  • 클래스 개체를 통해 메서드 개체 얻기
  1. Cls.getMethod ( "메서드 이름", class …… parameaType); (공개 항목 만 얻을 수 있음)

  2. Cls.getDeclareMethod ( "method name"); (임의로 장식 된 메서드 가져 오기, private 실행 불가)

  3. M.setAccessible (true); (개인 메서드를 실행 가능하게 함)
  • 메소드 실행
  1. Method.invoke (obj 인스턴스 객체, obj 변수 매개 변수); ----- (반환 값 있음)

2021 面试题,认准 JavaPub。

추천

출처blog.51cto.com/14747927/2625652