Java核心技术(三) —— 对象与类(1)

本文将对Java程序设计的对象和类进行深入详细介绍,主要涉及以下内容:

- 面向对象程序设计

- 如何创建标准Java类库中的类对象

- 如何编写自己的类


1、OOP概述

面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。在OOP中,不必关心对象的具体实现,只要能够满足用户的需求即可。

OOP中,数据是第一位的,然后再考虑操作数据的算法。

1.1 类

是构造对象的模板或蓝图,可以将类想象成制作小甜饼的切割机,将对象想象成小甜饼。由类构造对象的过程称为创建类的实例

(1)封装(有时称为数据隐藏),从形式上看,是将数据和行为组合在一个包中,并对对象的使用者隐藏了数据的实现方式。

(2)对象中的数据称为实例域,操纵数据的过程称为方法。对于每个特定的类实例都有一组特定的实例域值,这些值的集合就是这个对象的当前状态

(3)实现封装的关键在于绝对不能让类中的方法直接访问其他类的实例域,程序仅通过对象的方法与对象数据进行交互。

1.2 对象

使用OOP必须搞清楚对象的三个主要特性

- 对象的行为 —— 可以对对象施加哪些操作,即方法

- 对象的状态 —— 当施加那些方法时,对象如何响应

- 对象的表示 —— 如何辨别具有相同行为与状态的不同对象

1.3 类之间的关系

在类之间最常见的关系有

- 依赖(uses-a) —— 如果一个类的方法操作另一个类的对象,就说一个类依赖于另一个类

- 聚合(has-a) —— 实际即包含关系

- 继承(is-a) —— 用来表示特殊与一般关系

2、使用预定义类

2.1 对象与对象变量

要想使用对象,就必须首先构造对象,并制定初始状态,然后再对对象应用方法。

(1)在Java中,使用构造器来构造新的实例,并在构造器前面加new操作符。

构造器实际是一个特殊的方法。构造器的名字应该与类的名字相同。

如构造一个Data类的对象并保存在一个变量中的例子

Data birthday = new Date();

(2)由上面例子可以看到单独new Data()是构造一个对象,单独Data birthday是定义一个对象变量,对象与对象变量之间区别很大。

对象变量不是一个对象,实际上也没有引用对象,因而,是不能将任何类Date的方法应用于这个变量的,但对象就可以。

因此

Data birthday;

s = birthday.toString();

是错的,

System.out.println(new Data());

String s = new Data().toString();

以及

date birthday;

birthday = new Date();

String s = birthday.toString();

都是对的。

(3)因此,需要认识到,Java中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。new操作符的返回值也是一个引用,即

Data birth = new Data();

中等号右侧的表达式构造一个Date类型的对象,且它的值是对新创建对象的引用,这个引用存储在变量birth中。

2.2 GregorianCalendar类

标准Java类库分别包含了两个类:前面使用过的表示时间点的Date类,还有用来表示日历表示法的GregorianCalendar类。虽然后者还扩展了以更加通用的Calendar类,描述了日历的一般特性。

虽然Date类除了前面使用的方法还有一些其他方法,但这些方法在未来类库版本中有可能删去,已被标记为不鼓励使用,仍然使用有可能在编译时出现警告。

GregorianCalendar类包含的方法要比Date类多得多。

2.3 更改器方法与访问器方法

对实例域作出修改的方法称为更改器方法,仅访问实例域而不进行修改的方法称为访问器方法。

如上述日历的作用是提供某个时间点的年、月、日等信息,要想查询这些设置信息,应该使用GregorianCalendar类中的get方法,要想修改,则需用set和add等方法。

通常的习惯是在访问器方法名前面加上前缀get,在更改方法名前面加上前缀set。

3、用户自定义类

下面我们来学习设计复杂应用程序所需的各种主力类,通常,这些类没有main方法,却有自己的实例域和实例方法。

要想创建一个完整的程序,应该将若干类组合在一起,其中只有一个类有main方法。

Java中,最简单的类定义形式为

下面,我们编写一个简单的Employee类,再进行详细讲解

import java.util.*;

/**
 * This program tests the Employee class.
 * @version 1.11 2004-02-19
 * @author Cay Horstmann
 */
public class EmployeeTest
{
   public static void main(String[] args)
   {
      // fill the staff array with three Employee objects
      Employee[] staff = new Employee[3];

      staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15);
      staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
      staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);

      // raise everyone‘s salary by 5%
      for (Employee e : staff)
         e.raiseSalary(5);

      // print out information about all Employee objects
      for (Employee e : staff)
         System.out.println("name=" + e.getName() + ",salary=" + e.getSalary() + ",hireDay="
               + e.getHireDay());
   }
}

class Employee
{
   private String name;
   private double salary;
   private Date hireDay;

   public Employee(String n, double s, int year, int month, int day)
   {
      name = n;
      salary = s;
      GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
      // GregorianCalendar uses 0 for January
      hireDay = calendar.getTime();
   }

   public String getName()
   {
      return name;
   }

   public double getSalary()
   {
      return salary;
   }

   public Date getHireDay()
   {
      return hireDay;
   }

   public void raiseSalary(double byPercent)
   {
      double raise = salary * byPercent / 100;
      salary += raise;
   }
}

(1)注意一个源文件中只能有一个public类,但可以有任意数目的非公有类,其中该源文件的文件名必须与该公有类的类名相同。

(2)上述源文件中包含了两个类,习惯上我们可以将每一个类放到一个单独的源文件中。编译时,最方便的方式是只键入

javac EmployeeTest.java

当编译器发现EmployeeTest.java使用了Employee类时就会自动查找名为Employee,class的文件,如果没有找到,再自动搜索Employee.java,在对其进行编译。而且如果Employee.java的版本较已有的Employee.class版本新,编译器就会自动重新编译这个文件。

(3)Employee类中包含的一个构造器四个方法均标记为public,表示任何类的任何方法均可以调用这些方法。

关键字private标记的三个实例域表示只有Employee类自身的方法可以访问这些实例域。

因此,非常不提倡使用public标记实例域,这将破坏封装。

3.1 关于构造器

从上述程序可以看到

(1)构造器与类同名

(2)每个类可以有一个以上的构造器

(3)构造器可以有0、1或多个参数

(3)构造器没有返回值

(4)构造器总是随着new操作仪器调用,而不能对一个已经存在的对象调用构造器来达到重新设置实例域的目的

(5)注意,不要在构造器钟定义与实例域重名的局部变量,如

   public Employee(String n, double s, int year, int month, int day)
   {
      String name = n; //Error!
      Double salary = s; //Error!
      GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
      // GregorianCalendar uses 0 for January
      hireDay = calendar.getTime();
   }

上述错误的程序在构造器中又声明了局部变量name和salary,这些变量只能在构造器内部访问,从而对同名的实例域形成了屏蔽,形成错误,注意这种错误很难检查出来,要注意!

3.2 隐式参数和显式参数

例如调用number.raiseSalary(5);中可以看到方法raiseSalary有两个参数:

隐式参数,即出现在方法名前的Employee类对象,number

显式参数,即位于方法名后面括号中的数值,5

在每一个方法中,关键在this表示隐式参数,如果需要,以这种方式来编写raiseSalary方法

   public void raiseSalary(double byPercent)
   {
      double raise = this.salary * byPercent / 100;
      this.salary += raise;
   }

可以培养这种编写风格,可以将实例域与局部变量明显区分开来。

3.3 封装的优点

上面程序中出现的前三个方法都是典型的访问器方法,由于其只返回实例域值,也称为域访问器。

但有些时候,需要获得或设置实例域的值,因此,应该提供以下三项内容

- 一个私有的数据域

- 一个公有的域访问器方法

- 一个公有的域更改器方法

这样显然比提供一个简单的公有数据域复杂,但也有显著优点

(1)可以改变内部实现,除了该类的方法之外,不会影响其他代码

(2)更改器方法可以执行错误检查,然而直接对域进行赋值将不会进行这些处理

注意不要编写返回引用可变对象的访问器方法。

3.4 基于类的访问权限

(1)一个方法可以访问所调用对象的私有数据

(2)一个方法也可以访问所属类的所有对象的私有数据

显然调用

if (harry.equals(boss)) …

中方法equals同时访问了harry和boss的私有域。

3.5 私有方法

有时可能希望讲一个计算代码划分为若干个独立的辅助方法,而这些辅助方法不应成为公有接口的一部分,因为它们往往与当前的实现机制非常紧密,或者需要一个特别的协议以及一个特别的调用次序。

此时,只需将关键字public改为private即可。

3.6 final实例域

使用关键字final定义实例域,那么构建对象时必须初始化这样的域。即必须确保在每一个构造器执行之后,这个域的值被设置,且在后面的操作中,不能再对它进行修改。

final修饰符一般应用于基本类型域,或者不可变类的域。其中,如果类中的每个方法都不会改变其对象,这种类就是不可变的类。

时间: 2024-11-07 21:59:33

Java核心技术(三) —— 对象与类(1)的相关文章

Java核心技术-4-对象与类

4 对象与类 4.1 面向对象程序设计概述 1 类 封装(数据隐藏):将数据和行为组合在一个包中,并对对象使用者隐藏数据的实现方式. 对象中的数据成为实例域,操纵数据的过程称为方法. 2 对象 对象的三个主要特性:对象的行为behavior,对象的状态state,对象标识identity.3 识别类 4 类之间的关系 依赖uses-a,一个类的方法操纵另一个类的对象 聚合has-a,一个类的对象(其数据域)包含另一个类的对象 继承is-a,类A扩展类B. 4.2 使用预定义类 1 对象与对象变量

java基础知识-对象和类

前言: 因为要准备Java面试,所有将java基础知识点重新复习一遍,主要笔记来源于菜鸟教程和java核心技术的书籍中,也有一些博客上的资料(这些只供我个人学习使用) Java 对象和类 对象:对象是类的一个实例,有状态和行为.例如,一条狗是一个对象,它的状态有:颜色.名字.品种:行为有:摇尾巴.叫.吃等. 类:类是一个模板,它描述一类对象的行为和状态. 下图中男孩女孩为类,而具体的每个人为该类的对象: 1.Java中的对象 现在让我们深入了解什么是对象.看看周围真实的世界,会发现身边有很多对象

java学习笔记(Core Java)4 对象与类

第四章 对象与类oop三个特征:对象的行为.状态.标识类之间关系:依赖,聚合,继承依赖:一个类的方法操纵另一个类的对象.(尽量减少这种耦合情况)聚合(has-a)一个类作为另一个类的变量而存在继承(is-a) 如果只声明一个类变量,而没有在堆空间中开辟没存,那么这个变量就不能调用类中的方法因为这个变量没有引用对象 !!一个对象的变量并没有实际包含一个对象,而仅仅引用了一个对象 Data data;等同于:Data *data; //它只代表一个指针,而不拥有对象数据 get/set 访问器 一个

java之常见对象-Object类

1.API概述 API(Application Programming Interface),应用程序编程接口. 编写一个机器人程序去控制机器人踢足球,程序就需要向机器人发出向前跑.向后跑.射门.抢球等各种命令,没有编过程序的人很难想象这样的程序如何编写.但是对于有经验的开发人员来说,知道机器人厂商一定会提供一些用于控制机器人的java类,这些类中定义好了操作机器人各种动作的方法.其实,这些java类就是机器人厂商提供给应用程序编程的接口,大家把这些类就称为应用程序编程接口. 2.java AP

新手学JAVA(三)----StringBuilder类

上一篇文章新手学JAVA(二)----String类与StringBuffer类的区别中了解到,String的值是不可变的,这就导致 每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间,StringBuffer是可变 类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象. StringBuffer类和StringBuilder类功能基本相似.算是两个双胞胎. 下面主要说两点 第一点  线程安全 StringBuffer  线程安全

Java 核心技术 第四章 类与对象

类:构造对象的模板和蓝图.由类构造对象的过程称为创建类的实例. 对象的特征: 对象的行为 对象的状态 对象的标识 类之间的关系: 依赖 聚合 继承 对象与对象变量: new Date() new GregorianCalendar() new GregorianCalendar(1999, 11, 31) new GregorianCalendar(1999, Calendar.DECEMBER, 31) new GregorianCalendar(1999, Calendar.DECEMBER

Java第二章----对象和类

从第一章到第二章整整隔了一个月的时间,这速度也是慢的无语了.因为这个月负责开发公司一个SaaS类型APP,忙的昏天暗地终于上线了,这才有时间写个博客.本章还是以概念为主,有点枯燥重在理解. 第一节:对象 名词解释 OOA-Object Oriented Analysis-面向对象分析 OOD-Object Oriented Design-面向对象设计 OOP-Object Oriented Programming-面向对象程序设计 面向对象基本特性 万物皆可为对象:任何一件事物都可以表示为程序中

浅谈java中的对象、类、与方法的重载

对象: 一切皆为对象. 对象包括两部分内容:属性(名词形容词),行为(动词). 对象和对象之间是有关系的: 派生,关联,依赖. 类: 对同一类别的众多对象的一种抽象. 类,还是用来生成对象的一种模板,对象是类的一种具体化的表现. 面向对象的三大特性:封装,继承,多态. ? 1 2 3 4 class 类名{ 访问修饰符 成员变量的定义; 访问修饰符 成员函数(方法)的定义; } 访问修改符:默认不写,private,public. private,私有.只能被当前class 类名{}中的代码访问

JAVA学习记录①——对象、类、属性、方法、构造方法的总结

对象——现实存在的手机(三星.苹果) 类——虚拟的手机(包含属性:5.0寸屏幕,2.1GHZCPU等,方法:能打电话,玩游戏) 属性:手机的配置(5.0寸屏幕,2.1GHZCPU) 方法:手机能做什么的(能打电话,玩游戏) 构造方法:用来给手机赋初值 具体展示在下面: /* * 文件一 * 这是类文件,用来保存手机的性质以及如何赋初值 * */ //这是类 public class Telphone { //这是属性,表示手机应该拥有什么 double screen; double cpu; /