Java学习总结--第六章 对象和类

本文总结源自《Java语言程序设计》原书第五版,作者为Y.daniel Liang,习题及编程练习均参照此书。


主要内容

面向对象程序设计把数据和属于它们的操作放入一个叫做对象(object)的整体中,所有对象都与属性和活动联系在一起,这样做使程序更容易开发和维护。
本章将介绍面向对象程序设计的基本知识:声明类、创建对象、处理对象以及组织对象协调工作。

对象和类

  • 对象代表现实世界中可以明确表示的一个整体。对戏那个有自己独特的特性、状态和行为。对象的状态(state)是由具有当前值的数据域(data field,又称为属性)的集合构成的。对象的行为(behavior)方法(methed)的集合定义的。
  • 类(class)是定义同一类型对象的结构。在Java的类中,数据用来描述属性,方法用来定义行为。
    类提供构造方法(constructor),调用它可以创建类的对象。构造方法是用来进行初始化操作的。
  • 包含main方法的类称为主类(main class)

构造方法

  • 构造方法必须与定义它的类有完全相同的名字。构造方法可以重载,方便使用不同的初始数据值来构造对象。
  • 构造方法没有返回类型,甚至连void也没有。
  • 构造方法分为有参构造方法无参构造方法。后者在类中没有明确声明构造方法时会自动生成,以避免程序出错。无参构造方法称为默认构造方法
  • 构造方法的调用是在创建一个对象时使用new操作符进行的。
    类是一个蓝本,定义对象的数据和方法。一个对象是类的一个实例。可以从一个类中创建多个实例。创建的一个实例被称为实例化(instantiation)对象(object)实例(instance)两个词语经常互换使用。

对象的访问

  • 新创建的对象在内存中占用空间,通过访问对象的引用变量来访问,该变量仅包含对象的引用地址。
    一个类所定义的类型被称为引用类型(reference type)

    1
    String str;
  • 访问新创建的对象的数据和方法:

    1
    2
    objectRefVar.data------引用对象的数据。
    objectRefVar.method------引用对象的方法。
  • 当创建一个对象,但不赋给这个对象任何引用变量,那么这样创建的对象称为匿名(anonymous)对象。

  • 基本数据类型变量和引用类型变量的区别
    • 基本数据类型在内存中存储时就是基本类型的数据,但是引用类型在内存中存储的是一个引用,指向对象的存储地址。
    • 将一个基本数据类型变量赋值给另一个变量时,这个变量也有了相同的值。但将一个引用类型变量赋值给另一个变量时,这个变量仅拥有原来对象的引用。

可见性修饰符、访问器和修改器

Java提供了几个修饰符,用来控制对数据、方法和类的访问。

  • public 使类、方法和数据域可以在任何类中访问。
  • private 使方法和数据域只能从它自己所在类中访问。
  • 默认情况下,类、方法和数据域可以从同一个包里的任何类中访问,这时也被称为包私有的(package-private)或者包内访问的(package-access)
  • 一个对象不能访问自己类中的私有成员。但是,如果对象是在自己类内声明的则可以。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // 对象在自己类中声明,正确
    public class Foo {
    private boolean x;
    public static void main(String[] args) {
    Foo foo = new Foo();
    System.out.println(foo.x);
    System.out.println(foo.convert(foo.x));
    }
    private int convert(boolean b) {
    return x?1:-1;
    }
    }
    //对象不在自己类中声明,无法访问私有成员
    public class Test {
    public static void main(String[] args) {
    Foo foo = new Foo();
    System.out.println(foo.x);
    System.out.println(foo.convert(foo.x));
    }
    }
  • 修饰符private只修饰数据和方法,不修饰整个类(内部类除外)。
  • 大多数情况下,构造方法应该是公用的(public)。但是,如果不想让用户创建某个类的实例,可以使用私有的构造方法。例如:Math类。

数据域的封装(data field encapsulation)

  • 为了避免通过对象引用直接修改属性,应该使用private修饰符声明私有域。
  • get()方法称为读取器(getter)或访问器(accessor),set()方法称为设置器(setter)或修改器(mutator)。
  • 使用数据域封装使类更加容易维护。

永久对象和类

  • 如果一个对象一旦被创建,它的内容就不能再改变,那么该对象就称为永久对象(immutable object),它的类称为永久类(immutable class)
  • 一个类的所有数据都是私有的并且没有修改器,但它不一定是永久类。
    1
    //todo

要使一个类成为永久类,必须将所有数据域说明为私有的,并且不含返回引用非永久对象数据域的修改器和访问器。

给方法传递对象参数

  • 传递对象实际上是传递对象的引用(copy referance);传递基本数据类型的参数时,传递的是实参的值。(copy value)

静态变量、常量和静态方法

  • 实例变量不能被同一个类中的多个对象共享,静态变量(static variavle,又称为类变量)可以让一个类中的所有实例共享数据。
  • 静态变量存储在类的公用内存中,如果某个对象修改了静态变量的值,同一类中的所有对象都会受到影响。
  • 使用修饰符static声明静态变量或静态方法。

变量的作用域

  • 类的实例变量和静态变量称为类属变量(class's variavble,常称为类变量)数据域(data field)
    定义在方法内部的变量称为局部变量。
  • 类属变量的作用域是整个类,局部变量的作用域是方法体内。
  • 如果局部变量和一个类属变量具有相同的名字,那么局部变量优先,同名的类属变量将会被隐藏。(就近原则)

this关键字

有时需要在方法中引用类属的隐藏变量(hidden variable)

  • 隐藏的静态变量可以通过“类名.静态变量”的方式引用。隐藏的实例变量需要使用关键字this来引用。

对象数组

数组中的元素可以为对象,要初始化对象数组,可以使用for循环。

1
2
3
for(int i=0; i < 10; i++) {
Objects[i] = new Object();
}

类的抽象和封装

  • 类抽象(class abstraction)是将类的实现和使用分离。类的创建者提供了类的描述,让使用者明白如何使用类。从类外可以访问的方法和数据域的全体,以及对这些成员如何使用的描述,合称为类的合约(class's contract)
  • 类的封装(class encapsulation)是将类的实现细节包装好,对用户隐藏起来,用户不需要知道如何实现的,仅需要知道如何使用即可。

内部类

  • 内部类(inner class)或者叫嵌入类(nested class),是一种在其他类的内部定义的类。
  • 内部类可以引用包含在它的外部类中的数据和方法。
  • 内部类只是用来支持其外部类的工作。
  • 内部类可以声明为public、protected或private,其意义与用在类的其他成员上相同。
  • 内部类可以声明为静态的static。可以使用外部类的类名来访问静态的内部类,静态内部类不能访问外部类的非静态成员。
  • 从另外的类中创建内部类的对象:

    • 如果内部类是非静态的,必须先创建外部类的实例,然后使用如下语法:

      1
      外部类.内部类 内部类对象名 = 外部类对象.new 内部类();
    • 如果内部类是静态的,使用如下语法:

      1
      外部类.内部类 内部类对象名 = new 外部类对象.内部类();

复习小结

  • 在面向过程程序设计语言中,数据和方法是分离的,但是在面向对象语言中,数据和方法定义在同一个类当中。
  • 引用型数据的默认值是null,数值型的默认值是0,boolean型的默认值是false,char型的默认值是‘\u0000’
  • 通过引用变量引用一个对象之前,必须先创建该对象。如果引用一个没有创建的对象,会引起运行错误NullPointerException
  • 通过数据域的封装,原类中的数据不会被改变,仅在外部类调用时临时修改。
  • 如何判断一个变量或方法定义为实例的还是静态的?
    如果一个变量或方法依赖于类的具体实例,应该定义为实例变量或实例方法。如果一个变量或方法不依赖羽类的具体实例,就该定义为静态变量或静态方法。
  • 如何在内存中区分对象和类?
    • 类是静态的概念,位于代码区
    • 对象是new出来的,位于堆内存。类的每个成员变量在不同的对象中都有不同的值(除了静态变量),而方法只有一份,执行的时候才占用内存。
      堆内存是程序运行时动态分配的内存。
  • 非静态方法是依据不同的对象进行调用。
  • 静态成员变量存在于data seg区。

编程练习

习题6.1 6.3 6.5 6.7 6.8 6.11 6.12 6.13源代码见我的Github: chapter6



本文章首发www.whtis.com,转载请注明出处


如果觉得这篇文章还有用的话,请我喝杯饮料呗~~