最经典的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;
复制代码

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



相关文章
|
5天前
|
负载均衡 NoSQL 算法
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
这篇文章是关于Java面试中Redis相关问题的笔记,包括Redis事务实现、集群方案、主从复制原理、CAP和BASE理论以及负载均衡算法和类型。
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
|
5天前
|
存储 NoSQL Java
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
这篇文章是关于Java面试中的分布式架构问题的笔记,包括分布式架构下的Session共享方案、RPC和RMI的理解、分布式ID生成方案、分布式锁解决方案以及分布式事务解决方案。
一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
|
5天前
|
SQL Java 数据库连接
一天五道Java面试题----第六天(1)
这篇文章是关于Java面试中常见的五个问题,包括MyBatis和Hibernate的对比、MyBatis中#{}和${}的区别、MyBatis插件的运行原理及开发流程、索引的基本原理以及MySQL聚簇索引和非聚簇索引的区别。
|
5天前
|
缓存 NoSQL Redis
一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)
这篇文章是关于Java面试中可能会遇到的五个问题,包括MySQL索引类型及其对数据库性能的影响、Redis的RDB和AOF持久化机制、Redis的过期键删除策略、Redis的单线程模型为何高效,以及缓存雪崩、缓存穿透和缓存击穿的概念及其解决方案。
|
5天前
|
前端开发 Java 数据库连接
一天十道Java面试题----第五天(spring的事务传播机制------>mybatis的优缺点)
这篇文章总结了Java面试中的十个问题,包括Spring事务传播机制、Spring事务失效条件、Bean自动装配方式、Spring、Spring MVC和Spring Boot的区别、Spring MVC的工作流程和主要组件、Spring Boot的自动配置原理和Starter概念、嵌入式服务器的使用原因,以及MyBatis的优缺点。
|
5天前
|
存储 关系型数据库 MySQL
一天五道Java面试题----第八天(怎么处理慢查询--------->简述Myisam和innodb的区别)
这篇文章是关于Java面试中关于数据库性能优化和MySQL特性的五个问题,包括处理慢查询、ACID特性保证、MVCC概念、MySQL主从同步原理以及MyISAM和InnoDB存储引擎的区别。
|
5天前
|
算法 关系型数据库 MySQL
一天五道Java面试题----第七天(mysql索引结构,各自的优劣--------->事务的基本特性和隔离级别)
这篇文章是关于MySQL的面试题总结,包括索引结构的优劣、索引设计原则、MySQL锁的类型、执行计划的解读以及事务的基本特性和隔离级别。
|
4天前
|
NoSQL Java 数据库
2022年整理最详细的java面试题、掌握这一套八股文、面试基础不成问题[吐血整理、纯手撸]
这篇文章是一份详尽的Java面试题总结,涵盖了从面向对象基础到分布式系统设计的多个知识点,适合用来准备Java技术面试。
|
5天前
|
算法 关系型数据库 MySQL
一天五道Java面试题----第七天(mysql索引结构,各自的优劣--------->事务的基本特性和隔离级别)
这篇文章是关于MySQL的面试题总结,包括索引结构的优劣、索引设计原则、MySQL锁的类型、执行计划的解读以及事务的基本特性和隔离级别。
|
5天前
|
自然语言处理 NoSQL Java
一天一道Java面试题----第十二天(如何实现接口幂等性)
这篇文章探讨了实现Java接口幂等性的几种方法,包括使用唯一ID、服务端token、去重表、版本控制以及控制状态等策略。