最近参加了一次面试,一来就给我来一套试题,下面就谈谈其中的2道题目。
面试题1
1下面程序输出什么?
public class Main {
public static void main(String[] args){
Integer f1 = 100,f2 = 100,f3 = 150,f4 = 150;
System.out.println(f1 == f2);
System.out.println(f3 == f4);
}
}
看到这个代码,刚开始有点兴奋,怎么会有这种题目出现呢?这出题人脑子有毛病,出两个一样的输出语句。一不小心很容易两个true或者2个false。但是答案是这样的吗?不是。
这题是道陷阱题,中招的概率非常大。面试完后回家翻了一下Integer包装类型的源码,
Integer f1 = 100;调用的是Integer包装类型的静态方法valueOf(),
//当在-128到127范围内,是直接从IntegerCache取Integer cache[]中的对象,
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
//超出了-128~127范围,则产生一个新的对象
return new Integer(i);
}
// cache数组的范围是-128到127
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
在Java虚拟机初始化的时候,java.lang.Integer.IntegerCache.high属性就被设置了,但是我们可以通过VM arg:-XX:AutoBoxCacheMax来进行调整,这个IntegerCache中的cache数组是在方法区的运行常量池中。所以说第一个是true,第二个是false。可以看出越是这么简单的面试题,越需要面试者需要相当深厚的功夫才行。
总结一下:对于包装类型Short Character Long Byte Integer,默认情况下都是在-128-127之间直接从方法区的运行时常量池中拿数据,超出范围则就是new出来的一个新的在堆区的对象。而对于Double Float则永远是在堆区new一个对象。对于String类型则是运行时常量池中拿数据。
面试题2
2算法实现:啤酒2元一瓶,2个空瓶可以兑换1瓶,4个瓶盖可以兑换一瓶,请问n元能买多少瓶酒? 并计算出10元能喝多少瓶?
这个题目是一个智力题,手推都能出来,问题是要写成程序,它主要考察什么呢?迭代实现?递归实现?
public class Drinking {
static int money = 10; //10元金额
static int count = money/2; //初始多少瓶酒
static int P = count; //初始空瓶
static int G = count; //初始瓶盖
public static void drink(){
//这种情况是不能再兑换酒的
if(P<2&&G<4){
return;
}
if(G>=4||P>=2){
int curAdd = P/2 + G/4; //瓶盖兑酒新增的酒
count += curAdd;
P = curAdd + P%2; //空瓶兑酒新增的空瓶 + 空瓶兑酒后剩余的空瓶
G = curAdd + G%4; //瓶盖兑酒新增的瓶盖 + 瓶盖兑酒后剩余的瓶盖
}
drink(); //再一次递归调用
}
public static void init(){
drink();
System.out.println( money +"元钱能喝:"+ count +"瓶酒,剩余"+P +"空瓶和" +G+"个瓶盖。" );
}
public static void main(String[] args) {
init();
}
}
输出结果
10元钱能喝:15瓶酒,剩余1空瓶和3个瓶盖。
static int ping,P,G;
static int sum = 10,price = 2;
static int result = 0;
public static void main(String[] args) {
ping = sum/price;
result += ping;
G = ping;
P = ping;
ping = 0;
while(G>=4||P>=2){
ping = G/4 + P/2;
result += ping;
G = G%4 + ping; //剩余的瓶盖 + 兑换新增的酒产生的瓶盖
P = P%2 + ping; //剩余的空瓶 + 兑换新增的就产生的空瓶
ping = 0; //分解后兑换的啤酒ping置0
}
System.out.println(" result = "+result + " P = " + P + " G = " + G);
}
输出结果
result = 15 P = 1 G = 3
这个题目考察的是算法,我这里实现的是没有考虑可以借酒的情况,实际的生活当中也是不存在这个情况。
面试题3
有10000个随机数,求出其中最大的三个数。(快速排序?最小堆的优先队列,BFPRT算法)
面试题4
HashMap的工作原理
面试题5
Java多线程的实现方式
面试题6
怎么使主线程等待所有子线程完成之后再执行
面试题7
java中同步实现的种类
等等 后面我再慢慢分析吧