跳转到内容

定义类

100% developed
来自维基教科书,开放世界中的开放书籍

导航类和对象主题:v  d  e )

Java 中的每个类都可以由以下元素组成

  • 字段成员变量实例变量 — 字段是保存特定于每个对象的数据的变量。例如,员工可能有一个 ID 号码。每个类对象都有一个字段。
  • 成员方法实例方法 — 成员方法对对象执行操作。例如,员工可能有一个方法来签发他的工资单或访问他的姓名。
  • 静态字段类字段 — 静态字段对于相同类的任何对象都是通用的。例如,Employee 类中的静态字段可以跟踪发行的最后一个 ID 号码。每个静态字段在类中只存在一次,无论为该类创建了多少对象。
  • 静态方法类方法 — 静态方法是不影响特定对象的方法。
  • 内部类 — 有时在另一个类中包含一个类很有用,如果它在类外部没有用或不应该在类外部访问。
  • 构造函数 — 生成新对象的特殊方法。
  • 参数化类型 — 从 1.5 开始,参数化类型可以在定义期间分配给类。参数化类型将在类实例化时被指定类型替换。这是由编译器完成的。它类似于 C 语言宏“#define”语句,其中预处理器评估宏。
Computer code 代码清单 4.1:Employee.java
public class Employee {              // This defines the Employee class.
                                     // The public modifier indicates that
                                     // it can be accessed by any other class

    private static int nextID;       // Define a static field. Only one copy of this will exist,
                                     // no matter how many Employees are created.

    private int myID;                // Define fields that will be stored  
    private String myName;           // for each Employee. The private modifier indicates that
                                     // only code inside the Employee class can access it.
 
    public Employee(String name) {   // This is a constructor. You can pass a name to the constructor
                                     // and it will give you a newly created Employee object.
        myName = name;
        myID = nextID;               // Automatically assign an ID to the object
        nextID++;                    // Increment the ID counter
    }
 
    public String getName() {        // This is a member method that returns the
                                     // Employee object's name.
        return myName;               // Note how it can access the private field myName.
    }
 
    public int getID() {             // This is another member method.
   
        return myID;  
    }
 
    public static int getNextID() {  // This is a static method that returns the next ID
                                     // that will be assigned if another Employee is created.
        return nextID;
    }
}

以下 Java 代码将生成此输出

Computer code 代码清单 4.2:EmployeeList.java
public class EmployeeList {
    public static void main(String[] args) {

        System.out.println(Employee.getNextID());
 
        Employee a = new Employee("John Doe");
        Employee b = new Employee("Jane Smith");
        Employee c = new Employee("Sally Brown");
 
        System.out.println(Employee.getNextID());
 
        System.out.println(a.getID() + ": " + a.getName());
        System.out.println(b.getID() + ": " + b.getName());
        System.out.println(c.getID() + ": " + c.getName());
    }
}
Standard input or output 代码清单 4.2 的控制台
0
3
0: John Doe
1: Jane Smith
2: Sally Brown

构造函数

[编辑 | 编辑源代码]

构造函数在对象分配后立即被调用来初始化对象

Computer code 代码清单 4.3:Cheese.java
public class Cheese {
  // This is a constructor
  public Cheese() {
    System.out.println("Construct an instance");
  }
}

通常,构造函数使用new关键字调用

Example 代码部分 4.1:构造函数调用。
Cheese cheese = new Cheese();

构造函数语法与方法语法类似。但是,构造函数的名称与类的名称相同(大小写相同),并且构造函数没有返回类型。第二点是最重要的区别,因为方法也可以与类具有相同的名称,这是不推荐的

Computer code 代码清单 4.4:Cheese.java
public class Cheese {
  // This is a method with the same name as the class
  public void Cheese() {
    System.out.println("A method execution.");
  }
}

返回的对象始终是一个有效的、有意义的对象,而不是依赖于单独的初始化方法。构造函数不能是abstractfinalnativestaticstrictfpsynchronized。但是,构造函数像方法一样可以重载并接受参数。

Computer code 代码清单 4.5:Cheese.java
public class Cheese {
     // This is a constructor
     public Cheese() {
          doStuff();
     }

     // This is another constructor
     public Cheese(int weight) {
          doStuff();
     }

     // This is yet another constructor
     public Cheese(String type, int weight) {
          doStuff();
     }
}

按照惯例,接受其自身类型对象的构造函数并复制数据成员称为复制构造函数。构造函数的一个有趣的特性是,如果你没有在你的类中指定构造函数,那么编译器会为你创建一个。如果写出来,这个默认构造函数看起来像

Computer code 代码清单 4.6:Cheese.java
public class Cheese {
     public Cheese() {
           super();
     }
}

super()命令调用超类的构造函数。如果没有明确调用super(...)this(...),那么默认超类构造函数super();将在构造函数主体执行之前被调用。也就是说,在某些情况下,您需要手动添加调用。例如,如果您编写了一个构造函数,无论它接受什么参数,编译器都不会添加默认构造函数。代码清单 4.8会导致运行时错误

Computer code 代码清单 4.7:Cheese.java
public class Cheese {
     public Cheese(int weight, String type) {
          doStuff();
     }
}
Computer code 代码清单 4.8:Mouse.java
public class Mouse {
     public void eatCheese() {
             Cheese c = new Cheese(); // Oops, compile time error!
     }
}

在扩展现有类时,请牢记这一点。要么创建一个默认构造函数,要么确保每个继承你的类的类都使用正确的构造函数。

初始化器

[编辑 | 编辑源代码]

初始化器是与字段初始化器同时执行的代码块。

静态初始化器

[编辑 | 编辑源代码]

静态初始化器是与静态字段初始化器同时执行的代码块。静态字段初始化器和静态初始化器按声明顺序执行。静态初始化在类加载后执行。

Example 代码部分 4.2:静态初始化器。
static int count = 20;
static int[] squares;
static {  // a static initializer
    squares = new int[count];
    for (int i = 0; i < count; i++)
        squares[i] = i * i;
}
static int x = squares[5];  // x is assigned the value 25

实例初始化器

[编辑 | 编辑源代码]

实例初始化器是代码块,它们在实例(非static)字段的初始化器执行的同时执行。实例字段初始化器和实例初始化器按声明顺序执行。实例初始化器和实例字段初始化器都在构造函数调用期间执行。初始化器在调用超类构造函数后立即执行,并在构造函数主体之前执行。


华夏公益教科书