课后动手动脑问题解决(2019-10-14)
一、动手动脑1
1、问题:以下代码为何无法通过编译?哪儿出错了?
2、原因
首先,当类没有定义构造函数时,会自动生成一个无参的构造方法,但当类中定义了构造方法时,就会覆盖自动生成的构造方法,
这是只能使用类中定义的构造函数,题中类已经构造一个有参的构造方法,需要参数才能调用,而主函数中只能调用类中的构造
方法,但调用没有参数,导致匹配错误,所以会产生错误。
二、动手动脑2
1、题目:
请运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。
1 class Root
2 {
3 static{
4 System.out.println("Root的静态初始化块");
5 }
6 {
7 System.out.println("Root的普通初始化块");
8 }
9 public Root()
10 {
11 System.out.println("Root的无参数的构造器");
12 }
13 }
14 class Mid extends Root
15 {
16 static{
17 System.out.println("Mid的静态初始化块");
18 }
19 {
20 System.out.println("Mid的普通初始化块");
21 }
22 public Mid()
23 {
24 System.out.println("Mid的无参数的构造器");
25 }
26 public Mid(String msg)
27 {
28 //通过this调用同一类中重载的构造器
29 this();
30 System.out.println("Mid的带参数构造器,其参数值:" + msg);
31 }
32 }
33 class Leaf extends Mid
34 {
35 static{
36 System.out.println("Leaf的静态初始化块");
37 }
38 {
39 System.out.println("Leaf的普通初始化块");
40 }
41 public Leaf()
42 {
43 //通过super调用父类中有一个字符串参数的构造器
44 super("Java初始化顺序演示");
45 System.out.println("执行Leaf的构造器");
46 }
47
48 }
49
50 public class TestStaticInitializeBlock
51 {
52 public static void main(String[] args)
53 {
54 new Leaf();
55
56
57 }
58 }
输出结果:
2、原因:
1、静态初始化块只执行一次
2、执行子类的对象时,会先执行父类的静态初始化块的
三、动手动脑3
1、题目:
使用类的静态字段和构造函数,可以跟踪某个类所创建对象的个数。请写一个类,在任何时候都可以向它查询“你已经创建了多少个对象?”。
2、代码如下
1 public class Objectnum {
2 private static int sum=0;
3 public Objectnum() {
4 sum++;
5 }
6 public static void num() {
7 System.out.println("目前已创建"+sum+"个对象");
8 }
9 public static void main(String[] args) {
10 Objectnum obj = new Objectnum();
11 Objectnum obj1 = new Objectnum();
12 Objectnum obj2 = new Objectnum();
13 Objectnum.num();
14 }
15 }
3、输出如下
四、动手动脑4
1、题目
上页ppt如下:
2、输出结果
3、总结分析
1、执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”
2、当有构造函数时执行类的构造函数
附:类的初始化块不接收任何的参数,而且只要一创建类的对象,它们就会被执行。因此,适合于封装那些“对象创建时必须执行的代码”
五、动手动脑5
1、题目
静态方法中只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?请编写代码验证你的想法
2、代码
1 public class staticplay {
2 public static void play(staticplay s1) {
3 System.out.println("你在静态方法中");
4 s1.play1();
5 System.out.println("你在静态方法中");
6 }
7 public void play1() {
8 System.out.println("这是动态方法");
9 }
10 public static void main(String[] args) {
11 staticplay s=new staticplay();
12 play(s);
13 }
14 }
3、运行结果
六、动手动脑6
1、问题
以下代码输出诡异的结果,原因何在?
2、代码
1 public class StrangeIntegerBehavior
2 {
3
4
5 public static void main(String[] args)
6 {
7
8
9 Integer i1=100;
10
11 Integer j1=100;
12
13
14 System.out.println(i1==j1);
15
16
17 Integer i2=129;//false
18
19 Integer j2=129;
20
21 System.out.println(i2==j2);
22
23 }
24
25
26 }
3、输出结果
4、解决
首先用javap来反编译生成class文件,通过源代码进行分析原因
再打开JDK源文件查看源代码
1 /**
2 * Cache to support the object identity semantics of autoboxing for values between
3 * -128 and 127 (inclusive) as required by JLS.
4 *
5 * The cache is initialized on first usage. The size of the cache
6 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
7 * During VM initialization, java.lang.Integer.IntegerCache.high property
8 * may be set and saved in the private system properties in the
9 * sun.misc.VM class.
10 */
11
12 private static class IntegerCache {
13 static final int low = -128;
14 static final int high;
15 static final Integer cache[];
16
17 static {
18 // high value may be configured by property
19 int h = 127;
20 String integerCacheHighPropValue =
21 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
22 if (integerCacheHighPropValue != null) {
23 try {
24 int i = parseInt(integerCacheHighPropValue);
25 i = Math.max(i, 127);
26 // Maximum array size is Integer.MAX_VALUE
27 h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
28 } catch( NumberFormatException nfe) {
29 // If the property cannot be parsed into an int, ignore it.
30 }
31 }
32 high = h;
33
34 cache = new Integer[(high - low) + 1];
35 int j = low;
36 for(int k = 0; k < cache.length; k++)
37 cache[k] = new Integer(j++);
38
39 // range [-128, 127] must be interned (JLS7 5.1.7)
40 assert IntegerCache.high >= 127;
41 }
原因:由于源代码只支持-128到127的范围,129超出此范围,所以输出如上结果
posted on 2019-10-14 21:07 yangliuliu 阅读(155) 评论(0) 编辑 收藏 举报