“金山快盘”6道面试题题目及解答如下。
第一题:String,StringBuilder,StringBuffer的区别。
String:有两种初始化方式。其一是字面值创建,其二是使用new关键字创建。
举例如下:
String strA=“adf”;
String strB=“adf”;
String strC=new String("adf");
String strD=new String("adf");
根据字面值创建的是保存在常量池中,创建StrB的时候,先检查常量池中是否已经存在常量“adf”,如果已经存在,此时不会再创建新的字符串。创建strC的时候,不会去常量池中查找,而是在堆内存中直接创建了一个对象。即使再创建strD变量,同样会再开辟内存。因此当字符串串联时会造成很大浪费如下:
String strE=“a”+“df”+"ty";//中间会生成无用的“adf”,最终生成“adfty”。
String strF=strC+strD;//重新开辟内存存储strF
如果经常对字符串进行插入,删除,追加等操作,显然会造成内存浪费。解决办法是:StringBuffer
StringBuffer:String类是不可变的,体现在它是final修饰的类。内部维护的是:
private final char value[]; // The value is used for character storage
(注:String用final修饰,应用了设计模式中的不可变模式,该模式的好处是:在多线程操作的时候,有效的避免了异步问题,但是显然在内存方面就会做出牺牲)
对于StringBuffer,它同样是维护一个数组,但是它默认的数组大小是16,所以在append追加的时候,会检查是否越界才进行添加。这样不会每次都创建新的对象,而是直接对该对象操作,避免了内存浪费。对于线程异步问题,则是使用了关键字synchronized修饰,强制性进行了同步,所以是线程安全的。
StringBuilder:它和StringBuffer的区别在于它不是线程安全的。可以发现该类中方法并没有synchronized的修饰。StringBuffer是@since JDK1.0,StringBuilder是 @since 1.5
第二题:用什么办法可以让父类的方法不能被子类覆盖。
1:final: 无法继承,何谈重写。
2:private:无法继承,何谈重写。
3:static :可以被继承,不能被重写。
第三题:Java为什么可以在不同平台上运行?
只要在不同平台上安装了JRE-运行时环境,它会根据不同的平台将class文件翻译成不同平台上的执行命令,实现与平台无关。
第四题:给定一个数组,求出第二个最大的数。
可以先排序(如冒泡)再取出。方法应该很多。
第五题:用递归和非递归实现K阶Fib(K,n)函数。函数定义是:
F(n)=F(n-1)+F(n-2)+...+F(n-k),(n>=k)
F(n)=1,(n=k-1)
F(n)=0,(0=<n<k-1)
递归方法:
public static int FibD(int k, int n) {
// 递归终止条件
if (n < k) {
return 0;
}
if (n == k) {
return 1;
}
// 初始化数组前k-1项的值
int[] data = new int[n];
for (int i = 0; i < k - 1; i++) {
data[i] = 0;
}
// 第k项的值
data[k - 1] = 1;
// 计算
int total = 0;
for (int j = n - k; j < n; j++) {
total += FibD(k, j);
}
return total;
}
非递归方法:
public static int FibF(int k, int n) {
int[] data = new int[n];
// 前k-1项的值
for (int i = 0; i < k - 1; i++) {
data[i] = 0;
System.out.println("data[" + i + "]=" + data[i]);
}
// 第k项的值
data[k - 1] = 1;
for (int i = k; i < n; i++) {
for (int j = i - k; j < i; j++) {
data[i] += data[j];
}
}
return data[n-1];
}
第六题:设计一个日志类框架,可以实现自定义的KPLog日志类,写出主要思路和核心代码(尚未实现)