该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2011-03-08
这更应该叫面试知识点,或者说三年以下程序员面试知识点。
|
|
返回顶楼 | |
发表时间:2011-03-08
第七题弄明白的条件是,你么知道,传递的只是引用的拷贝
|
|
返回顶楼 | |
发表时间:2011-03-08
String x = "hello";
String y = "world"; String a = "helloworld"; System.out.println("a == x+y:" + (a == (x + y))); 因为x,y都是引用数据类型,都可以看成是一个对象,这样两个应用数据类型相加,会在堆中产生一个新的对象,所以就不相等了 |
|
返回顶楼 | |
发表时间:2011-03-09
fastbo 写道 以下几个知识点是非常容易搞混的Java知识点。大家不准开编译器,并且先不看答案,要是能全部答对,那Java基础是挺牢固的。如果答对了,还能分析出具体原因,那算你NB。近段时间有参加一些公司的面试,做了一些基础题,发现总有掌握得不好的地方。今天一并总结了这些问题,希望对大家有所帮助。如果大家认为还有其它易混淆的地方,也可以跟贴发出来,大家一起讨论。从大家的回贴中,发现了不少自已不知道的东西,想看的就看吧。
一、关于Switch 代码: public class TestSwitch { public static void main(String[] args) { int i = 2; switch (i) { case 1: System.out.println(1); case 2: System.out.println(2); case 3: System.out.println(3); default: System.out.println(4); } } } 结果: 2 3 4 分析: 少了break;所以2以下的case和default都执行了一遍。 二、Equals和==运算符 代码: public static void test() { String x = "hello"; String y = "world"; String z = new String("helloworld"); String a = "helloworld"; System.out.println("x+y equals z:" + (x + y).equals(z)); System.out.println("a == z:" + (a == z)); System.out.println("x == hello:" + (x == "hello")); System.out.println("a == helloworld:" + (a == "hello" + "world")); System.out.println("a == x+y:" + (a == (x + y))); } 结果: x+y equals z:true a == z:false x == hello:true a == helloworld:true a == x+y:false 分析: 1.String.equals()方法比较的是字符串的内容,所以(x + y).equals(z)为true. 2.“==”比较的是 String 实例的引用,很明显 a 和z 并不是同一个 String 实例,所以(a == z)为false. 3.根据常量池的知识,容易得知(x == "hello")和(a == "hello" + "world")都为true. (常量池指的是在编译期被确定并被保存在已编译的.class 文件中的一些数据。它包含了 关于方法、类、接口等,当然还有字符串常量的信息。也就是所谓的持久代。) 4.那么(a == (x + y))为什么是false呢?这点暂点有点不大清楚。初步认为是x+y是引用相加,不能放入常量池。 三、Override覆盖 代码: public class Parent { public static String say() { return "parent static say"; } public String say2() { return "parent say"; } } public class Child extends Parent { public static String say() { return "child static say"; } public String say2() { return "child say"; } } /** * @author 子弹哥 * */ public class OverrideTest { public static void main(String[] args) { Parent p = new Child(); System.out.println(p.say()); System.out.println(p.say2()); } } 结果: parent static say child say 分析: 1.我们创建了一个Parent类的实例。变量 p 的数据类型为 Parent 类 但是它仍旧是 Child 类的一个实例。因为Child类覆盖了Parent类的方法say2(),所以p.say2()调用为子类的方法。 2.为什么p.say()却是调用父类Parent的方法呢?因为Java中规定“实例方法被覆盖,静态方法被隐藏”. 关于Override的一些规则: 用子类的静态方法隐藏父类中同样标识的实例方法是不合法的,编译器将会报错; 用子类的实例方法覆盖父类中同样标识的静态方法也是不合法的,编译器同样会报错; 带关键字 final的方法(静态和实例方法)都不能被覆盖; 实例方法能够被覆盖; 抽象方法必须在具体类中被覆盖。 四、Java强类型 代码: /** * @author 子弹哥 * */ public class Type { public static void main(String[] args) { double i = 5.0; double j = 1 / 4 + 3 / 4 + i + 12 / 6.0 + 3 / 4 + 1 / 4; System.out.println(j); } } 结果: 7.0 分析: Java 是强类型的 strongly type,它支持8 种基本数据类型。通过对这些基本数据类型用法的严格检查 Java 编译器能够及时地在开发过程中捕捉到许多简单细微的错误。基本数据类型的转换可以隐性地发生,所以转换时会有精度损失。由于1/4和3/4发生隐性类型转换,精度损失,不会生成0.25和0.75,所以有分号的数都为0。 五、假构造函数 代码: /** * @author 子弹哥 * */ public class Constructor { private int a, b, c; public void Constructor() { a = 3; b = 5; c = a + b; } public void test() { System.out.println("The value of c :" + c); } public static void main(String[] args) { Constructor c = new Constructor(); c.test(); } } 结果: The value of c :0 分析: public void Constructor()并不是一个真正的构造函数,而是一个方法。所以c的值为默认值0. 六、提前引用 代码: /** * @author 子弹哥 * */ public class ForwardReference { static int first = test(); static int second = 2; static int test() { return second; } public static void main(String[] args) { System.out.println("first = " + first); } } 结果: first = 0 分析: 由于在初始化second之前test方法就访问了它,那么方法得到的是second的默认值,即 0。 因此输出结果first= 0,而不是2。假如你使用方法调用来初始化静态变量,那么你必须保证 这些方法并不依赖于在它们之后声明的其它静态变量。静态变量以及静态初始化块是在类被加载进 JVM 时执行初始化操作的。Java 语言规范8.5节指出“静态初始化块和静态变量是按照其在代码中出现的顺序依次执行初始化操作的,而不能在类变量声明出现之前就引用它”。 七、对象引用 代码: /** * @author 子弹哥 * */ public class TestRef { public static void main(String[] args) { StringBuffer a = new StringBuffer("a"); StringBuffer b = new StringBuffer("b"); append(a, b); System.out.println(a.toString() + "," + b.toString()); b = a; System.out.println(a.toString() + "," + b.toString()); } public static void append(StringBuffer a, StringBuffer b) { a.append(b); b = a; } } 结果: ab,b ab,ab 分析: 大家来分析一下这题,我还没有完全理解。 我的分析,可能是错的,哈哈,算是抛砖引玉。 1.a.append(b);-->ab 。因为a是引用,所以调用a的方法,相当于直接调用jvm中的a,所做的append也相当于直接在对象上操作,生效。 2.append方法中第一次b=a,-->b。因为a,b都为main方法内局部变量,跨append方法作用域b对a的引用不生效。 3.main方法中第二次b=a,-->ab。因为在同一作用域方法中,b对a的引用生效,。 |
|
返回顶楼 | |
发表时间:2011-03-09
这里有最后一题的详细说明:http://anna-zr.iteye.com/blog/382459
|
|
返回顶楼 | |
发表时间:2011-03-09
那么(a == (x + y))为什么是false呢?这点暂点有点不大清楚。初步认为是x+y是引用相加,不能放入常量池。
因为你的x、y不是final的,无法在编译期间加入常量池。 |
|
返回顶楼 | |
发表时间:2011-03-09
java解惑上说的很明白啊
|
|
返回顶楼 | |
发表时间:2011-03-09
fellatioyzx 写道 我都答对了
关于最后一题的话,由于java方法传值是值传递,所以方法里面的ab虽然和方法外的ab指向的对象一样,但是这两个引用在栈中的位置不一样。 过程大概是首先在栈中复制引用a为a',b为b',并令a'指向a所指的在堆中的StringBuffer对象,b'指向b所指的在堆中的StringBuffer对象。 因此方法中的b=a只是起到了b'=a'的作用,并没有影响方法外b的指向。 此言与我心中所想完全一致 |
|
返回顶楼 | |
发表时间:2011-03-16
这帖子挺给力的
|
|
返回顶楼 | |
发表时间:2011-03-16
x跟y是final的下面
System.out.println("a == x+y:" + (a == (x + y))); 就是true了,因为这时候是常量,编译期间就能确定的值,就直接饮用字符串池里的。 |
|
返回顶楼 | |