Archive

Archive for the ‘JAVA’ Category

All About JAVA 关于JAVA对象的创建以及构造方法(2)

2010年09月25日 留下评论

      如果一个类A继承自另一个类B,当创建这个A类的对象时,构造函数是怎样运作的? 我们知道一个类继承了另一个类后,这个类会包含父类的所有的实例变量和方法。也包括父类中的private实例变量,虽然在子类中无法直接访问父类中标记为private类型的实例变量,但是仍然可以通过父类中定义的GETTER与SETTER来进行操作。并且继承自父类的一些其他方法也有可能会用到父类中的一些实例变量,如果父类中的实例变量没有进行初始化,很可能进行A的初始化时会遇到问题,所以在我们初始化A类对象之前应该先对B类(父类)进行初始化。

public class Animal {
    public Animal() {
         System.out.println("I am making a new Animal");
    }
}

public class Dog extends Animal {
    public Dog() {
         System.out.println ("I am making a new Dog");
    }
}

public class TestDog {
    public static void main(String[] args) {
        System.out.println("I am Starting");
        Dog d = new Dog();
    }
} // 这段代码,当我们运行了 TestDog 类后 正确的输出应该为
  // I am Starting
  // I am making a new Animal
  // I am making a new Dog

      可以看出,当我们创建Dog对象时首先完成了Animal类的构造方法,最后才完成了Dog类的构造方法,可以用栈来理解这个构造方法的调用,当我们new 一个 Dog 时,Dog()构造方法被压入栈中,随后Animal()构造方法被压入栈中,实际上JAVA中所有类都继承自Object,所以Object()构造方法也被压入栈中,也就是栈的最顶层。然后首先完成了Object()构造方法,Object()从栈中弹出,再完成了Animal()构造方法并从栈中弹出,最后完成了Dog()构造方法并从栈中弹出,至此Dog对象的创建工作才算完成。
      通过以上代码及输出可以看到,在Dog的构造函数运行时自动调用了它的父类Animal类的构造方法,而Animal构造方法实际上自动调用了Object类的构造方法。因为实际上JVM在我们每个构造方法的第一行添加了 super(); 这行语句。它的作用就是调用父类的构造方法,当然我们也可以手动调用super(),比如当父类的构造方法带有参数时,我们可以使用super(xx, xx);在子类的构造方法中调用父类的构造方法,但是需要注意super()语句需要放在子类构造方法的第一行进行调用,否则会报错。一旦我们自己手动调用了super() JVM将不再自动为我们添加 super() 的调用。
      另外如果我有两个或多个构造方法,当一个A构造方法只是对另一个B构造方法额外添加了一些处理,我们可能会想到代码重用,我们可以在A构造方法中使用this(); 来调用B构造方法实现代码重用。例如:

      public class Dog {
            int height;
      
            public Dog() {
                 this(40);
                 // 这里还可以做一些其他初始化处理
                 // ******  我们需要注意,this 也必须放在构造方法中的第一行,还记得之前谈到 super(); 也是要求放在第一行的,
                 // 所以 this(); 和 super(); 是不能同时使用的 ****************************************************************
             }
            public Dog( int newHeight ) {
                 height = newHeight;
            } 
      }

分类:JAVA

All About JAVA 关于JAVA对象的创建以及构造方法(1)

2010年09月25日 留下评论

      对于JAVA对象的创建,我们使用这样的语句:Object myObj = new Object(); 它实际分为三个步骤:

            1. Object myObj  — 分配存储空间并创建一个引用变量。
            2. new Object()  — 创建一个Object对象。
            3. =  — 将创建的对象引用赋值给 myObj 这个引用变量。

      在上边的第二个步骤,当我们使用了 new 这个关键词时,实际上是做了额外的一些工作来创建我们需要的对象,我们调用了 Object 对象的构造方法。构造方法与类同名,并且不能定义返回值类型,例如 Object 类的构造方法可能为:

public Object() {
     // 这里做一些初始化对象的操作
} 

public Object(int size, String name) {
     // 这里做一些类似将size 与 name赋值给实例变量等初始化对象的操作
     // 从这两个构造方法可以看出,构造方法可以带参数,并且在一个类中可以存在多个构造方法,只要它们符合重载的条件即可。
     // 符合重载的条件分为两点:参数的个数不同,相同位置上的参数的类型不同
}

public Object(String name, int size) {
     // 这个构造函数与上一个是两个不同的构造函数,因为他们满足重载的条件
}

      构造方法类似一个类的普通方法,但是它并不是类的普通方法,构造方法并没有定义返回值类型,而类的方法是必须定义返回值类型的,这是它与普通类方法的唯一区别。 很多时候在我们编写一个类时可能并没有手动编写一个构造方法,但它的确存在,因为 JVM 会自动对没有定义构造方法的类添加一个不带参数的空的构造方法。

      为什么系统已经为我们添加了构造方法,我们还需要来创建自己的构造方法?构造方法最大的作用就是让我们新创建的的对象在使用前被完整的初始化,想象一个Dog类,它有一个private int height; 实例变量,如果没有构造方法,它刚刚被创建为对象时height值默认是0的,这样我们就有了一个0高度的狗狗,显然这样不好。所以我们需要使用构造函数来初始化我们的对象,例如:

public class Dog {
    int height;

    public Dog() {
        height = 30;
    } // 当我们添加了自己的构造方法后,系统将不再为我们手动添加不带参数的构造函数
       // 这样当我们的类的使用者使用不带参数的构造方法创建对象时会产生错误,所以一般情况下建议
       // 为类添加一个不带参数的构造方法,并在其中给类的一些重要的实例变量一个默认值。

    public Dog(int newHeight) {
        height = newHeight;
    } // 对不带参数的构造方法的重载 
}

public class TestDog {
    Dog myDog = new Dog(40);
    System.out.print ( myDog.height );
}
分类:JAVA