vol.1 java基础

  1. 谈谈你对Java平台的理解?
    Java本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“书写一次,到处运行”(Write once, run anywhere),能够非常容易地获得跨平台能力;另外就是垃圾收集(GC, Garbage Collection),Java通过垃圾收集器(Garbage Collector)回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。
  2. jre和jdk的区别
    我们日常会接触到JRE(Java Runtime Environment)或者JDK(Java Development Kit)。 JRE,也就是Java运行环境,包含了JVM和Java类库,以及一些模块等。
    而JDK可以看作是JRE的一个超集,提供了更多工具,比如编译器、各种诊断工具等。
  3. java是解释执行吗?
    对于“Java是解释执行”这句话,这个说法不太准确。我们开发的Java的源代码,首先通过Javac编译成为字节码(bytecode),然后,在运行时,通过 Java虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。但是常见的JVM,比如我们大多数情况使用的Oracle JDK提供的Hotspot JVM,都提供了JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。
  4. 解释执行和编译执行细节
    在运行时,JVM会通过类加载器(Class-Loader)加载字节码,解释或者编译执行。就像我前面提到的,主流Java版本中,如JDK 8实际是解释和编译混合的一种模式,即所谓的混合模式(-Xmixed)。通常运行在server模式的JVM,会进行上万次调用以收集足够的信息进行高效的编译,client模式这个门限是1500次。Oracle Hotspot JVM内置了两个不同的JIT compiler,C1对应前面说的client模式,适用于对于启动速度敏感的应用,比如普通Java桌面应用;C2对应server模式,它的优化是为长时间运行的服务器端应用设计的。默认是采用所谓的分层编译(TieredCompilation)。
    -Xint
    -Xcom
  5. Error和exception
  6. 谈谈fnal、fnally、 fnalize有什么不同?
    final 可以用在类、方法、和字段上
  7. 反射和动态代理
      是在运行状态中,对于任意一个类,都能够获取这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取类信息以及动态调用对象内容就称为java语言的反射机制
      简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。
      程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
      反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。
      Java 反射框架主要提供以下功能:
      1. 在运行时判断任意一个对象所属的类
      2. 在运行时构造任意一个类的对象
      3. 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用 private 方法)
      4. 在运行时调用任意一个对象的方法
      重点:是运行时而不是编译时
  8. 反射的实现
    要使用一个类,就要先把它加载到虚拟机中,生成一个Class对象。这个class对象就保存了这个类的一切信息。
    反射机制的实现,就是获取这个Class对象,通过Class对象去访问类、对象的元数据以及运行时的数据。
  9. 如何获取class对象
    有三种方法获得类的Class对象:Class.forName(String className)、className.class、实例对象.getClass();
  10. 静态代理和动态代理
  11. 为什么需要代理?
    可以隐藏委托类的实现;
    可以实现客户与委托类之间的解耦, 在不修改委托类代码的情况下能够做一些额外的处理
  12. 静态代理
    首先, 定义接口和接口的实现类, 然后定义接口的代理对象, 将接口的实例注入到代理对象中, 然后通过代理对象去调用真正的实现类,实现过程非常简单也比较容易理解, 静态代理的代理关系在编译期间就已经确定了的。它适合于代理类较少且确定的情况。
  13. 为什么要用动态代理?
    缺点是只适用委托方法少的情况下, 试想一下如果委托类有几百上千个方法, 岂不是很难受, 要在代理类中写一堆的代理方法
  14. JDK 动态代理:
    为了解决静态代理中,生成大量的代理类造成的冗余;
    JDK 动态代理只需要实现 InvocationHandler 接口,重写 invoke 方法便可以完成代理的实现,
    jdk 的代理是利用反射生成代理类 Proxyxx.class 代理类字节码,并生成对象
    优点:解决了静态代理中冗余的代理实现类问题。
    缺点:JDK 动态代理是基于接口设计实现的,如果没有接口,会抛异常。
  15. 为什么jdk动态代理只能代理接口?
    jdk 动态代理之所以只能代理接口是因为代理类本身已经 extends 了 Proxy,而 java 是不允许多重继承的,但是允许实现多个接口
    根据被代理的接口来动态生成代理类的class文件,并加载class文件运行的过程,通过反编译被生成的$Proxy0.class文件发现:
class类定义为:
public final class $Proxy0 extends Proxy implements Interface {
public $Proxy0(InvocationHandler paramInvocationHandler) {
super(paramInvocationHandler);
}
  1. CGLIB 动态代理
    CGLIB 代理是针对类来实现代理的,原理是对指定的委托类生成一个子类并重写其中业务方法来实现代理。代理类对象是由 Enhancer 类创建的。CGLIB 创建动态代理类的模式是:
    1)、查找目标类上的所有非 final 的 public 类型的方法 (final 的不能被重写)
    2)、将这些方法的定义转成字节码
    3)、将组成的字节码转换成相应的代理的 Class 对象然后通过反射获得代理类的实例对象
    4)、实现 MethodInterceptor 接口, 用来处理对代理类上所有方法的请求,实现里面的interceptor方法,
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("方法调用之前");
        Object o = proxy.invokeSuper(obj, args);
        System.out.println("方法调用之后");
        return o;
    }

CGLIB 代理:
由于 JDK 动态代理限制了只能基于接口设计,而对于没有接口的情况,JDK 方式解决不了;
CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,来完成动态代理的实现。
实现方式实现 MethodInterceptor 接口,重写 intercept 方法,通过 Enhancer 类的回调方法来实现。
但是 CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。
同时,由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理。

优点:没有接口也能实现动态代理,而且采用字节码增强技术,性能也不错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值