【Java基础】易错面试题2,【反射和动态代理】(更新中...)

1、说一下Java中反射的概念和它的优缺点:

  反射指的是在运行时能够分析类的能力的程序,首先说到反射我们需要知道在正常情况下,如果使用一个类,必须要经过一下几个步骤:

  •  使用important导入类所在的包。

  • 通过关键字new进行类对象实例化

  • 产生对象可以使用“对象.属性” 来进行类中属性的调用

  • 通过“对象.方法()”调用类中的方法    

在反射中,使用一个类并不需要导入类所在的包,只要知道类的完整的路径就可以知道该类中的信息。反射并不需要有明确的类型对象,所有的对象使用Objiect表示。可以直接通过Object的与反射机制的混合调用类中的方法。简单来说,反射机制时程序在运行时能狗获取自身的信息。

在Java中,只要给定类的名字就可以通过反射机制来获取类的所有信息。    

      1. 为什么要使用反射,它在实际编程中有什么应用

    • 静态 编译: 在编译时确定类型,绑定对象即通过。

    • 动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了Java的灵活性,体现了多态的应用,降低类之间的耦合性。

    1.  反射的优点和缺点:

      1. 优点:可以实现动态创建对象和编译,体现出很大的灵活性,

      2. 缺点:对性能有影响。使用反射基本上是一种操作解释, 我们告诉jvm 我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

         

这是在牛客上刷到的一道题考了对Java反射的理解。

A :Filed、Method Constructor分别分别用与描述类的与、方法和构造器。 在Java.lang.reflet包中而Class而是在Java.lang中

B:是对的 ,动态代理就是实现接口的 ,然后我们可以通过类的路径可以的到类的全部信息。(可以看下面的动态代理的原理)

反射常见的作用有:动态加载类、动态获取类的信息(属性、方法、构造器);

动态构造对象;动态调用类和对象的任意方法、构造器;

动态调用和处理属性;

获取泛型信息;处理注解

C:反射的概念中提到过 反射可以通过类的路径来得到该类的全部信息。

D:反射可以动态的调用类和对象的任意方法

E:反射的缺点是对性能有影响

F:反射会降低效率,可是设置禁止安全检查,来提高反射的运行速度;


2、动态代理的原理

由于通过上面反射是可以动态实现接口的 我们扯到了 动态代理,在明白动态代理之前我们要明白什么是代理,

什么是代理模式(Proxy)  给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用

使用的场景有两种:

  • 客户端不想直接访问实际对象,或者访问实际的对象存在技术上的障碍, 因而通过代理对象作为桥梁来完成简介访问;
  • 在不改变目标对象方法的情况下对方法进行增强。

代理又分为静态代理和动态代理,

  • 静态代理:
    • 在不破坏接口实现类的同时又想新增一些功能 怎么办 ? 可以引出动态代理,其实就是创建一个实现接口类,且内部维护一个接口的成员变量指向原始接口的对象,通过代理对象的方法内部调用原始的接口实例的方法;
    • 代码如下:创建一个接口里面有一个方法。
public interface IDveloper {
    public void writeCode();
}
public class Developer  implements  IDveloper{
    private  String name;
    public Developer(String name){
        this.name = name;
    }
    @Override
    public void writeCode() {
        System.out.print("Developer " +name + " wrters code");
    }
}
public class DeveloperTest {
    public static void main(String[] args) {
        IDveloper wrto = new Developer("wtao");
        wrto.writeCode();
    }
}





    • 静态代理的优点: 

    • 容易理解和实现

    • 代理类和真实类的关系是编译期静态决定的,和动态代理比较起来,执行时没有任何额外开销

    • 静态代理的缺点:

    • 接口和代理时1对1的,有多个接口需要代理或接口中有多个方法,就需要创建多个代理类或者实现接口中的方法,繁琐

动态代理:

静态代理受限于接口的实现。而动态代理就是通过反射,动态的获取抽象接口的类型,从而获取相关特性进行代理。

使用动态的代理有三个步骤,

  • 创建一个代理执行类,,必须实现InvocationHandler 接口,表面该类是一个动态代理执行类。

  • 代理类需要实现InvocationHandler接口中的invoke(Object[] proxy,Method,Object[] args)方法【增强被代理类的功能或逻辑的方法】
  • 获取代理类,增强了功能,关键是要获取到代理类的对象,使用静态方法Proxy.newProxylnstance去获取代理的对象。
  • 代码如下: 



获取代理类对象的方法,要传入的3个参数。

    • 第一个参数是类加载器

    • 第二个参数是委托类的接口类型,代理类返回的是同一个实现接口下的类型,保持代理类返回的类型;

    • 第三个参数就是代理类本身,就是告诉代理类,代理类遇到某个原视类的方法时该调用哪个代理执行下的invoke方法;

也可以在定义代理执行类时,直接在类中一个写出public方法来获取代理类的对象。

代码如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DeveloperProxy implements InvocationHandler {
    private  Object target; //被代理的类
   public Object getProxyInstance(Object target){
       this.target = target;
       Object object = Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
       return  object;
   }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.print("还没睡呢? ");
        Object result = method.invoke(target,args);
        System.out.print("你还没睡呢? ");
        return result;
    }
}
	

public class DeveloperTest {

    public static void main(String[] args) {

        //创建被代理的对象

       IDveloper wtao = new Developer("wato");

       //创建被代理执行的对象

        DeveloperProxy jdkProxy = new DeveloperProxy();

        //将被代理对象交给代理类维护且获取代理类对象

        IDveloper WtaoProxy = (IDveloper) jdkProxy.getProxyInstance(wtao);

        WtaoProxy.writeCode();

    }

}

静态代理类和动态代理类的区别

  • 静态代理类需要自己写代理类并一一实现目标方法,且代理类必须实现目标对象相同的接口。
  • 动态代理不需要自己实现代理类,它是利用JDKAPI,动态地子啊内存中构建代理对象需要我们传入被代理类,并且默认实现所有的目标方法。

【完】我是一块小饼干 麻烦大佬点个赞😁
 

全部评论

相关推荐

11-24 19:04
已编辑
湖南工商大学 Java
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
1
1
分享
牛客网
牛客企业服务