Java基础知识

1. 如何实现对象克隆?

有两种方式:

  • 实现Cloneable 接口并重写 clone 方法(浅拷贝);

  • 实现Serializable ,通过对象的序列化和反序列化实现真正的深度克隆(深拷贝),代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class MyUtil {

        private MyUtil() {
            throw new AssertionError();
        }

        public static <T> T clone(T obj) throws Exception {

            ByteArrayOutputStream bout = new ByteArrayOutputStream();

            ObjectOutputStream oos = new ObjectOutputStream(bout);

            oos.writeObject(obj);


            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());

            ObjectInputStream ois = new ObjectInputStream(bin);

            return (T) ois.readObject();


            // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义

            // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放

        }
    }

    注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型界定,可以检查出要克隆对象是否支持序列化,这项检查是编译器完成的,不是运行时抛出异常,这种方案明显优于使用object类的clone方法克隆对象。让问题在编译的时候暴漏出来总是优于把问题留在运行时。

2. 内部类访问局部变量的时候,为什么加final?

  • 内部类和局部变量的生命周期不同,方法结束后局部变量的生命周期就结束了,而内部类只要有引用就不结束,内部类生命周期>=局部变量

  • Java会在编译时在内部类的构造方法里边,将局部变量以参数形式传递给内部类

  • 而如果局部变量发生改变,内部类不知情的场景,所以要加fianl ,保证引用不可改变

    注意:在Java8中,可以不适用final关键字,但是如果我们修改了局部变量还是会发生错误,从而保证局部变量的引用不变。

3. transient 关键字

如果使用transient 修饰变量,当对象存储时,它的值不需要维持。换句话来说就是用transient 修饰的变量不参与序列化的过程。

4. String 和 StringBuild,StringBuffer的区别

String 是只读字符串,创建完成之后是不能修改,如果修改也是创建一个新对象,回收旧对象的过程,所以执行效率比较低,StringBuildStringBuffer 可以改变,StringBuild 线程不安全,但是效率比较高,StringBuffter 线程安全

效率快慢:Stringbuilder> StringBuffer> String

5. String 为什么设计成不可变

  • 安全性
    • 本身是final 类不可修改,不可变极为安全
    • String 常被用来作为 HashMapkey 如果可变会引来安全问题,例如两个key 相同
  • 效率高
    • 通过字符串池可以节省很多空间
    • 每一个String 对应一个 hashcode ,再次使用不用重新计算

6. java 中的四种引用及应用场景

  • 强引用
  • 弱引用—-引用到达,不可达就会被回收,即便是内存充足,可用于图片Bitmap 缓存,当不再使用Bitmap 时,就会被回收
  • 软引用—–内存不足时被回收,也可用于Bitmap回收,当内存不足时,可回收
  • 虚引用—-它指向的对象回收时,它本身会被加入到引用队列中,这样我们就知道它指向的对象何时被销毁
-------------本文结束感谢您的阅读-------------