Java 基础面经(二)

1 浅拷贝与深拷贝

关于 Java 中的对象克隆,有直接赋值、浅拷贝、深拷贝三种方式。

  1. 直接赋值:例如 Person a = new Person();Person b = a;,这种方法仅仅拷贝了对象引用地址,并没有在内存中生成新的对象。
  2. 浅拷贝:如果原型对象的成员变量是值类型,将复制一份给克隆对象,也就是说在堆中拥有独立的空间;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。换句话说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。要实现浅拷贝,我们只需要被复制类需要实现 Cloneable 接口,重写 clone 方法即可。
  3. 深拷贝:相对于浅拷贝,深拷贝是一种完全拷贝,无论是值类型还是引用类型都会完完全全的拷贝一份,在内存中生成一个新的对象,简单点说就是拷贝对象和被拷贝对象没有任何关系,互不影响。深拷贝有两种方式,一种是跟浅拷贝一样实现 Cloneable 接口,另一种是实现 Serializable 接口,用序列化的方式来实现深拷贝。

2 什么是反射?

java反射机制的理解

3 反射机制的优点与缺点?

  1. 优点:可以实现动态创建对象和编译,体现出很大的灵活性,特别是在 J2EE 的开发中它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
  2. 缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉 JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

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

4 java 元注解的作用?

元注解是 java API 提供,是专门用来定义注解的注解。java 一共有四个元注解:

  1. @Target 表示该注解用于什么地方
  2. @Retention 表示在什么级别保存该注解信息
  3. @Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被 javadoc 工具提取成文档。在 doc 文档中的内容会因为此注解的信息内容不同而不同
  4. @Inherited 允许子类继承父类中的注解

5 jdk 自带的注解?

  1. @Overried:告诉编译器要检查该方法是重写父类的方法
  2. @Deprecated:标记某个类或方法等已经废弃
  3. @SuppressWarnings:抑制编译器警告
  4. @FunctionalInterface:用来指定该接口是函数式接口

6 char 型变量中能不能存贮一个中文汉字,为什么?

可以。因为 Java 中使用的编码是 Unicode,一个 char 类型占2个字节(16比特),所以放一个中文是没问题的。

7 两个对象值相同(x.equals(y) == true),但却可以有不同的 hashcode?

如果该对象重写了 equals 方法,那么可能会出现 equals 相同,但 hashcode 不同的情况,但假如没有重写 equals 方法,那么它默认继承是 Object 的 equals 方法,根据源码可知,此时 equals 相同, hashcode 一定相同。

public boolean equals(Object obj) {
        return (this == obj);
}

需要注意的是,我们在开发的过程中,应保证 equals 相等的对象,hashcode 也必须相等。当重写 equals 方法时有必要重写 hashcode 方法,保证相等的对象有相等的哈希码。

如果两个对象相同(equals 方法返回 true),那么它们的 hashCode 值一定要相同;如果两个对象的 hashCode 相同,这两个对象并不一定相同。

8 List<T>,List<?>,List<Object> 三者的区别?

建议采用的顺序

9 BIO、NIO 和 AIO 的区别?

BIO、NIO和AIO的区别、三种IO的原理与用法

10 Integer 类的缓存机制?

Integer类的缓存机制

11 String 与 int 之间的转换?

示例一

String str = "" + 100;
System.out.println(str);

示例二

String str = Integer.toString(100);
System.out.println(str);

示例三

String str = String.valueOf(100);
System.out.println(str);

重点来了!上面三种方法只有 String.valueOf() 方法会首先对转换的对象进行判空检测,如果为空,则返回 “null” 字符串,以至于不会报出空指针异常。所以,在遇到字符串转换的时候,首选 String.valueOf() 方法。

12 Java 位运算

  1. 左移( << ):5 << 2 = 20
  2. 右移( >> ) :5 >> 2 = 1(正数右移,高位用0补,负数右移,高位用1补)
  3. 无符号右移( >>> ) :使用 >> 会根据原来最高位符号位进行补位,而 >>> 会直接使用0进行补位,故其会由负数变成正数
  4. 位与( & ):第一个操作数的的第 n 位与第二个操作数的第 n 位如果都是1,那么结果的第 n 位也为1,否则为0
  5. 位或( | ):第一个操作数的的第 n 位与第二个操作数的第 n 位只要有一个是1,那么结果的第 n 位也为1,否则为0
  6. 位非( ~ ):第一个操作数的的第 n 位与第二个操作数的第 n 位相反,那么结果的第 n 位也为1,否则为0
  7. 位异或( ^ ):操作数的第 n 位为1,那么结果的第 n 位为0,反之

参考;Java 浅拷贝、深拷贝,你知多少?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章