Java 面试常见问题-Java基础

1 JavaSE部分

1.1 java中对正则表达式的支持

正则表达式用来描述字符串规则,可用于字符串的匹配和处理。

  • String类中提供支持正则表达式操作的方法,包括matches()、replaceAll()、replaceFirst()、split()。
  • Pattern类表示正则表达式对象

1.2 java vs javascript

  • 面对对象和基于对象: java面对对象,对象由开发者设计;javascript基于对象,提供丰富的内部对象。
  • 编译和解释:Java运行前要编译;javascript是解释型,由浏览器解释执行。
  • 强类型变量和弱类型变量:java是强类型变量,所有变量在编译前必须声明;javascript可以不声明变量类型,由解释器推断

1.3 Java如何跳出多重循环

推荐方法:break跳出当前循环 通过内部跳出条件控制跳出外部循环

1.4 &与&&的区别

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

1.5 包装类

从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为null,而原始类型实例变量的缺省值与它们的类型有关。

1.6 String StringBuilder StringBuffer

Java 面试常见问题-Java基础
(1)如果要操作少量的数据用 String;

(2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;

(3)单线程操作字符串缓冲区下操作大量数据 StringBuilder。

1.7 Array和ArrayList

  • Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
  • Array大小是固定的,ArrayList的大小是动态变化的。
  • ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
  • 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。

1.8 值传递和引用传递

值传递的时候,将实参的值,copy一份给形参,对形参的修改不会影响实参。
引用传递的时候,将实参的地址值,copy一份给形参,形参和实参指向同一个内存地址(同一个对象),所以对参数的修改会影响到实际的对象。
java中是值传递
Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。

1.9 十进制的数在内存中是怎么存的

2进制的小数无法精确的表达10进制小数
计算机以补码的方式存十进制数
Java 面试常见问题-Java基础

1.10 java 8新特性

  • Lambda 表达式 :Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。

  • 方法引用:方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

  • 默认方法:默认方法就是一个在接口里面有了一个实现的方法

  • Stream API :新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

  • Date Time API : 加强对日期与时间的处理。

  • Optional 类 :Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

1.11 “ ==”比较的是什么?equal 和hashcode的区别

== 对比两个对象基于内存引用,如果两个对象的引用完全相同(指向同一个对象)时,== 操作将返回true,否则返回false。“==”如果两边是基本类型,就是比较数值是否相等。

想要弄明白hashCode的作用,必须要先知道Java中的集合。  
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。这里就引出一个问题:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?
这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。
于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上,初学者可以简单理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。
这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
简而言之,在集合查找时,hashcode能大大降低对象比较次数,提高查找效率!
Java对象的eqauls方法和hashCode方法是这样规定的:

1、相等(相同)的对象必须具有相等的哈希码(或者散列码)。
2、如果两个对象的hashCode相同,它们并不一定相同。

此处参考最详细的equal和hashcode详解

HashMap中,如果要比较key是否相等,要同时使用这两个函数!因为自定义的类的hashcode()方法继承于Object类,其hashcode码为默认的内存地址,这样即便有相同含义的两个对象,比较也是不相等的。HashMap中的比较key是这样的,先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等的。若equals()不相等则认为他们不相等。如果只重写hashcode()不重写equals()方法,当比较equals()时只是看他们是否为同一对象(即进行内存地址的比较),所以必定要两个方法一起重写。HashMap用来判断key是否相等的方法,其实是调用了HashSet判断加入元素 是否相等。重载hashCode()是为了对同一个key,能得到相同的Hash Code,这样HashMap就可以定位到我们指定的key上。重载equals()是为了向HashMap表明当前对象和key上所保存的对象是相等的,这样我们才真正地获得了这个key所对应的这个键值对。

参考:参考