面试话痨系列是从技术广度的角度去回答面试官提的问题,适合萌新观看!

   面试官,别再问我火箭怎么造了,我知道螺丝的四种拧法,你想听吗?


  String相关的题目,是面试中经常考察的点,当面试中遇到了String相关的问题,我们可以这么聊:

一:String底层结构

  从底层结构上来说,jdk1.8的String,底层是char[]。我在工作中几乎很少用到char[],因为List太好用了,我宁愿用List<Character>也不想用char[],因为以前学C时体会过用char[]的痛苦,长度必须事先设定好,也没有丰富的API去处理数据。所以刚开始用java时,觉得String这个类简直太好用了(直视面试官的眼睛,露出有点不好意思的笑)。后来才知道,原来是源码在替我们负重前行。

  比如我们都知道String的拼接,大部分情况下都是新建一个空间(这里可以用稍微缓慢不确定的语气说这句话,稍有心的面试官就会问你什么情况下不会新建空间,你就可以回答:1.连续相加时jdk会自动优化成一次空间的新建,2.两个字符串常量相加的值如果是已经存在的字符串常量,那么会直接指向这个已存在的字符常量),新建的原因就是因为底层是一个char[],无法直接扩容。而新建空间的花费很多,所以对于有多次拼接需求的情况,我会酌情选择StringBuffer和StringBuilder,主要是看是否存在多线程的情况,存在的话就用StringBuffer(线程安全的方式,涉及的知识点很多,可以专门写一章,先留个传送门:面试话痨(三)我会锁的四种配法,您配吗?)。

  另外,我有次看jdk11里面String的底层已经变成了byte[],顺手查了一下,说是用byte[]存的话,可以减少大概一半的内存占用,再具体的怎么实现怎么优化的没太仔细了解。(对于自己不太懂的知识,介绍完自己懂得部分以后,一定要接一句:再往下自己就不清楚了之类的话。这样面试官就不会再接着问你这个问题)。

  题外话:字符之间可以直接使用‘+’和‘-’运算符,实际计算的是字符对应的ASCII码的位置的加减,如 ‘1’ - ‘0’ = (int)1,用这个方法可以快速的完成char到int的强转,很多String类的题目都需要用到这个方法。

二:final修饰符

  因为char[]本身就是一个不能扩容的数组,所以用不可变的常量去修饰字符串就很适合。另外,final的特性也能为String带来很多的好处:

  1. 安全方面来说,密码、个人信息等基本都是以String为载体来进行存储的,final修饰的String类不可以被继承,创建的对象也不可以被改变,可以保证关键数据的安全性。

  2. 性能方面来说,final修饰后,String就被放入了常量池,常量池中有专门的字符串常量池,JVM可以将多个一样的String指向同一个地址,其中有任意一个String改变时,因为final的特性都会去重新建一个地址(或者指向另外一个值恰好相同的地址),不会影响原来的值;另外,String的不可变性让它的hashcode是固定的,可以被缓存的,用来做Map的key运算更快捷;还有,final修饰后,也不会存在多线程安全的问题。

  (本来想接着说一下常量的,但是一想到常量,脑子里就蹦出了方法区,堆,栈,JDK版本更替、GC方式,类加载,JVM内存模型,Java内存模型,可见性,volatile,自旋锁,太多了。先留个坑吧。面试话痨(四)常量在哪里呀,常量在哪里)。

  与final长得像的,还有finally和finalize。finally就是跟在try或者catch后面的一个关键字,以前我们学的是,try之后必定会执行finally,但其实这个是有前提的,就是程序不崩溃或者不被强制结束,try中加一句 System.exit(0); ,finally就不会被执行。

  至于finalize,这个方法几乎没人用了,它是Object类中就自带的方法,学名析构函数,听说是在java刚出生时,为了迎合C编程人员的习惯添加的方法。在对象快要被回收时调用且只会被调用一次。如果finalize中的代码将另外一个指针指向了该对象,那么JVM就会放弃该对象的回收。等到下一次该对象又不可达了,JVM就会直接回收,不会再调用finalize方法。因此方法存在不确定性,很少被使用。

三:equals

  在Obejct中,equals和==是一样的,都是直接比较数据的存放地址是否一致,而在String中,equals方法被重写成三个步骤的判断。

  

  HashMap中的equals大致也是使用了这三个步骤的判断:地址是否相等 --> size是否相等 --> 每一个key是否有equals的key,对应的value是否equals。

  不同的类对于equals的实现方式不一样,但他们都遵循若hashcode不相等,则equals也不相等的原则。这样做的目的主要是为了让Hash类集合插入值时的重复判定更合理:

   

  试想一下,假设两个身份证对象的hashcode不相等,equals却相等,那么两个相同身份证信息就会被放入HashSet中了!这会对我们的编码造成很大的困扰,所以对于需要被用于Hash的key值的对象(HashSet的值插入相当于是将值放入了key中,再插入了一个固定value值的HashMap),我们需要满足若hashcode不相等,则equals也不相等的原则。

  HashSet中的元素重复判定,优先判定hashcode的原因是:hashcode通过与HashSet的大小取余以后,可以快速的定位到可能相等的元素的位置,这时再对该位置上存在的元素的进行equals就行,只要hash分布的足够均匀,该操作的时间复杂度就接近于O(1),而若去掉hashcode寻址,直接使用equals对n个数进行对比的话,时间复杂度就是O(n)。

  说到这里还可以提一个经常被问到的问题,HashMap的查询时间复杂度是多少?

  如我上面的分析一样,时间复杂度是接近于O(1)的,当然也会有O(n)的情况。比如新建了一个类,hashcode值全部返回1,这样所有的值都会接到一个链表上,数组+链表的结构就退化成纯链表,时间复杂度就变成了O(n)。jdk1.8以后,链表长度超过8,并且数组长度大于64时,链表会变成红黑树,红黑树的遍历时间复杂度为O(log(n))。(红黑树、B树、索引、数据库、图、广度搜索、深度搜索相关的数据结构及算法后面再说。面试话痨(N)还没有头绪不知道什么时间写)。


  最后,送大家一道我特别喜欢的面试题。

    请将一段字符串转换成整数,不要使用parseInt。

    public int MyParseInt(String str) throws Exception{
/*
1.数据校验
(不管面试过程中遇到什么题,都可以先优雅的写下
//1.数据校验
然后胸有成竹的写一些有的没的校验,写的过程中再想后面应该怎么写。
写注释+周全的校验是写代码的基本素养)
*/
String errMsg = check(str);
if (errMsg != null) {
throw new Exception(errMsg);
}
char[] c = str.toCharArray();
int result = 0;
for (int i = 0; i < c.length; i++) {
result = result * 10 + (c[i] - '0');
}
return result;
} /**
*
* @param str 待校验的数据
* @return 错误信息,没有错误时返回null
*/
private String check(String str) {
if (str == null) {
return "输入不能为空!";
}
/*
很少有人能一遍写出不用调试没有bug的代码,更别说在面试那么紧张的气氛中了
所以,在写完能够基本实现题目要求的代码以后,最好能想下代码中不足的地方,然后坦诚的告诉面试官:
这个代码还有需要改进的地方,比如可以添加对 负号、正号、小数点的支持,比如没有校验int的阀值,
如果是工作中遇到,我肯定能解决这些问题。
*/
if (str.replaceAll("[0-9]","").length() > 0){
return "包含非法字符";
}
return null;
}

  本章中提到的一些面试回答技巧这里再写一下,我个人觉得挺有用的:

  1、 对于自己擅长的问题,可以在问题中留下一些点,吸引面试官继续提问。

  2、 对于自己不擅长的问题,回答完自己会的部分以后,可以直接说再往下自己就不懂了,不要不懂装懂,让面试官继续问下去后再回答不知道。

  3、 如果面试官已经问了你不知道的问题,尽量从性能和安全方面,说出一个答案。直接先坦诚的告诉面试官你不知道,只是根据个人经验这个应该是这样的,因为这样对于安全/性能的优点是xxx。


  原创不易,转载请注明出处

  本系列链接如下:

  面试话痨(一)让我们来热切的讨论这个养猪场吧

  面试话痨(二)C:JAVA String,别以为你穿个马甲我就不认识你了

   面试话痨(三)我会锁的四种配法,您配吗?

  

  

  

  

  

  

面试话痨(二)C:JAVA String,别以为你穿个马甲我就不认识你了的更多相关文章

  1. Java 面试知识点解析(二)——高并发编程篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  2. Java面试集合(二)

    前言 大家好,给大家带来Java面试集合(二)的概述,希望你们喜欢 二 1.请问线程有哪些状态? 新建状态(New) 就绪状态(Runnable) 运行状态(Running) 阻塞状态(Blocked ...

  3. 源码浅谈(二):java中的 Integer.parseInt(String str)方法

    这个方法是将字符串转换为整型 一.parseInt方法 ,可以看到默认又调用了parseInt(s,10) ,  第二个参数为基数,默认10 ,当然也可以自己设置  public static int ...

  4. 面试之Java String 编码相关

    实话说,作为一个多年Java老年程序员,直到近来,在没有决心花时间搞清楚Java String的编码相关问题之前, 自己也都还是似懂非懂,一脸懵逼的.设想如果在面试中,有同学能够条理清晰的回答下面的问 ...

  5. 面试问题记录 二 (数据库、Linux、Redis)

    面试问题记录 二 (数据库.Linux.Redis) 前言 接着上次的面试问题记录,在最后还有几道问的数据结构方面的知识点要补充 还是那句话:如果文中解释有明显错误,劳烦请及时指正我,在这不胜感激!! ...

  6. Java总结篇系列:Java String

    String作为Java中最常用的引用类型,相对来说基本上都比较熟悉,无论在平时的编码过程中还是在笔试面试中,String都很受到青睐,然而,在使用String过程中,又有较多需要注意的细节之处. 1 ...

  7. (转)面试大总结之一:Java搞定面试中的链表题目

    面试大总结之一:Java搞定面试中的链表题目 分类: Algorithm Interview2013-11-16 05:53 11628人阅读 评论(40) 收藏 举报 链表是面试中常出现的一类题目, ...

  8. 通过反编译深入理解Java String及intern(转)

    通过反编译深入理解Java String及intern 原文传送门:http://www.cnblogs.com/paddix/p/5326863.html 一.字符串问题 字符串在我们平时的编码工作 ...

  9. 我对java String的理解 及 源码浅析

    摘要: 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 每天起床告诉自己,自己的目标是 ”技术 + 英语 还有生活“! ...

随机推荐

  1. OS Summary 1

    内容概述 什么是操作系统 操作系统的演变 操作系统结果的分类 什么是操作系统 操作系统可以是: 一个控制程序 一个资源管理器 一套标准库 操作系统通常有内核.命令行和 GUI 组成.我们研究的主要是内 ...

  2. 前端页面设计常见的30个CSS选择器

    1. *   -->   通配符选择器 * { margin: 0; padding: 0; } 星号符会选择页面每个元素.很多开发者用它把所有margin和padding归零.这当然是快捷测试 ...

  3. 4-CSS规范

    4.1 命名规范:4.1.1 css文件命名 reset.css 重置样式,重置元素默认样式,使得页面在所有浏览器中有统一的外观 global.css 全局样式,全站公用,定义页面基础样式(常见的公共 ...

  4. –IDEA+Maven+JavaWeb+tomcat项目搭建(图文并茂,详细)

    一.创建Maven项目 1:如果刚打开IDEA,显示的是这个页面,我们直接单击 Create New Project(创建项目) 或者 File-> New-> Project 2:选中左 ...

  5. 从谷歌到脸书:为何巨头纷纷“钟情于”VR相机?

    VR的火爆,自然无需多言.而基于VR这一个概念,已经在多个相关行业不断衍生出新的产品.服务或内容.VR眼镜.VR头盔.VR相机.VR游戏.VR影视.VR应用--但VR产业的发展并不是齐头并进,而是出现 ...

  6. ECMA5中定义的对象属性特性和方法

    ECMA5规定了只有内部才有的特性,描述了属性的各种特征,这些特性用于实现JavaScript引擎,因此在Js中不能直接访问他们.为了标识特性,我们一般会他们放入两对方括号中. ECMAScript中 ...

  7. 达拉草201771010105《面向对象程序设计(java)》第十周学习总结

    达拉草201771010105<面向对象程序设计(java)>第十周学习总结 实验十  泛型程序设计技术 实验时间 2018-11-1 第一部分:理论知识        泛型:也称参数化类 ...

  8. Linux命令学习神器!命令看不懂直接给你解释!

    大家都知道,Linux 系统有非常多的命令,而且每个命令又有非常多的用法,想要全部记住所有命令的所有用法,恐怕是一件不可能完成的任务. 一般情况下,我们学习一个命令时,要么直接百度去搜索它的用法,要么 ...

  9. 移动端轮播图实现方法(dGun.js)

    本文章介绍在移动端无缝隙轮播图实现的原理,这个轮子比较简单,但可以方便刚刚入门的同学参考.最终效果是在移动端无缝隙无限滑动,可以自定义轮播的速度.支持手势左右滑动.最后会放上源码. HTML部分 &l ...

  10. <select>标签,不要在select标签中写value属性!!!

    <select> select标签,一个选择框标签,在开发中很多时候会用到这个标签,例如选择生日19**年,或者在segmentfault中编辑文章时选择'原创','转载',还是'翻译'等 ...