最经典的Java面试题,带你拿offer拿到手软,还不快来?(二)

简介: 从今天开始我会持续更新面试题,其中涵盖了:Java基础、多线程、IO、高并发、集合框架、数据库、框架以及分布式技术。持续更新中·······

10. 说说Hashcode的作用


  • java的集合有两类,一类是List,还有一类是Set。前者有序可重复,后者无序不重复。当我们在set中插入的时候怎么判断是否已经存在该元素呢,可以通过equals方法。但是如果元素太多,用这样的方法就会比较满。
  • 于是有人发明了哈希算法来提高集合中查找元素的效率。 这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储的那个区域。
  • hashCode方法可以这样理解:它返回的就是根据对象的内存地址换算出的一个值。这样一来,当集合要加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。


11. String、StringBuffer、StringBuilder的区别


  • String是只读字符串,它并不是基本数据类型,而是一个对象。从底层源码来看是一个fifinal类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改。每次对String的操作都会生成新的String象。

String的底层声明:

private final char value[];
复制代码

每次+操作 : 隐式在堆上new了一个跟原字符串相同的StringBuilder对象,再调用append方法拼接+后面的字符。

StringBuffffer和StringBuilder他们两都继承了AbstractStringBuilder抽象类,从AbstractStringBuilder抽象类中我们可以看到以下的源代码:

/**
* The value is used for character storage.
*/
char[] value;
复制代码
  • 他们的底层都是可变的字符数组,所以在进行频繁的字符串操作时,建议使用StringBufffferStringBuilder来进行操作。 另外StringBuffffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。


12. 熟悉Java对象的引用嘛


  • 强引用:强引用是我们平时使用最多的引用,强引用在程序内存不足的时候(OOM)的时候也不被回收,使用方式如下代码:
String str = new String("str");
System.out.println(str);
复制代码
  • 使用场景:使用new关键字创建一个新的对象的时候。
  • 软引用 :软引用是程序内存不足时,会被回收,使用方式如下代码:
// 注意:wrf这个引用也是强引用,它是指向SoftReference这个对象的,
// 这里的软引用指的是指向new String("str")的引用,也就是SoftReference类中T
SoftReference<String> wrf = new SoftReference<String>(new String("str"));
复制代码
  • 使用场景 : 创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM就会回收早先创建的对象。
  • 弱引用 : 弱引用就是只要JVM垃圾回收器发现了它,就会将之回收,使用方式如下代码:
WeakReference<String> wrf = new WeakReference<String>(str);
复制代码
  • 使用场景 : Java源码中的 java.util.WeakHashMap 中的 key 就是使用弱引用,我的理解就是,一旦我不需要某个引用,JVM会自动帮我处理它,这样我就不需要做其它操作。
  • 虚引用 :虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入 ReferenceQueue 中。注意哦,其它引用是被JVM回收后才被传入 ReferenceQueue 中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。还有就是,虚引用创建的时候,必须带有 ReferenceQueue ,使用方式如下代码:
PhantomReference<String> prf = new PhantomReference<String>(new String("str"),
new ReferenceQueue<>());
复制代码
  • 使用场景:对象销毁前的一些操作,比如说资源释放等。 Object.finalize() 虽然也可以做这类动作,但是这个方式即不安全又低效。

上诉所说的几类引用,都是指对象本身的引用,而不是指Reference的四个子类的引用(SoftReference等)。


12. 泛型常用特点


泛型是Java SE 1.5之后的特性, 《Java 核心技术》中对泛型的定义是: “泛型” 意味着编写的代码可以被不同类型的对象所重用。

泛型”,顾名思义,“泛指的类型”。我们提供了泛指的概念,但具体执行的时候却可以有具体的规则来约束,比如我们用的非常多的ArrayList就是个泛型类,ArrayList作为集合可以存放各种元素,如Integer, String,自定义的各种类型等,但在我们使用的时候通过具体的规则来约束,如我们可以约束集合中只存放Integer类型的元素。

List<Integer> list = new ArrayList<>();
复制代码


13. 使用泛型的好处


以集合来举例,使用泛型的好处是我们不必因为添加元素类型的不同而定义不同类型的集合,如整型集合类,浮点型集合类,字符串集合类,我们可以定义一个集合来存放整型、浮点型,字符串型数据,而这并不是最重要的,因为我们只要把底层存储设置了Object即可,添加的数据全部都可向上转型为Object。 更重要的是我们可以通过规则按照自己的想法控制存储的数据类型。


14. 创建对象的几种方式


  • new创建一个新对象
  • 通过反射机制创建
  • 采用clone技术=
  • 通过序列化创建


15. 有没有两个不相等的对象有想通过的hashcode值


有可能.在产生hash冲突时,两个不相等的对象就会有相同的 hashcode 值


16. 深拷贝与浅拷贝的区别


  • 浅拷贝 : 被复制的对象的所有变量都含有原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.
  • 深拷贝 : 被复制对象的所有变量都含有与原来的对象相同的值.而那些引用其他对象的变量将指向被复制过的新对象.而不再是原有的那些被引用的对象.换言之.深拷贝把要复制的对象所引用的对象都复制了一遍.


17. final关键字的作用


  • 被fifinal修饰的类不可以被继承。
  • 被fifinal修饰的方法不可以被重写。
  • 被fifinal修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变.。
  • 被fifinal修饰的方法,JVM会尝试将其内联,以提高运行效率。
  • 被fifinal修饰的常量,在编译阶段会存入常量池中。

除此之外,编译器对final域要遵守两个重排序规则更好:

在构造函数内对一个fifinal域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序 初次读一个包含fifinal域的对象的引用,与随后初次读这个fifinal域,这两个操作之间不能重排序。


18. static关键字的作用


  • 所有的人都知道static关键字这两个基本的用法:静态变量和静态方法.也就是被static所修饰的变量方法都属于类的静态资源,类实例所共享。
  • 除了静态变量和静态方法之外,static也用于静态块,多用于初始化操作:
public class PreCache{
  static{
    // 逻辑代码
  }
}
复制代码

注意:static代码块中的代码只在类加载的时候只执行一次并且只会执行一次。

  • 此外static也多用于修饰内部类,此时称之为静态内部类。
  • 最后一种用法就是静态导包,即 import static .import static是在JDK 1.5之后引入的新特性,可以用来指定导入某个类中的静态资源,并且不需要使用类名,可以直接使用资源名,比如:
import static java.lang.Math.*;
public class Test{
 public static void main(String[] args){
 //System.out.println(Math.sin(20));传统做法
 System.out.println(sin(20));
 }
}
复制代码


19. 3*0.1 == 0.3 返回值是什么


false,因为有些浮点数是不能被精确表示出来的,取得是一些近似值。


20. a=a+b与a+=b的区别


+=操作符会进行隐式自动类型的转换,此处a+=b隐式的将加操作的结果进行强制类型转换为持有结果的类型,而a=a+b则不会自动进行类型转换,如下代码:

byte a = 127;
byte b = 127;
b = a + b; // 编译报错
b+=a;  // 输出结果:254
复制代码

以下代码是否有错,有的话怎么改?

short s1 = 1;
s1 = s1 + 1;
复制代码

有错误.short类型在进行运算时会自动提升为int类型,也就是说 s1+1 的运算结果是int类型,而s1是short类型,此时编译器会报错。

正确写法:

short s1 = 1;
s1 += 1;
复制代码

+=操作符会对右边的表达式结果强转匹配左边的数据类型,所以没错。



相关文章
|
4天前
|
Java 数据库连接 数据库
spring--为web(1),富士康java面试题整理
spring--为web(1),富士康java面试题整理
|
1天前
|
数据采集 Java 数据挖掘
最新Python+OpenCV+dlib汽车驾驶员疲劳驾驶检测!,2024年最新网易云java面试
最新Python+OpenCV+dlib汽车驾驶员疲劳驾驶检测!,2024年最新网易云java面试
最新Python+OpenCV+dlib汽车驾驶员疲劳驾驶检测!,2024年最新网易云java面试
|
1天前
|
机器学习/深度学习 数据采集 Java
2024年9(2),2024年最新大厂面试题java
2024年9(2),2024年最新大厂面试题java
2024年9(2),2024年最新大厂面试题java
|
4天前
|
移动开发 前端开发 JavaScript
Java和web前端,IT新人该如何选择?,2024年最新Web前端内存优化面试
Java和web前端,IT新人该如何选择?,2024年最新Web前端内存优化面试
|
4天前
|
安全 Java 数据库
Spring boot 入门教程-Oauth2,java面试基础题核心
Spring boot 入门教程-Oauth2,java面试基础题核心
|
4天前
|
Java
Java中int[]与Integer[]相互转化的方法,java基础知识面试重点总结
Java中int[]与Integer[]相互转化的方法,java基础知识面试重点总结
|
5天前
|
算法 Java C++
刷题两个月,从入门到字节跳动offer丨GitHub标星16k+,美团Java面试题
刷题两个月,从入门到字节跳动offer丨GitHub标星16k+,美团Java面试题
|
5天前
|
设计模式 算法 Java
Java的前景如何,好不好自学?,万字Java技术类校招面试题汇总
Java的前景如何,好不好自学?,万字Java技术类校招面试题汇总
|
5天前
|
存储 网络协议 前端开发
es集群安装,邮储银行java面试
es集群安装,邮储银行java面试