Java基础面试题(I)

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. == 和 equals 的区别是什么?

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

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

代码示例

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

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

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

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

原来 equals 本质上就是 ==。

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

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

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

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

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

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

代码示例

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

4. final 在 java 中有什么作用?与finally、finalize的区别

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

    * finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码放入finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。

    * finalize是一个方法,属于Object类的一个方法。该方法一般由垃圾回收器来调用,回收垃圾。

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

等于2 和 -1,因为四舍五入的原理是在参数上加 0.5 然后进行下取整。

6. String 属于基础的数据类型吗?

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

Java基本数据类型图

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

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

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

StringBuffer 和 StringBuilder  最大的区别在于,StringBuffer是线程安全的,而StringBuilder是非线程安全的,但 StringBuilder 的性能却高于 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() 方法。

代码示例

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

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

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

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

该抽象类中并没有抽象方法,但完全可以正常运行。

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

* 普通类不能包含抽象方法,抽象类可以包含抽象方法。

* 抽象类不能直接实例化,普通类可以直接实例化。

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

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

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

* 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
* 构造函数:抽象类可以有构造函数;接口不能有。
* main方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
* 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
* 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。

15. java 中 IO 流分为几种?

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

按类型来分:字节流(InputStream)和字符流(Reader)。

按效率来分:普通流和高效流(BufferedInputStream)

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 都实现了 Map接口,因此很多特性非常相似。但是,他们有以下不同点:

    1)HashMap 允许键和值是null,而 Hashtable 不允许键或者值是 null。
    2)Hashtable 是同步的,而 HashMap 不是。因此,HashMap 更适合于单线程环境,而Hashtable 适合于多线程环境。
    3)HashMap 提供了可供应用迭代的键的集合,因此,HashMap 是快速失败的。另一方面,Hashtable 提供了对键的列举(Enumeration)。

    一般认为 Hashtable 是一个遗留的类。

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

HashMap:适用于在Map中插入、删除和定位元素。

Treemap:适用于按自然顺序或自定义顺序遍历键(key)

HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap。

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

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

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

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

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

     (HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。)

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

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

ArrayList 底层的数据结构是数组,查询快,增删慢        线程不安全,效率高

LinkedList 底层的数据结构是链表,查询慢,增删快        线程不安全,效率高

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

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

* 数组转换成为List:调用Arrays工具类的asList方法。

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

1)线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。

2)扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。

3)效率:ArrayList 的效率高于 Vector。

28. Array 和 ArrayList 有何区别?

1)Array 可以包含基本数据类型和对象类型,而 ArrayList 只能包含对象类型。

2)Array 有固定的大小,而 ArrayList 是动态变化的。

3)ArrayList 中包含了更多的方法特性,如 addAll()、iterator()、romoveAll()等

对于基本类型,集合使用自动装箱能减少编码工作量。但是对于固定大小的数据类型,这种方法会比较慢。

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

poll() 和 remove() 都是从队列中删除队列的头,但是当队列为 null 时,poll() 会返回 null,而 remove() 会抛出异常。

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

* vector:底层结构为数组,线程安全,效率较低,因此不建议使用。
* statck:堆栈类,先进后出。
* hashTable:与hashMap相似,不同的是它是线程安全的。
* enumeration:枚举,相当于迭代器。

31. 迭代器 Iterator 是什么?

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为"轻量级"对象,因为创建它的代价小。

32. Iterator 怎么使用?有什么特点?

Java中的Iterator功能比较简单,并且只能单向移动:

(1)使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

Iterator接口中的方法
Collection继承后的方法

(2)使用next()获得序列中的下一个元素。

(3)使用hasNext()检查序列中是否还有元素。

(4)使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

33. Iterator 和 ListIterator 有什么区别?

* Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。 
* Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。 
* ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

ListIterator 的全部方法

34. 并行和并发有什么区别?

* 并发:指两个或多个事件在同一时间间隔发生。(同一个实体上)例如:在一台处理器上"同时"处理多个任务。

* 并行:指两个或者多个事件在同一时刻发生。(不同实体上)例如:在多台处理器上同时处理多个任务。

因此,并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

35. switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上

在JDK5以前,switch(x)中,x 只能是byte、short、char以及int。从JDK5以后,引入枚举类型,x也可以是enum类型。从JDK7以后,x 还可以是 String 类型,但是 long 类型在目前所有的版本中都是不可以的。

36. 用最有效率的方法计算 2 乘以 8

2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)

37. float  f = 3.5; 是否正确?

不正确,3.5 默认为 double 类型(双精度数)。将 double 类型(双精度数)赋值给 float 类型(单精度数)属于向下转型会造成精度损失。因改成float f =(float)3.5; 或者写成 float f =3.5F。

38. short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?

对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。

而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。

39. Java 中的访问修饰符

定义:Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

分类:
1)private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
2)default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
3)protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
4)public : 对所有类可见。使用对象:类、接口、变量、方法

访问修饰符图

40. &和&&的区别

&运算符有两种用法:(1)按位与;(2)逻辑与。

&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。

41. this与super的区别

* super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)

* this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)

* super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。

* super() 和this() 均需放在构造方法内第一行。

* 尽管可以用this调用一个构造器,但却不能调用两个。

* this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

* this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static 变量,static方法,static语句块。

从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。

42. static 的应用场景和注意事项

常见的static应用场景

注意事项:1、静态只能访问静态。 2、非静态既可以访问非静态的,也可以访问静态的。

43. break ,continue ,return 的区别及作用

* break 跳出总上一层循环,不再执行循环(结束当前的循环体)

* continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)

* return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)

推荐阅读更多精彩内容