热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于JavaString,StringBuilder,StringBuffer,Hashtable,HashMap的面试题

题目是一道简单的小程序,像下面这样:publicclassTest1{publicstaticvoidmain(Stringargs[]){StringsnewStri

题目是一道简单的小程序,像下面这样:

public class Test1 {
public static void main(String args[]) {
String s = new String("Hello");
System.out.println(s);

foo(s);
System.out.println(s);
}

public static void foo(String s) {
s = new String("World");
}
}

问程序先后两次分别会输出什么。
第一个肯定输出“Hello”。关键是第二个,个别基础不牢的朋友可能被考倒,但基础稍微扎实一点的就不会。第二个输出的也是“Hello”。
到这里,万事大吉。面试官两眼放出喜悦的光芒,赞叹道:“嗯,不错不错。不会变的,对吧。因为String是immutable类型,immutable类型改不了的。”他说的“immutable”是指String类没有任何一个方法会改变对象的状态。

 

这可就有问题了。确实程序两次输出的都是“Hello”,但原因却不是String的immutable特性。不信换一个“mutable”的试试,比如StringBuilder或StringBuffer。


public class Test2 {
public static void main(String args[]) {
StringBuilder s = new StringBuilder("Hello");
System.out.println(s);

foo(s);
System.out.println(s);
}

public static void foo(StringBuilder s) {
s = new StringBuilder("World");
}
}

这次呢?会先输出“Hello”,然后输出“World”吗?不会,仍然是两次“Hello”。
足以说明这个问题跟String的immutable特性没有一毛钱的关系。不管是immutable类型,还是一般的类型,用这种方式写出来的程序main方法中前后两个对象肯定是一样的。

 

真正的原因是:Java语言的参数传递机制是“按值传递”(pass by value)。虽然Java中除基本数值类型外,其它变量都是引用,但那是另一回事。变量的语义(“引用”还是“值”)跟函数传参的机制是两个正交的概念。
各种编程语言中,最常见的参数传递方式不外乎按值传递和按引用传递(pass by reference)两种。比如,C和Java中函数参数都是按值传递的,C++和C#则同时支持按值传递和按引用传递。C和Java的不同在于,C是值类型的按值传递,而Java是引用类型的按值传递(基本的数值类型除外)。
按值传参最大的特点就是函数内部对“形参变量”本身的所做的修改外面的“实参变量”感知不到。

 

不过,对于StringBuilder来说我们至少有办法让它改变,比如像下面这样:


public class Test3 {
public static void main(String args[]) {
StringBuilder s = new StringBuilder("Hello");
System.out.println(s);

foo(s);
System.out.println(s);
}

public static void foo(StringBuilder s) {
s.replace(0, s.length(), "World");
}
}


体会到不同了吗?虽然参数变量本身是按值传递的,但这次我们对变量本身不感兴趣,我们不改变变量本身,而是通过它直接修改它所引用的那个对象。这一次,Java语言“几乎一切皆引用”的特点起作用了,程序第一次输出“Hello”,第二次输出“World”。熟悉C的朋友可能马上联想到:这很像C语言中通过指针来修改它指向的内容。
而先前那个String版本的程序,我们无法写出一个相应的可变版本。为什么呢?……“嗯,不错不错。因为String是immutable类型……”,这次真对了。——可见先前说“没有一毛钱的关系”也不尽然。因为immutable,导致我们无法针对String写出一个像Test3那样的“可变”程序,如此说来,“二分钱的关系”应该是有的。

 

“pass reference by value”就像C++ 11中的“An lvalue with rvalue reference type”一样,乍一看挺绕的,但只要仔细想清楚,让正交的东西“尘归尘 土归土”,就可以加深对语言的理解。

顺便问一句,您知道java.lang.StringBuilder和java.lang.StringBuffer的区别吗?好多面试官都喜欢“顺便”问问这个,而且答对了不会加分,答不上来却会扣分,至少扣印象分。:(


java.lang.StringBuilder和java.lang.StringBuffer的区别:

StringBuffer is synchronized, StringBuilder is not.

StringBuilder is faster than StringBuffer because it's not synchronized.


看来以前喜欢用StringBuffer不是个好习惯,以后要多用StringBuilder !!!




这也让我想到了另一个经典的问题:Hashtable和HashMap的区别是什么?

  1. Hashtable is synchronized, whereas HashMap is not. This makes HashMap better for non-threaded applications, as unsynchronized Objects typically perform better than synchronized ones.
  2. Hashtable does not allow null keys or values. HashMap allows one null key and any number ofnull values.
  3. One of HashMap's subclasses is LinkedHashMap, so in the event that you'd want predictable iteration order (which is insertion order by default), you could easily swap out the HashMap for aLinkedHashMap. This wouldn't be as easy if you were using Hashtable.

Since synchronization is not an issue for you, I'd recommend HashMap. If synchronization becomes an issue, you may also look at ConcurrentHashMap.


总之都是unsynchronized要快一些,但鉴于Hashtable这个概念在面试中比HashMap来的多得多,所以在做面试题时还是用Hashtable吧,在项目开发中我从来都是用HashMap.


Ref:

http://blog.csdn.net/steedhorse/article/details/6892569

http://stackoverflow.com/questions/355089/stringbuilder-and-stringbuffer-in-java

http://vanillajava.blogspot.de/2013/04/why-synchronized-stringbuffer-was-never.html

http://stackoverflow.com/questions/40471/differences-between-hashmap-and-hashtable





推荐阅读
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • java程序设计试题_《Java语言程序设计》期末考试模拟试题——填空题和编程题...
    一、根据题意,填写出空格中的内容Java平台包括三个技术方向,其中J2ME代表____________、J2SE代表___________、J2EE代表 ... [详细]
  • 图片添加二维码水印教程
    本博客介绍一下用jdkawt实现图片加文字水印和图片水印的方法一、图片文字水印原来图片加上文字水印后图片二、图片加图片水印原来图片:水印图片:添加水印后的图片: ... [详细]
  • 一、HashMap1.HashMap概述:HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是 ... [详细]
  • (2.1.8)Java之集合类:set、list、hashmap、hashtable等和迭代器iterator
    一、容器常见的集合类有这些种:实现Collection接口的:Set、List以及他们的实现类。实现Map接口的:HashMap及其实现类编程爱好者学习,下面我我们通过一个图来整体描述一下:这个图片没 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 本文介绍了在PostgreSQL中批量导入数据时的优化方法。包括使用unlogged表、删除重建索引、删除重建外键、禁用触发器、使用COPY方法、批量插入等。同时还提到了一些参数优化的注意事项,如设置effective_cache_size、shared_buffer等,并强调了在导入大量数据后使用analyze命令重新收集统计信息的重要性。 ... [详细]
  • 流数据流和IO流的使用及应用
    本文介绍了流数据流和IO流的基本概念和用法,包括输入流、输出流、字节流、字符流、缓冲区等。同时还介绍了异常处理和常用的流类,如FileReader、FileWriter、FileInputStream、FileOutputStream、OutputStreamWriter、InputStreamReader、BufferedReader、BufferedWriter等。此外,还介绍了系统流和标准流的使用。 ... [详细]
  • java io换行符_Java IO:为什么从stdin读取时,换行符的数字表示出现在控制台上?...
    只是为了更好地理解我在讲座中听到的内容(关于Java输入和输出流),我自己做了这个小程序:publicstaticvoidmain(String[]args)thro ... [详细]
  • 要讨论这些常用的默认初始容量和扩容的原因是:当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复 ... [详细]
  • HashMap和Hashtable的区别主要的区别有三点:线程安全性,同步(synchronization),以及速度。(两者都是无序排放)HashMap几乎可以等价于Hashtable,除了Hash ... [详细]
  • 常用API-Hashtable类及其与HashMap、HashSet的区别转载请表明出处:http:blog.csdn.netu012637501(嵌入式_小J的天空)一、Hashtable&l ... [详细]
  • HashMap及HashTable源码解析HashMap在java和Android经常使用到,之前学过数据结构,理解了它的原理,却很 ... [详细]
author-avatar
hadley朱_469
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有