构造方法

构造方法

对象实例化

下面的例子展示如何访问实例变量和调用成员方法:

public class Puppy{
   int puppyAge;
   public Puppy(String name){
      // 这个构造器仅有一个参数:name
      System.out.println("小狗的名字是 : " + name );
   }

   public void setAge( int age ){
       puppyAge = age;
   }

   public int getAge( ){
       System.out.println("小狗的年龄为 : " + puppyAge );
       return puppyAge;
   }

   public static void main(String[] args){
      /* 创建对象 */
      Puppy myPuppy = new Puppy( "tommy" );
      /* 通过方法来设定age */
      myPuppy.setAge( 2 );
      /* 调用另一个方法获取age */
      myPuppy.getAge( );
      /*你也可以像下面这样访问成员变量 */
      System.out.println("变量值 : " + myPuppy.puppyAge );
   }
}

构造方法

每个类都有构造方法。如果没有显式地为类定义构造方法,Java 编译器将会为该类提供一个默认构造方法。在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法。下面是一个构造方法示例:

public class Puppy {

  public Puppy() {}

  public Puppy(String name) {
    // 这个构造器仅有一个参数:name
  }
}

构造方法的名字和类名相同,并且没有返回值,构造方法主要用于为类的对象定义初始化状态。我们不能直接调用构造方法,必须通过 new 关键字来自动调用,从而创建类的实例。Java 的类都要求有构造方法,如果没有定义构造方法,Java 编译器会为我们提供一个缺省的构造方法,也就是不带参数的构造方法。

使用 Java 类实例化一个对象的时候,如果在类中不显式的声明其构造函数,则会使用一个默认的构造函数来初始化对象。

//一个没有显式声明构造函数的类
Public class People{
    int age = 23;
    Public void getAge(){
        System.out.print("the age is "+age);
    }
}

//用这个类来实例化一个对象
People xiaoMing = new People(); // People() 是People类的默认构造函数,它什么也不干
xiaoMing.getAge();//打印年龄

也可以在声明类的时候显式的声明一个构造函数:

//一个带显式构造函数的类
Public class People{
    int age = 23;
        Public void getAge(){
        System.out.print("the age is "+ age);
    }
    // 显式声明一个带参数的构造函数,用于初始化年龄
    Public People(int a){
        this.age = a;
    }
}

//用这个类来实例化一个对象
People xiaoMing = new People(20); // 使用带参数的构造函数来实例化对象
xiaoMing.getAge(); // 打印出来的年龄变为20

交叉调用

Java 允许在某个构造函数中调用另一个构造函数,推荐的模式是从最小的构造器一直调用到最大的构造器,示例代码如下:

public class Cons {

  public Cons() {
    // A no arguments constructor that sends default values to the largest
    this(madeUpArg1Value, madeUpArg2Value, madeUpArg3Value);
  }

  public Cons(int arg1, int arg2) {
    // An example of a partial constructor that uses the passed in arguments
    // and sends a hidden default value to the largest
    this(arg1, arg2, madeUpArg3Value);
  }

  // Largest constructor that does the work
  public Cons(int arg1, int arg2, int arg3) {
    this.arg1 = arg1;
    this.arg2 = arg2;
    this.arg3 = arg3;
  }
}

这里需要注意的是,一定要把 super 或者对于其他构造函数的调用语句放在本构造函数的第一行。另一种可以替代的方式就是封装成单独的 set 方法:

public class Cons {
  public static Cons newCons(int arg1,...) {
    // This function is commonly called valueOf, like Integer.valueOf(..)
    // More recently called "of", like EnumSet.of(..)Cons c = new Cons(...);
    c.setArg1(....);return c;
  }
}

finalize() 方法

Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize(),它用来清除回收对象。例如,你可以使用 finalize() 来确保一个对象打开的文件被关闭了。在 finalize() 方法里,你必须指定在对象销毁时候要执行的操作。

finalize() 一般格式是:

protected void finalize()
{
   // 在这里终结代码
}

关键字 protected 是一个限定符,它确保 finalize() 方法不会被该类以外的代码调用。当然,Java 的内存回收可以由 JVM 来自动完成。如果你手动使用,则可以使用上面的方法。

public class FinalizationDemo {
  public static void main(String[] args) {
    Cake c1 = new Cake(1);
    Cake c2 = new Cake(2);
    Cake c3 = new Cake(3);

    c2 = c3 = null;
    System.gc(); //调用Java垃圾收集器
  }
}

class Cake extends Object {
  private int id;
  public Cake(int id) {
    this.id = id;
    System.out.println("Cake Object " + id + "is created");
  }

  protected void finalize() throws java.lang.Throwable {
    super.finalize();
    System.out.println("Cake Object " + id + "is disposed");
  }
}

/**
$ javac FinalizationDemo.java
$ java FinalizationDemo
Cake Object 1is created
Cake Object 2is created
Cake Object 3is created
Cake Object 3is disposed
Cake Object 2is disposed
**/

构造器调用顺序

子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

class SuperClass {
  private int n;
  SuperClass(){
    System.out.println("SuperClass()");
  }
  SuperClass(int n) {
    System.out.println("SuperClass(int n)");
    this.n = n;
  }
}
// SubClass 类继承
class SubClass extends SuperClass{
  private int n;

  SubClass(){ // 自动调用父类的无参数构造器
    System.out.println("SubClass");
  }

  public SubClass(int n){
    super(300);  // 调用父类中带有参数的构造器
    System.out.println("SubClass(int n):"+n);
    this.n = n;
  }
}
// SubClass2 类继承
class SubClass2 extends SuperClass{
  private int n;

  SubClass2(){
    super(300);  // 调用父类中带有参数的构造器
    System.out.println("SubClass2");
  }

  public SubClass2(int n){ // 自动调用父类的无参数构造器
    System.out.println("SubClass2(int n):"+n);
    this.n = n;
  }
}
public class TestSuperSub{
  public static void main (String args[]){
    System.out.println("------SubClass 类继承------");
    SubClass sc1 = new SubClass();
    SubClass sc2 = new SubClass(100);
    System.out.println("------SubClass2 类继承------");
    SubClass2 sc3 = new SubClass2();
    SubClass2 sc4 = new SubClass2(200);
  }
}

/**
------SubClass 类继承------
SuperClass()
SubClass
SuperClass(int n)
SubClass(int n):100
------SubClass2 类继承------
SuperClass(int n)
SubClass2
SuperClass()
SubClass2(int n):200
**/
上一页