Java常见面试题 1-30

Java基础

1.JDK和JRE有什么区别?

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

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

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

== 解读

对于基本类型和引用类型 == 的作用效果是不同的, 如下所示:

  • 基本类型: 比较的是值是否相同;
  • 引用类型: 比较的是引用是否相同;

代码示例:

String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x==y); // true
System.out.println(x==z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true

代码解读: 因为 x 和 y 指向的是同一个引用, 所以 == 也是 true, 而 new String()方法则重写开辟了内存空间, 所以 == 结果为 false, 而 equals 比较的一直是值, 所以结果都为true.

equals 解读

equals 本质上就是 == , 只不过 String 和 Integer 等重写了 equals 方法, 把它变成了值比较. 看下面的代码就明白了.

首先来看默认情况下 equals 比较一个有相同值的对象, 代码如下:

class Cat {
    public Cat(String name) {
        this.name = name;
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Cat c1 = new Cat("老王");
Cat c2 = new Cat("老王");
System.out.println(c1.equals(c2)); // false

输出结果出乎我们的意料,竟然是 false?这是怎么回事,看了 equals 源码就知道了,源码如下:

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

原来 equals 本质上就是 ==。

那问题来了,两个相同值的 String 对象,为什么返回的是 true?代码如下:

String s1 = new String("老王");
String s2 = new String("老王");
System.out.println(s1.equals(s2)); // true

同样的,当我们进入 String 的 equals 方法,找到了答案,代码如下:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

原来是 String 重写了 Object 的 equals 方法,把引用比较改成了值比较。

总结:

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

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

不对,两个对象的 hashCode()相同,equals()不一定 true。

代码示例:

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

执行的结果:

str1:1179395 | str2:1179395

false

代码解读: 很显然"通话"和"重地"的hashCode()相同,然而 equals()则为false,因为在列表中,hashCode()相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。

4. final 在 java 有什么作用?

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

5. java 中的 Math.round(-1.5)等于多少?

等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以0.5是往上取整,负 0.5 是直接舍弃。

6. String 数据基础数据类型吗?

String不属于基础数据类型,基础数据类型有8种:byte、short、int、loog、float、double、char、boolean,而String属于对象。

7. java 中操作字符串都有哪些类? 它们之间有什么区别?

操作字符串的类有:String、StringBuffer、StringBuilder。

String 和 StringBuilder 的却别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 Stringbuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。

StringBuffer 和 StringBuilder 最大的却别在于,StringBuffer 是线程安全的,而StringBuilder 是非线程安全的,StringBuider 性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

8. String str = "i" 与 String str = new String("i")一样吗?

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

9. 如何将字符串反转?

使用 StringBuilder 或者 StringBuffer 的 reverse() 方法。

实例代码:

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

10. String 类的常用方法都有哪些?

  • indexOf():返回指定字符的索引。
  • charAt():返回指定索引处的符。
  • eqplace():字符串替换。
  • trim():去除字符串两端空白。
  • split():分割字符串,返回一个分割后的字符串数组。
  • getBytes():返回字符串的 byte 类型数组。
  • length():返回字符串长度。
  • toLowerCase():将字符串转成小写字母。
  • toUpperCase():将字符串转成大写字符。
  • substring():截取字符串。
  • equals():字符串比较。

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

不需要,抽象类不一定非要有抽象方法。

示例代码:

abstract class Cat {
    public static void sayHi() {
        System.out.println("hi~");
    }
}

 上面代码,抽象类并没有抽象方法但完全可以正常运行。

12. 普通类和抽象类有哪些区别?

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

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

不能,定义抽象类就是为了让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类,如下图所示,编辑器也会提示错误信息:

 

14. 接口和抽象类有什么区别?

  • 实现:抽象类的子类使用 extends 来继承;实现类必须使用 implements 来实现接口。

  • 构造函数:抽象类可以有构造函数;接口不能有。

  • main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。

  • 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。

  • 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。

15. java 中 IO 流分为几种?

按功能来分:输入流(input)、输出流(output)。

按类型来分:字节流和字符流。

  • 字符流是以Reader,Writer结尾的
  • 字节流是以InputStream或OutputStream结尾的

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

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

  • BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单,使用方便,并发处理能力低。
  • NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务端通过 Channel (通道)通讯,实现了多路复用。
  • AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2, 实现了异步非阻塞 IO,异步 IO 的操作基于事件和回调机制。

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

  • Files.exists():检测文件路径是否存在。
  • Files.createFile():创建文件。
  • Files.createDirectory():创建文件夹。
  • Files.delete():删除一个文件或目录。
  • Files.copy():复制文件。
  • Files.move():移动文件。
  • Files.size():查看文件个数。
  • Files.read():读取文件。
  • Files.write():写入文件。

容器

18. java 容器都有哪些?

常用容器的图录:

19. Collection 和 Collections 有什么区别?

  • java. util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection 接口在 java 类库中有很多具体的实现。Collection 接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。

  • Collections 则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于集合中元素进行排序、搜索以及线程安全等各种操作。

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

 21. HashMap 和 Hashtable 有什么却别?

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

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

对于在 Map 中插入、删除和定位元素这类操作,HashMap 是最好的选择。然而,假如你需要对一个有序的 key 集合进行遍历,TreeMap 是更好的选择。基于你的 Collection 的大小,也许向 HashMap中添加元素会更快,将 map 换为 TreeMap 进行有序的 key 遍历。

23. 说一下 HashMap 的实现原理?

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

HashMap 的数据结构:在 java 编程语言中,最基本的结构就是两种,一个是数组,另一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap 也不例外。HashMap 实际上是一个"链表散列"的数据结构,即数组和链表的集合体。

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

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

24. 说一下 HashSet 的实现原理?

  • HashSet 底层由 HashMap 实现 

  • HashSet 的只存放于 HashMap 的 key 上

  • HashMap 的 value 统一为 PRESENT

25. ArrayList 和 LInkedList 的区别是什么?

最明显的区别是 ArrayList 底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度度是O(1),而 LinkedList 是O(n)。

26. 如何实现数组和 List 之间的转换?

  • List 转换成数组:调用 ArrayList 的 toArray方法。
  • 数组转换成为List:调用 Arrays 的 asList 方法。

27. ArrayList 和 Vector 的区别是什么?

  • Vector 是同步的,而 ArrayList 不是。然而,如果你寻求在迭代的时候对列表进行改变,你应该使用 CopyOnWriteArrayList。
  • ArrayList 比 Vector 快,他因为有同步,不会过载。
  • ArrayList 更加通用,因为我们可以使用 Collections 工具类轻易的获取同步列表和只读列表。

28. Array 和 ArrayList 有何区别?

  • Array 可以容纳基本类型和对象,而 ArrayList 只能容纳对象。

  • Array 是指定大小的,而 ArrayList 大小是固定的。

  • Array 没有提供 ArrayList 那么多功能,比如 addAll、remobeAll和iterator等。

29. 在 Queue 中 poll() 和 remove() 有什么区别?

poll() 和 remove() 都是从列队中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是remove() 失败的时候会抛出异常。

30. 那些集合类是线程安全的?

  • Vector:就比 ArrayList 多了个同步化机制(线程安全),因为效率低,现在已经不太建议使用。在 web 应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
  • Statck:堆栈类,先进后出。
  • HashTable:就比 HashMap多了个线程安全。
  • Enumeration:枚举,相当于迭代器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值