整理一波笔试中一些比较有意思的题目,顺便复习下 ~
秋招真是叫人头大 。
不定时持续更新 ~
1. Try-Catch
以下代码的运行结果是什么 ? 如果将①处注释掉,并去掉②处的注释,重新运行,结果又是什么?
public class Demo {
public static void main(String args[]) {
int num = 10;
System.out.println(test(num));
}
public static int test(int b) {
try {
b += 10;
return b++;// !
} catch (RuntimeException e) {
} catch (Exception e2) {
} finally {
b += 10;
return b; //①
}
// return 1; //②
}
}
答案 : 31 , 20 。这里需要注意finally语句块对try语句块中的return的影响。
一句话总结就是 finally块的语句在try或catch中的return语句执行之后 , 返回之前执行 且finally里的修改语句可能影响也可能不影响try或catch中return已经确定的返回值, 若finally里也有return语句则覆盖try或catch中的return语句直接返回。
2. 基本包装类型
有如下4条语句 :
Integer i01=59;
int i02=59;
Integer i03=Integer.valueOf(59);
Integer i04=new Integer(59);
那么以下哪些语句输出结果为true?
A. System.out.println(i01==i02);
B. System.out.println(i01==i03);
C. System.out.println(i03==i04);
D. System.out.println(i02==i04);
答案 : A , B , D
要做对这一题需要知道 :
① 包装类型的缓存机制 , 对于Byte,Short,Integer,Long,Character这5种整型的包装类,在使用 = 直接赋值时,值的范围在∈[-128,127]时会使用缓存,即会将其置入常量池中,引用的是常量池中的对象。
② 对于包装类的valueOf方法同样的也使用了常量池缓存技术,以Integer为例:
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
*@param i an {@code int} value.
*@return an {@code Integer} instance representing {@code i}.
*@since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
③ == 运算符在一边为数值类型,一边为包装类型时,会自动拆箱(编译器完成)。
④ 使用new 关键字时引用的总是在堆中新建的对象。
3. getClass()
下面一段代码的输出结果是什么 ?
package test;
import java.util.Date;
public class SuperTest extends Date{
private static final long serialVersionUID = 1L;
private void test(){
System.out.println(super.getClass().getName());
}
public static void main(String[]args){
new SuperTest().test();
}
}
答案 :test.SuperTest
解析 :
TestSuper和Date的getClass都没有重写,他们都是调用Object的getClass,而Object的getClass作用是返回的是运行时的类的名字。这个运行时的类就是当前类 。
4. 数组的复制
下面几种数组复制方法中,哪个效率最高?
A. for循环逐一复制
B. System.arraycopy
C. Array.copyof
D. 使用clone方法
答案 :B
解析 :for循环的话,肯定是最慢的,System.arraycopy 是native方法,Arrays.copyof本质上也是调用的System.arraycopy方法,故性能自然比System.arraycopy要低,clone的话返回的是Object类型,需要强制转换,故一般会慢一点。
实际上,这几种方式在复制小型数组的时候,性能相差无几,一般在需要复制大型数组的时候使用System.arraycopy来提高性能。
5.静态方法的绑定
有关下述Java代码描述正确的选项是__?
public class TestClass {
private static void testMethod(){
System.out.println("testMethod");
}
public static void main(String[] args) {
((TestClass)null).testMethod();
}
}
A. 编译失败
B. 编译通过,运行异常,报NullPointerException
C. 编译通过,运行异常,报NoSuchMethodException
D. 运行正常,输出testMethod
答案 :D
解析 :静态方法绑定在类上,不依赖具体实例,且null可以被转换为任意类型,于是可以通过它来执行静态方法。
6. final 修饰变量
关于下面的代码段,叙述正确的是?
byte b1=1,b2=2,b3,b6;
final byte b4=4,b5=6;
b6=b4+b5;
b3=(b1+b2);
System.out.println(b3+b6);
A. 输出结果:13
B. 语句:b6=b4+b5编译出错
C. 语句:b3=b1+b2编译出错
D. 运行期抛出异常
答案 :C ,
解析 :b1和b2是byte类型,JAVA中进行计算时候将他们提升为int类型,再进行计算,b1+b2计算后已经是int类型,赋值给b3,b3是byte类型,类型不匹配,编译不会通过,需要进行强制转换。被final修饰的变量是常量,类似于C语言中的宏变量,在编译时就会被替换为对应的字面量,故这里的b6=b4+b5可以看成是b6=10。
7. JMM
检查程序,是否存在问题,如果存在指出问题所在,如果不存在,说明输出结果。
package cn.echo0.jmm;
public class LocalVariableTest {
public static void main(String[] args) {
LocalVariableTest localVariableTest = new LocalVariableTest();
int i = 0;
localVariableTest.increase(i);
i = i++;
System.out.println(i);
}
void increase(int i) {
i++;
}
}
答案 : 能正常运行,输出结果为 0。
解析 :
① Java中都是值传递。
② 对于 i=i++; 一句 ,Java使用了中间缓存变量机制,等同于以下代码段:
temp = i; ( 对应于i=i++ 等号右边的i )
i = i + 1; ( 等号右边的 i )
i = temp; ( 等号左边的 i )
8. math
Math.round(11.5) 等于多少 (). Math.round(-11.5) 等于多少 ( )?
答案 :12,-11 。
解析 : Math.round(x) 等同于 Math.floor(x+0.5) , 即将原来的数字加上0.5后再向下取整 。
9. 类的初始化
下面代码的输出是什么?
public class Base
{
private String baseName = "base";
public Base()
{
callName();
}
public void callName()
{
System. out. println(baseName);
}
static class Sub extends Base
{
private String baseName = "sub";
public void callName()
{
System. out. println (baseName) ;
}
}
public static void main(String[] args)
{
Base b = new Sub();
}
}
答案 : null 。
解析 : 在创建子类对象时,总是会先创建父类对象,创建父类即默认调用Base()方法,在base()中调用了callName()方法,而子类重写了这个方法,所以被调用的是子类中的callName()方法,但是此时子类仍未构造,所以变量baseName的值为null。
10. Java中的关键字
null 是java中的关键字吗? true 和 false 呢 ? 那么 const 和 goto 呢?
答案 : null 仅仅只是空字面常量,true和false也仅仅只是布尔字面常量,并非关键字,在 Java 中 const 和 goto 尽管没有被使用,但仍然被保留为关键字了 。