1. 深拷贝与浅拷贝

深拷贝与浅拷贝的区别在于是否真的获取到一个对象的复制实体而非地址引用。
浅拷贝:复制一个对象,复制后的对象与被复制的对象地址相同
深拷贝:复制一个对象,复制后的对象与被复制的对象地址不同
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,

假设B复制了A,修改A的时候,看B是否发生变化:
如果B跟着也变了,说明是浅拷贝(修改堆内存中的同一个值)
如果B没有改变,说明是深拷贝(修改堆内存中的不同的值)

浅拷贝的效率显然更高。

2. 增强for循环的底层实现

  1. for (Integer i : list) {
  2. System.out.println(i);
  3. }
  4. 反编译后:
  5. Integer i;
  6. for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
  7. i = (Integer)iterator.next();
  8. }
  • 增强for循环底层是通过迭代器的方式实现的;
  • 迭代器是另起一条线程;
  • 任何增强for循环中的操作都是在主线程中进行的;
  • 如果在增强for循环中对被迭代对象进行修改,会产生ConcurrentModifyException。

3. 抽象类与接口的区别

抽象类 接口
被子类继承 被类实现
方法可以有方法体也可以没有方法体 只能有方法声明,不能有方法体
变量是普通变量 定义的变量只能是公共的静态变量
是重构的结果 是设计的结果
抽象级别没有接口高 抽象级别更高
不能多继承 可以多继承接口

4. 面向对象与面向过程的区别

面向对象 面向过程
优点 易维护、易复用、易扩展
有封装继承多态,降低耦合
一般用于嵌入式系统,对性能要求较高
缺点 性能较低一些 面向对象的优点反过来。

5. == 和 equals

==:(严格判断一个对象是否相同)

  1. 比较基本数据类型值是否相同
  2. 比较引用数据类型地址值是否相同

equals:底层调用==
return (this == obj)

6. 为什么重写equals时必须重写hashCode方法?

hashCode()方法是一个native方法,是用c语言或c++实现的,会将对象的内存地址转换为整数之后返回。
hashCode()的作用是获取哈希码值,返回一个int数,确定该对象在hash表中的索引位置。

规定:如果两个对象相等,则hashcode也一定相同。
重写equals后,A1对象和A2对象在业务逻辑上是相同的,但是内存地址不同,所以hashcode值不相同,违背了上述的规定。
HashMap判断两个对象是否相同时根据Node节点的hash值(经过hashcode和hash()方法得到的hash值)

7. final、finally、finalize

final

final:修饰类、方法、变量(成员变量和局部变量)
final修饰类:表明这个类不能被继承,final类中的成员变量可以设为final,但成员方法都会被隐式地指定为final方法。
final修饰方法:锁定方法,防止继承类修改;将final方法转化为内嵌调用,提高效率。
final修饰变量:

  1. 如果是基本数据类型,数值一旦初始化后就不能修改了;
  2. 如果是引用类型,则对其初始化后就不能再指向另一个对象。

final 与 static

finally

抓取到异常后最终执行的步骤

finalize

Object中的方法,当垃圾回收器回收对象所占内存之前被调用,让此对象处理最后的逻辑。

8. 静态内部类的延迟加载

一个类加载的时候不会加载内部类

// static inner Class
public class Outer {
    private Outer(){
        System.out.println("Outer的无参构造 被静态内部类调用");
    }
    static {
        System.out.println("加载Outer类");
    }
    private static Outer getInstance(){
        System.out.println("调用了getInstance方法");
        return StaticInner.outer;
    }

    private static class StaticInner{
        {
            System.out.println("静态内部类的 静态代码块");
        }
        private static Outer outer = new Outer();
    }

    public static void main(String[] args) {
        System.out.println("main方法");
    }
}

控制台结果:

加载Inner类 main方法

9. StringBuffer和StringBuilder

StringBuffer StringBuilder
线程安全,适合多线程环境 线程不安全,适合单线程环境
速度较慢 速度较快