Java 是面向对象的程序设计语言,Java语言提供了定义类、成员变量、方法等最基本的功能。类可被认为是一种自定义的数据类型,可以使用类来定义变量,所有使用类定义的变量都是引用变量,它们将会引用到类的对象。类用于描述客观世界里某一类对象的共同特征,而对象则是类的具体存在,Java程序使用类的构造器来创建该类的对象。
面向对象的程序设计过程中有两个重要概念:类(class)和对象(object,也被称为实例,instance)。类和对象是面向对象的核心。Java 语言提供了对创建类和创建对象简单的语法支持。
[修饰符] class 类名
{
零个到多个构造器定义...
零个到多个成员变量...
零个到多个方法...
}
在上面的语法格式中,修饰符可以是public、final、abstract,或者完全省略这三个修饰符。Java类名必须是由一个或多个有意义的单词连缀而成,每个单词首字母大写,其他字母全部小写,单词与单词之间不要使用任何分隔符。
对一个类定义而言,可以包含三种最常见的成员:构造器、成员变量和方法,三种成员都可以定义零个或多个,如果三种成员都只定义零个,就是定义了一个空类,这没有太大的实际意义。类里各成员之间的定义顺序没有任何影响,各成员之间可以相互调用。但需要指出的是,static修饰的成员不能访问没有static修饰的成员。
构造器是一个类创建对象的根本途径,Java 语言通过new关键字来调用构造器,从而返回该类的实例。如果一个类没有构造器,这个类通常无法创建实例。因此,Java 语言提供了一个功能:如果程序员没有为一个类编写构造器,则系统会为该类提供一个默认的构造器。一旦程序员为一个类提供了构造器,系统将不再为该类提供构造器。
定义成员变量的语法格式如下:
[修饰符] 类型 成员变量名 [=默认值];
定义方法的语法格式如下:
[修饰符] 方法返回值类型 方法名(形参列表)
{
// 由零条到多条可执行性语句组成的方法体
}
方法体里多条可执行语句之间有严格的执行顺序,排在方法体前面的语句总是先执行,排在方法体后面的语句总是后执行。
定义构造器的语法格式如下:
[修饰符] 构造器名(形参列表)
{
// 由零条到多条可执行性语句组成的构造器执行体
}
值得指出的是,构造器既不能定义返回值类型,也不能使用void 声明构造器没有返回值。如果为构造器定义了返回值类型,或使用void 声明构造器没有返回值,编译时不会出错,但Java 会把这个所谓的构造器当成方法来处理一它就不再是构造器。
简单地说,这是Java的语法规定。实际上,类的构造器是有返回值的,当使用new 关键字来调用构造器时,构造器返回该类的实例,可以把这个类的实例当成构造器的返回值,因此构造器的返回值类型总是当前类,无须定义返回值类型。但必须注意:不要在构造器里显示使用return来返回当前类的对象,因为构造器的返回值是隐式的。
static 是一个特殊的关键字,它可用于修饰成员变量、方法等。static 修饰的成员表明它属于这个类本身,而不属于该类的单个实例,因为通常把static 修饰的成员变量和方法也称为类变量、类方法。不使用static 修饰的普通方法、成员变量则属于该类的单个实例,而不属于该类。因为通常把不使用static 修饰的成员变量和方法也称为实例变量、实例方法。
由于static 的英文直译就是静态的意思,因此有时也把static 修饰的成员变量和方法称为静态变量和静态方法,把不使用static 修饰的成员变量和方法称为非静态变量和非静态方法。静态成员不能直接访问非静态成员。
static 的真正作用就是用于区分成员变量、方法、内部类、初始化块这四种成员到底属于类本身还是属于实例。在类中定义的成员,static 相当于一个标志,有static 修饰的成员属于类本身,没有static 修饰的成员属于该类的实例。
此外,static 修饰的方法和成员变量,既可通过类来调用,也可通过实例来调用。没有使用static 修饰的普通方法和成员变量,只可通过实例来调用。
创建对象的根本途径是构造器,通过new 关键字来调用某个类的构造器即可创建这个类的实例。
当一个对象被创建成功以后,这个对象将保存在堆内存中, Java 程序不允许直接访问堆内存中的对象, 只能通过该对象的引用操作该对象。也就是说,不管是数组还是对象,都只能通过引用来访问它们。
栈内存里的引用变量并未真正存储对象的成员变量,对象的成员变量数据实际存放在堆内存里。而引用变量只是指向该堆内存里的对象。从这个角度来看, 引用变量与C 语言里的指针很像, 它们都是存储一个地址值,通过这个地址来引用到实际对象。实际上,Java 里的引用就是C 里的指针,只是Java语言把这个指针封装起来,避免开发者进行烦琐的指针操作。
引用变量本身只存储了一个地址值,并未包含任何实际数据,但它指向实际的对象,当访问 引用变量的成员变量和方法时,实际上是访问引用变量所引用对象的成员变量和方法。
如果堆内存里的对象没有任何变量指向该对象,那么程序将无法再访问该对象, 这个对象也就变成了垃圾,Java 的垃圾回收机制将回收该对象,释放该对象所占的内存区。因此,如果希望通知垃圾回收机制回收某个对象,只需切断该对象的所有引用变量和它之间的关系即可,也就是把这些引用变量赋值为null 。
Java 提供了一个this 关键字,this 关键字总是指向调用该方法的对象。根据this 出现位置的不同,this 作为对象的默认引用有两种情形。
this 可以代表任何对象,当this 出现在某个方法体中时,它所代表的对象是不确定的,但它的类型是确定的。它所代表的只能是当前类的实例,只有当这个方法被调用时,它所代表的对象才被确定下来,即谁在调用这个方法,this 就代表谁。
大部分时候,普通方法访问其他方法、成员变量时无须使用this前缀,但如果方法里有个局部变量和成员变量同名,但程序又需要在该方法里访问这个成员变量时,则必须使用this前缀。
对于static 修饰的方法而言,则可以使用类来直接调用该方法,如果在static 修饰的方法中使用this关键字,则这个关键字就无法指向合适的对象。所以,static 修饰的方法中不能使用this 引用。
除此之外,this 引用也可以用于构造器中作为默认引用,由于构造器是直接使用new 关键字来调用,而不是使用对象来调用的,所以this 在构造器中代表该构造器正在初始化的对象。
当this 作为对象的默认引用使用时,程序可以像访问普通引用变量一样来访问这个this 引用, 甚至可以把this 当成普通方法的返回值。如:
- public class Dog {
-
- public int age;
-
- public Dog grow() {
- age++;
- // return this 返回调用该方法的对象
- return this;
- }
-
- public static void main(String[] args) {
- Dog dog = new Dog();
- // 可以连续调用同一个方法
- dog.grow()
- .grow()
- .grow();
- System.out.println(dog.age);
- }
-
- }
从上面程序中可以看出,如果在某个方法中把this 作为返回值,则可以多次连续调用同一个方法,从而使得代码更加简洁。但是,这种把this 作为返回值的方法可能造成实际意义的模糊,例如上面的grow 方法,用于表示对象的生长,即age 成员变量的值加1, 实际上不应该有返回值。