[置顶] 【面试题】java装箱拆箱引发的思考
2016-12-04 15:55
796 查看
问题一:装箱拆箱举例
装箱拆箱的demo.javapublic class Demo{ public static void main(String[] args) { Integer i = 10; int n =i; } }
看看装箱拆箱分别通过什么方法实现的?
反编译Demo.class即可知
public class Demo { public static void main(String[] paramArrayOfString) { Integer localInteger = Integer.valueOf(10); int i = localInteger.intValue(); } }
装箱通过:
Integer localInteger = Integer.valueOf(10);拆箱通过:
int i = localInteger.intValue();
如果到这就结束了,也太小瞧面试官了。新的面试题是这样的。
问题二、八种基本类型的包装类中的常量池与否
进阶的demo.javapublic class Main { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200; System.out.println(i1==i2); System.out.println(i3==i4); } }答案是:true,false。
原因:
看看valueOf的源码:-128到128之外,则新建对象。(注释:java1.7源码)
public static Integer valueOf(int i) { return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128]; }否则,用已经存在的对象cache的引用。常量数组SMALL_VALUES(也称常量池)引用源码如下
/** * A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing */ private static final Integer[] SMALL_VALUES = new Integer[256]; static { for (int i = -128; i < 128; i++) { SMALL_VALUES[i + 128] = new Integer(i); } }
可能这么看还不直观,继续看反编译进阶demo的class的代码:看到全部都用的是valueOf方法,也就是上面的源代码。
import java.io.PrintStream; public class Demo { public static void main(String[] paramArrayOfString) { Integer localInteger1 = Integer.valueOf(100); Integer localInteger2 = Integer.valueOf(100); Integer localInteger3 = Integer.valueOf(200); Integer localInteger4 = Integer.valueOf(200); System.out.println(localInteger1 == localInteger2); System.out.println(localInteger3 == localInteger4); } }
假如面试官只是为了考点是否深入其实到这儿就结束了。碰到一个较真的面试官,可能会一并问这个问题。
进阶的demo.java混淆视听代码:
public class Demo{ public static void main(String[] args) { Double i1 = 100.0; Double i2 = 100.0; Double i3 = 200.0; Double i4 = 200.0; System.out.println(i1==i2); System.out.println(i3==i4); } }
答案:false,false。
长得几乎一摸一样,只是类型由Integer变成了Double。
原因:value的valueOf方法源码如下:
public static Double valueOf(double d) { return new Double(d); }
是不是想问为什么设计者这么变态?因为常量数量有限,可以通过常量数组去处理加快速度,而类似double,float也用-127到128范围枚举的话就太多了。
总结记住以下:(记少不记多,记住第二句!)
Integer、Short、Byte、Character、Long、Boolean有常量池。
double,float没有常量池。
问题三、boolean和Boolean的区别
遇到这么变态的面试官,赶快喊爸爸。public class Main { public static void main(String[] args) { Boolean i1 = false; Boolean i2 = false; Boolean i3 = true; Boolean i4 = true; System.out.println(i1==i2); System.out.println(i3==i4); } }
答案,一眼看出答案,true,true,只要不是被上面3题弄晕了。
//然而这一题不是问答案,问的是Boolean和boolean的区别。什么时候用到Boolean
反编译后的class
import java.io.PrintStream; public class Demo { public static void main(String[] paramArrayOfString) { Boolean localBoolean1 = Boolean.valueOf(false); Boolean localBoolean2 = Boolean.valueOf(false); Boolean localBoolean3 = Boolean.valueOf(true); Boolean localBoolean4 = Boolean.valueOf(true); System.out.println(localBoolean1 == localBoolean2); System.out.println(localBoolean3 == localBoolean4); } }答案:
唯一只能使用Boolean上的就是从列表或者哈希表获取值时。
比如
boolean t = false; Map map = new HashMap(); map.put("t", t);那么获取值时只能用Boolean t1 = (Boolean) map.get(t); //前面只能用Boolean强制转换,不能使用boolean。
简而言之:
也就是需要强制类型转换的时候。
问题四、衍生的String的问题:
如果以上都问了,问到这题,面试官,请收下我的膝盖。你肯定是因为我长得太帅,而针对我!public class Demo{ public static void main(String[] args) { String s1 = new String("hello"); String s2 = new String("hello"); System.out.println(s1 == s2);//输出false System.out.println(s1.equals(s2));//输出true String s3 = "hello"; String s4 = "hello"; System.out.println(s3 == s4);//输出true System.out.println(s3.equals(s4));//输出true } }
这题,作为一个资深面试官,我会问
答案是什么?
1. equals和==的区别?
2. String的equals方法和hashcode方法的源码是否阅读过?
如果还没晕的话,首先需要知道String是一个基本数据类型。那么这题不再是考包装类了。而是考基本数据类型和引用数据类型。了解这点,已经赢了一大半。==比较:比较值是否相等。
equals的定义比较复杂:
单看String的equals方法源码如下:
@Override public boolean equals(Object other) { if (other == this) { return true; } if (other instanceof String) { String s = (String)other; int count = this.count; if (s.count != count) { return false; } if (hashCode() != s.hashCode()) { return false; } for (int i = 0; i < count; ++i) { if (charAt(i) != s.charAt(i)) { return false; } } return true; } else { return false; } }第2行,比较是否同一个对象。如果是则返回true。
第5行,先比较字符串的长度,然后比较字符串的hashcode(如果hashcode不相等,则字符串一定不相等。反过来则需要继续判断)。最后比较每个位置的字符的值。
看看String的hashCode方法:
初始是0,每次(原累计数hash)*31 加上当前位置字符的ASCII码,比如h字符的ASCII码是104。循环累加。得到hash值。
@Override public int hashCode() { int hash = hashCode; if (hash == 0) { if (count == 0) { return 0; } for (int i = 0; i < count; ++i) { hash = 31 * hash + charAt(i); } hashCode = hash; } return hash; }
结论来了,如果
两个一模一样的字符串,它的hashcode必然是一样的。而hashcode一样,却不一定是同一个字符串。
为什么呢?
第一句的原因,原因是因为如果字符串相同,同一个算法,那么累积和必然是一个一摸一样的数值。比如“hello”,和“hello”。所以在比较字符串值是否相等的时候先比较hashcde是否一样,能加快比较速度。(因为比较一个数值肯定比挨个比较字符串要快)
第二句的原因,举个栗子“hello” 和 “hlleo”按照上面的算法,hashcode值是一样的,而事实不是同一个字符串。所以仍然需要继续比较下去。
先码到这,下波继续java。
相关文章推荐
- C#与.NET程序员面试宝典 3.1.3 面试题22:如何解决装箱和拆箱引发的性能问题
- JAVA学习提高之---- 一道面试题引发的思考之:类的初始化
- 由面试题引发对java字符串思考【转】
- Android 之Java基础---一个列表框引发的血案暨java装箱拆箱的实际应用
- 笔试题引发的思考--装箱与拆箱
- 一条语句引发的思考:装箱和拆箱,空指针的类型转换
- 一个面试题引发的思考(Java的值传递)
- 【每日一题】Java 包装类型装箱拆箱基础面试题
- 一个java面试题引发的思考
- 面试题-java自动拆箱与装箱
- Java编程之自动装箱与拆箱
- java 装箱/拆箱
- java初学者实践教程8—jdk5的拆箱与装箱
- .NET中装箱拆箱与JAVA的异同
- java装箱与拆箱
- java装箱与拆箱
- 一道面试题引发的思考
- java中 interger自动装箱拆箱
- java自动装箱、自动拆箱和正常情况性能比较
- java装箱与拆箱