2020最新Java面试题(常见面试题及答案汇总)

Java基础篇

1. JDK 和 JRE 的区别是什么?

  • JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。
  • JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。

总结: JDK 包含了 JRE,同时还包含了编译 java 源码的编译器 javac,还包含了很多 java 程序调试和分析的工具。简单来说:如果你需要运行 java 程序,只需安装 JRE 就可以了,如果你需要编写 java 程序,就需要安装 JDK。

2. Java中有哪些数据类型?

Java中数据类型分为基本数据类型和引用数据类型2种

  • 基本类型:byte(默认值0,占1字节)、short(默认值0,占2字节)、int(默认值0,占4字节)、long(默认值0,占8字节)、float(默认值0.0,占4字节)、double(默认值0.0,占8字节)、char(默认值\u0000,占2字节)、boolean(默认值false)
  • 引用类型:类(默认值null)、接口(默认值null)、数组(默认值null)

3. == 和 equals 的区别是什么?

基本类型和引用类型比较,== 的作用效果是不同的。

  • 基本类型:比较的是值是否相同
  • 引用类型:比较的是引用是否相同
	int x = 10;
	int y = 10;
	String a = "panda";
	String b = "panda";
	String c = new String("panda");
	// true 基本类型比较值是否相同
	System.out.println(x == y);
	// true 引用类型比较引用是否相同,这里引用相同
	System.out.println(a == b);
	// false 引用不同
	System.out.println(a == c);
    // true 引用不同,String重写了equals,使其用值比较
    System.out.println(a.equals(c));

equals 本质上就是 ==,Object类中定义的 equals 方法如下

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

总结:== 对于基本类型比较的是值,对于引用类型比较的是引用;而 equals 默认情况下是引用比较,只是很多类重写了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

4. 两个对象的 hashCode() 相同,则 equals() 也一定为 true 正确吗?

不正确,两个对象的 hashCode() 相同,equals() 不一定 true。比如在 map 中,hashCode() 相等,只能说明这两个键值对的哈希值相同,不代表这两个键值对相等。

	String str1 = "通话";
	String str2 = "重地";
	// str1: 1179395 | str2: 1179395
	System.out.println(String.format("str1: %d | str2: %d",str1.hashCode(),str2.hashCode()));
	// false
	System.out.println(str1.equals(str2));

5. Java 中 final 关键字的作用是什么?

  • final 修饰的类叫最终类,不能被继承
  • final 修饰的方法叫最终方法,不能被重写,但可以被继承
  • final 修饰的变量叫常量,必须初始化,初始化之后值不能被修改

6. String、StringBuffer、StringBuilder 的区别是什么?

String 是字符串常量,每次操作都会生产新的对象,适用于少量字符串操作的情况;StringBuffer、StringBuilder 是字符串变量,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

7. String str=“donkey” 与 String str=new String(“donkey”) 一样吗?

不一样,因为内存的分配方式不一样。String str=“donkey”,java 虚拟机会将其分配到常量池中;而 String str=new String(“donkey”) 则会被分到堆内存中。

8. 字符串如何反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法

	StringBuffer stringBuffer = new StringBuffer();
	stringBuffer.append("abcdefg");
	System.out.println(stringBuffer.reverse()); // gfedcba
	StringBuilder stringBuilder = new StringBuilder();
	stringBuilder.append("abcdefg");
	System.out.println(stringBuilder.reverse()); // gfedcba

9. String 类中常用方法都有哪些?

	String str = " app le ";
	// indexOf(): 返回指定字符的索引
	System.out.println(str.indexOf("a")); // 1
	// charAt(): 返回指定索引处的字符
	System.out.println(str.charAt(5)); // l
	// replace(): 字符串替换
	System.out.println(str.replace("pp", "cc")); // " acc le "
	// trim(): 去除字符串两端空白
	System.out.println(str.trim()); // "app le"
	// split(): 分割字符串,返回一个分割后的字符串数组
	String[] arr = str.split(" ");
	// getBytes(): 返回字符串的 byte 类型数组
	byte[] bytes = str.getBytes();
	// length(): 返回字符串长度
	System.out.println(str.length()); // 8
	// toLowerCase(): 将字符串转成小写字母
	System.out.println(str.toLowerCase()); // " app le "
	// toUpperCase(): 将字符串转成大写字符
	System.out.println(str.toUpperCase()); // " APP LE "
	// substring(): 截取字符串
	System.out.println(str.substring(2)); // "pp le "
	// equals(): 字符串比较
	System.out.println("apple".equals(str)); // false

10. 抽象类是什么?

拥有抽象方法(指没有方法体的方法,同时抽象方法还必须使用关键字abstract 做修饰)的类就是抽象类,抽象类要使用 abstract 关键字声明。

11. 抽象类必须要有抽象方法吗?

不需要,抽象类不一定非要有抽象方法,如下代码可以正常运行

public abstract class elephant {
    String str = "apple";
    public void test01(){
        System.out.println("aaaa");
    }
}

12. 普通类和抽象类的区别是什么?

  • 普通类不能包含抽象方法,抽象类可以有抽象方法
  • 普通类可以直接实例化,抽象类不能直接实例化

13. 抽象类能使用 final 修饰吗?

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类。

14. 接口是什么?

接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准。

15. 接口和抽象类的区别是什么?

  • 接口必须使用 implements 来实现接口;抽象类的子类使用 extends 来继承
  • 接口不能有构造函数;抽象类可以有构造函数
  • 一个类只能继承一个抽象类,但可以实现多个接口
  • 抽象类中成员变量默认 default,可在子类中被重新定义,也可被重新赋值,抽象方法被 abstract 修饰,不能被 private、static、synchronized 和 native 等修饰;接口中成员变量默认为 public static final 修饰,必须赋初值,不能被修改,其所有的成员方法默认使用 public abstract 修饰的

16. Java 中 IO 流分几种?

  • 按功能分:输入流(input)、输出流(output)
  • 按类型分:字节流、字符流

字节流和字符流的区别:字节流按 8 位传输,以字节为单位输入输出数据;字符流按 16 位传输,以字符为单位输入输出数据。

17. BIO、NIO、AIO 有什么区别?

  • BIO:同步阻塞 IO,就是我们平常使用的传统 IO,服务器的实现模式是一个请求连接一个线程,并发处理能力低,可能造成不必要的线程开销,严重的还将导致服务器内存溢出。
  • NIO:同步非阻塞 IO,是传统 IO 的升级,服务器的实现模式是多个请求一个线程,即请求会注册到多路复用器Selector上,多路复用器轮询到连接有IO请求时才启动一个线程处理。
  • AIO:异步非阻塞 IO,是 NIO 的升级,也叫 NIO2,服务器的实现模式为多个有效请求一个线程,客户端的IO请求都是由OS先完成再通知服务器应用去启动线程处理(回调)。

18. Files 的常用方法都有哪些?

	// Files.exists():检测文件路径是否存在
	Path path1 = Paths.get("C:\\Users\\e-yangfangchao\\Desktop\\test");
	System.out.println(Files.exists(path1, new LinkOption[]{LinkOption.NOFOLLOW_LINKS})); // true
	// Files.createFile():创建文件
	Path path2 = Paths.get("C:\\Users\\e-yangfangchao\\Desktop\\test\\a.txt");
	try {
	    Path newFilw = Files.createFile(path2);
	} catch (FileAlreadyExistsException e){
	    System.out.println("exists");
	} catch (IOException e) {
	    System.out.println("other wrong");
	}
	// Files.createDirectory():创建文件夹
	Path path3 = Paths.get("C:\\Users\\e-yangfangchao\\Desktop\\test\\newDirectory");
	try {
	    Path newDirectory = Files.createDirectory(path3);
	} catch (FileAlreadyExistsException e) {
	    System.out.println("exists");
	} catch (IOException e){
	    System.out.println("other wrong");
	}
	// Files.delete():删除一个文件或目录
	try {
	    Files.delete(path2);
	} catch (IOException e) {
	    e.printStackTrace();
	}
	// Files.copy():复制文件
	Path source = Paths.get("C:\\Users\\e-yangfangchao\\Desktop\\test\\b.txt");
	Path target = Paths.get("C:\\Users\\e-yangfangchao\\Desktop\\test\\newb.txt");
	try {
	    Files.copy(source,target);
	} catch (FileAlreadyExistsException e) {
	    System.out.println("targetFile already exists");
	} catch (IOException e){
	    System.out.println("other wrong");
	}
	// Files.move():移动文件
	Path source1 = Paths.get("C:\\Users\\e-yangfangchao\\Desktop\\test\\b.txt");
	Path target1 = Paths.get("C:\\Users\\e-yangfangchao\\Desktop\\test\\newDirectory\\a.txt");
	try {
	    Files.move(source1,target1);
	} catch (FileAlreadyExistsException e) {
	    System.out.println("targetFile1 already exists");
	} catch (IOException e){
	    System.out.println("other wrong");
	}
	// Files.size():查看文件个数
	// Files.read():读取文件
	// Files.write():写入文件

Java 容器篇

1. Java 中都有哪些容器?

在这里插入图片描述

2. Collection 和 Collections 的区别是什么?

  • java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection 接口在 Java 类库中有很多具体的实现。Collection 接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有 List 与 Set。
  • Collections 则是集合类的一个工具类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

3. List、Set、Map 之间的区别是什么?

在这里插入图片描述

4. HashMap 和 Hashtable 的区别是什么?

  • hashMap 去除了 HashTable 的 contains() 方法,但是加上了 containsValue() 和 containsKey() 方法。
  • hashTable 是线程同步的,而 HashMap 是非同步的,HashMap 效率上比 hashTable 要高。
  • hashMap 允许空键空值,而 hashTable 不允许。

5. 如何决定使用 HashMap 还是 TreeMap?

在 Map 中做插入、删除和定位元素这类操作,HashMap 是最好的选择。假如你需要对一个有序的 key 集合进行遍历,TreeMap 是更好的选择。

6. HashMap 的实现原理是什么?

HashMap概述: HashMap 是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

HashMap的数据结构: HashMap 实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

当我们往 HashMap 中 put 元素时,首先根据 key 的 hashcode 重新计算 hash 值,根据 hash 值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾。如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。

Jdk1.8 中对 HashMap 的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的 O(n) 到 O(logn)。

发布了87 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43365369/article/details/104356512