java课后实验性问题4

课后作业一:

使用类的静态字段和构造函数,我们可以跟踪某个类所创建对象的个数。请写一个类,在任何时候都可以向它查询“你已经创建了多少个对象?

设计思路:定义类的构造函数时使静态变量i进行i++,即每构造一次就叠加一个构造的对象数。

程序流程图:

import java.util.Scanner;

public class Test {
    static int i = 0;
    public Test(){
        i++;
    }
    public static int getTimes(){
        return i;
    }
    public static void main(String[] args) {
        int x = 1;
        Scanner con = new Scanner(System.in);
        for(; x != 0;){
            System.out.print("构建个数(0退出):");
            x = con.nextInt();
            for(int t= 0; t < x; t++){
                Testi g = new Test();
            } 
            System.out.println("程序已经创建对象的个数为:" + getTimes());
        }
    }
}

 课后作业二:

1.这两种方式定义的变量是一样的吗?

Int value = 100;

MyClass obj = new MyClass();

不一样。

int “是原始数据类型”的变量。定义后,会马上给其分配内存。

MyClass “是对象变量”。声明一个对象类型变量时,实际没有创建一个对象,变量 = null。

2.对象变量可以用“==”判断两变量值是否相等吗?运行以下代码,得到什么结果?

不可以。判断的不是变量值。

public class Test{
    public static void main(String[] args){
        Foo obj1 = new Foo();
        Foo obj2 = new Foo();
        System.out.println(obj1 == obj2);
    }
}
class Foo{
    int value = 100;
}

结果:false

当“==”施加于引用类型变量时,比较的是两个变量是否引用同一个对象。

3.如何比较两个对象“内容”是否一样?

比较“字段值”。可以重写equals()方法。

public class ObjectEquals {
    public static void main(String[] args) {
        MyTestClass obj1 = new MyTestClass(100);
        MyTestClass obj2 = new MyTestClass(100);
        System.out.println(obj1 == obj2);
        System.out.println(obj1.equals(obj2));
    }
}
class MyTestClass
{
    public int Value;
    /*注意:只有参数类型为Object的,才是重写了Object的equals方法
      参数类型为MyTestClass的,仅仅是Overload了equals方法。
       @Override
       public boolean equals(Object obj) {
         return ((MyTestClass)obj).Value == this.Value;
       }
  */
public boolean equals(MyTestClass obj){ return obj.Value == this.Value; } public MyTestClass(int initValue){ Value = initValue; } }

结果:flase 

   true

4.总结一下,这个方法有那些“与众不同”之处?

public MyTestClass(int initValue){
            Value = initValue;
}

这个方法是类的构造方法。它有参数值。

5.以下代码为何无法通过编译?哪出错了?

public class Test{
    public static void main(String[] args){
        Foo obj1 = new Foo();
    }
}
class Foo{
    int value;
    public Foo(int initValue){
        value = initValue;
    }
}

Foo obj1 = new Foo()错误。

结论:如果类提供了一个自定义的构造方法,就将导致系统不再提供默认构造方法。所以,“Foo obj1 = new Foo();”中需要添加默认的参数。

6.如果一个类中既有初始化块,又有构造方法,同时还设定了字段的初始值,谁说了算?

“public int field = 100;”说了算。也就是谁比较靠后就是谁初始化起作用。执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”。

构造函数,类的初始化块不接收任何的参数,只要一创建类的对象,它们就会被执行。因此,适合于封装那些“对象创建时必须执行的代码”。

对象变量可以用“==”判断两变量值是否相等吗?运行以下代码,得到什么结果?

不可以。判断的不是变量值。

public class Test{
    public static void main(String[] args){
        GetField obj = new GetField();
        System.out.println(obj.field);
        obj = new GetField(300);
        System.out.println(obj.field);
    }
}
class GetField{
    {
        field = 200;
    }
    Public int field = 100;
    public GetField(int value){
        this.field = value;
    }
    public GetField(){
    }
}

7.请运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。

class Root{
    static{
        System.out.println("Root的静态初始化块");
    }
    {
        System.out.println("Root的普通初始化块");
    }
    public Root() {
        System.out.println("Root的无参数的构造器");
    }
}
class Mid extends Root{
    static{
        System.out.println("Mid的静态初始化块");
    }
    {
        System.out.println("Mid的普通初始化块");
    }
    public Mid() {
        System.out.println("Mid的无参数的构造器");
    }
    public Mid(String msg){
        this();
        System.out.println("Mid的带参数构造器,其参数值:" + msg);
    }
}
class Leaf extends Mid{
    static{
        System.out.println("Leaf的静态初始化块");
    }
    {
        System.out.println("Leaf的普通初始化块");
    }    
    public Leaf(){
        super("Java初始化顺序演示");
        System.out.println("执行Leaf的构造器");
    }
 
}
 
public class TestStaticInitializeBlock{
    public static void main(String[] args) {
        new Leaf();
    }
}

结论: 1.静态初始化块只执行一次。

    2.创建子类型对象时,父类静态初始化块也执行。

8.静态方法中只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?

public class Test{
    public static void main(String[] args){
    System.out.println ("(静态变量)total_employees =  "+Employee.clear());
    Employee e = new Employee();
    System.out.print("(实例变量)name =  "+e.name);
    }
}
class Employee{
    String name = "2";
    static int total_employees = 0;
    static int clear(){
        return total_employees;
    }
    static void clear2(){
    }
}    

9. 输出诡异的结果,原因何在?

public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
}
Integer cache类的实现:
 private static class IntegerCache {
        static final int high;
        static final Integer cache[];
        static {
            final int low = -128;
            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }
        private IntegerCache() {}
}

在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。

上面的代码中i1和j1的数值为100,因此会直接从cache中取已经存在的对象,所以i1和j1指向的是同一个对象,而i2和j2则是分别指向不同的对象。所以输出不同。

 

posted @ 2017-10-20 07:39  什么名都不好  阅读(260)  评论(0编辑  收藏  举报