每日十道面试题(八)

每天进步一点

1.什么是浅拷贝,什么是深拷贝

浅拷贝你可以看成是引用拷贝,就是多了个引用指向同一个内存地址,

深拷贝就是对象拷贝,你自己复制了一个内存来存放,然后新引用指向新地址

比如你盗版别人视频,如果浅拷贝,你只盗版了一个链接地址,别人哪天视频下架了,你链接过去也看不到

如果深拷贝的话,你下载了别人的视频,然后自己发布,给别人 的地址就是自己的盗版视频地址,跟原作者怎么改动视频无关,但是后续更新你要一次次克隆

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object clone = super.clone();
        //深克隆 序列化,反序列化也会克隆
        Video v=(Video)clone;
        //将这个对象的属性也进行克隆
        v.createTime = (Date) this.createTime.clone();
        return clone;
    }

ps:这里的话我建议可以去了解一下设计模式的原型模式哦,花个5分钟就能理解

2.JDK 和 JRE 有什么区别?

JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。
JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。
具体来说 JDK 其实包含了 JRE,同时还包含了编译 java 源码的编译器 javac,还包含了很多 java 程序调试和分析的工具。简单来说:如果你需要运行 java 程序,只需安装 JRE 就可以了,如果你需要编写 java 程序,需要安装 JDK。

一般来说jdk很多工具类最重要的就是rt.jar了根加载器会去找里面的类,ext是扩展加载器,其它是应用加载器

3.synchronized 和 volatile 的区别是什么?

  • volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  • volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
  • volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。
  • volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
  • volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。

你可以把synchronized 想成一个重量级锁,而volatile是轻量级,关于volatile可以看我前几期的面试题里有讲

4.Java 中会存在内存泄漏吗,请简单描述

理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。例如hibernate的Session(一级缓存)还有mybatis的SqlSessionfactory中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露

这里可以了解一下可达性分析,如果跟GCROOT没关系就会被回收,下面是GCroot对象

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象。(可以理解为:引用栈帧中的本地变量表的所有对象)
  2. 方法区中静态属性引用的对象(可以理解为:引用方法区该静态属性的所有对象)
  3. 方法区中常量引用的对象(可以理解为:引用方法区中常量的所有对象)
  4. 本地方法栈中(Native方法)引用的对象(可以理解为:引用Native方法的所有对象)

5.如何实现字符串的反转及替换?

方法很多,可以自己写实现也可以使用String或StringBuffer/StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:

public static String reverse(String originStr) {
      if(originStr == null || originStr.length() <= 1) 
          return originStr;
      return reverse(originStr.substring(1)) + originStr.charAt(0);
  }

或者不允许使用工具类的话,那就自己循环头尾互换,时间是o(N)

6.列出一些你常见的运行时异常?

  • ArithmeticException(算术异常)

  • ClassCastException (类转换异常)

  • IllegalArgumentException (非法参数异常)

  • IndexOutOfBoundsException (下标越界异常)

  • NullPointerException (空指针异常)

  • SecurityException (安全异常)

  • OOM

  • StackflowExcption

  • 并发修改异常

下面三个比较重要

7.线程的sleep()方法和yield()方法有什么区别?

答:
① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;

④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性

yield方法调用后是使线程让出当前cpu资源而已,然后大家再竞争

8.事务的ACID是指什么?

**原子性(Atomic):**事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
一致性(Consistent):事务结束后系统状态是一致的;
隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

9.Servlet的运行过程?(生命周期)

Web容器加载Servlet并将其实例化后,Servlet生命周期开始,容器运行其init()方法进行Servlet的初始化;请求到达时调用Servlet的service()方法,service()方法会根据需要调用与请求对应的doGet或doPost等方法;当服务器关闭或项目被卸载时服务器会将Servlet实例销毁,此时会调用Servlet的destroy()方法。

10.转发(forward)和重定向(redirect)的区别?

forward是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把那个URL 的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。redirect就是服务器端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的链接地址,很明显redirect无法访问到服务器保护起来资源,但是可以从一个网站redirect到其他网站。forward更加高效,所以在满足需要时尽量使用forward(通过调用RequestDispatcher对象的forward()方法,该对象可以通过ServletRequest对象的getRequestDispatcher()方法获得),并且这样也有助于隐藏实际的链接;在有些情况下,比如需要访问一个其它服务器上的资源,则必须使用重定向(通过HttpServletResponse对象调用其sendRedirect()方法实现)。

你可能感兴趣的:(剑指Java面试)