存档

‘Java’ 分类的存档

SCJP考试通过了

2009年10月30日 低调の华丽 2 条评论

SCJP成绩单

前天去上海参加了SCJP的考试,终于过了,看来一个月的复习没白费。

考试地点在交大慧科南洋,提前一天去的预约。第二天中午到了那里,不过不知道是因为老师太热情的缘故,突然感觉有点紧张。在考场外面看了一个多小时的书,让自己调整下心情。

开始有几个问题好像是SUN的调查问卷(貌似还计入考试时间了),我没怎么看,都是胡乱填的。一共60道题(之前以为有72道),考试时间是3个小时,时间上还是比较充裕的。而且之前以为选择题是不定项选择题,后来才发现会告诉本题的答案数量,这也大大降低了难度。做题花了两个小时,检查了一个小时,最后成绩出来,81分,还是比较满意的。

SCJP的考试总体来说不难,但是设计J2SE的方方面面,虽然有的题看起来比较偏,但是确实能反映对一些知识的掌握程度。怎么说对自己这两年的技术有个交待了,很欣慰,哈哈!

接下来要等6周后才能拿到SUN寄出的考试证书,比较期待。

分类: Java 标签: ,

关于Java的一些编译机制

2009年10月26日 低调の华丽 没有评论

No.1 前几天在JavaEye上看到有人讨论Java对String常量优化的问题,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package test;
 
public class TestA {
	public static void main(String[] args) {
                String s="ab";
		String s1="a";
		String s2="b";
		String s3=s1+s2;
		String s4="a"+"b";
		System.out.println(s3==s4);
		System.out.println(s3=="ab");
		System.out.println(s4=="ab");
	}
}

结果:false
false
true

s3和s4虽然值相同,但是显然s3和s4并没有指向同一个String常量池中的String常量。String s4=”a”+”b”;,字符串连接的行为是在编译期间,编译器给优化了。而String s3=s1+s2;中的字符串连接是在代码运行期间进行的。这也间接的说明一个问题,就是String常量池在代码运行前就已经分配好了,代码运行时生成的String对象不会增加到String常量池中。因为s4指向的对象是在代码运行时新生成的对象,所以s3和s4没有指向同一个对象。

推荐这篇文章《Java编译器对于String常量表达式的优化

No.2 Java编译涉及到的基本变量的问题。下面的代码

1
2
3
4
5
6
7
8
9
10
11
package test;
 
public class TestA {
	public static void main(String[] args) {
		short s=10;//这行代码可以通过编译
		new TestA().go(11);//无法通过编译,需要进行类型转换
	}
	short go(short s){
		return 12;//可以通过编译
	}
}

之前我一直无法理解为什么第5行和第9行可以通过编译,第6行不能通过编译,需要进行强制类型转换。因为这三行同样都是基本变量赋值的问题。后来我发现,这里面涉及到一个重载的问题。比如下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package test;
 
public class TestA {
	public static void main(String[] args) {
		short s=10;
		new TestA().go(11);//go方法会取调用最匹配的重载方法
	}
 
	short go(short s){
		return 12;
	}
//	short go(int i){
//		return 12;
//	}
	short go(long l){
		return 12;
	}
}

在go(int i)的方法注释掉之前,自然会调用go(int i)方法,注释掉之后,g(11)会调用最匹配的重载方法,而11既可以赋值给short型(强制类型转换),也可以赋值给long型(隐式类型转换),这是不可能的,不存在两个重载方法都匹配的情况,那样的话编译器无法知道真正要调用的方法到底是哪个。所以编译器无法为你主动做强制类型转换,,只能调用go(long l)方法。所以java规定第6行那样的情况需要做强制类型转换。

分类: Java 标签: , , ,

protected访问级别

2009年10月23日 低调の华丽 没有评论

protected是子类继承和包级访问。对于包外子类,只能通过继承访问protected成员,不能通过使用对超类实例的引用来访问protected成员(换句话说,继承是包外子类访问其超类protected成员的唯一机制)。

对于实例变量和静态变量来说,有一些区别

TestA

package test4;
 
public class TestA {
	protected static int i = 11;
	protected int i2=12;
}

TestB

package test5;
 
import test4.TestA;
 
public class TestB extends TestA{
	public static void main(String[] args) {
		TestA ta=new TestA();
		System.out.println(ta.i);//
		System.out.println(TestA.i);//
		System.out.println(TestB.i);//
		//System.out.println(ta.i2); 这行代码不能被编译*
 
		TestB tb=new TestB();
		System.out.println(tb.i2);
		System.out.println(tb.i);
		new TestA.go();
	}
 	public void go() {
		System.out.println(i);
		System.out.println(i2);
	}
}

一开始觉得奇怪,因为在TestA里,System.out.println(ta.i);可以被编译,而System.out.println(ta.i2);不能被编译。

事实是,protected并不是父类的方法能在子类中访问,而是父类方法在子类中被继承,所以子类通过继承访问protected方法。

在TestA中,ta.i可以被访问,是因为静态变量i被继承,而静态变量是class级变量,ta.i相当于TestA.i而TestA.i也就相当于TestB.i(TestB继承了此静态变量),这点和对象不一样

而ta.i2,因为i2只能通过子类继承访问,所以从对象ta中无法访问实例变量i2

因为是继承访问,go方法中的两句代码可以被编译

分类: Java 标签: ,