第4章 对象与类总结

4.1 面向对象程序设计概述(面向对象与面向方法)
面向对象的程序,由对象组成,对象包含特定的功能。不关心对象的具体实现,满足用户的需求。数据在先(对象),算法在后(对象拥有的功能)

面向方法通过算法解决问题。算法在先,数据在后

4 . 1.1 类(封装)

类,实例,实例域,方法

封装:是将数据和行为组合在一个包中,对对象的使用者隐藏数据实现细节。程序仅通过对象的方法与对象数据进行交互。

4 . 1.2 对 象

对象的3个重要特性(了解)
1.行为,方法
2.状态,施加方法,对象如何响应
3.标识,区别不同对象

4.1.4 类之间的关系
1.依赖,“uses a”,一个类的方法使用了另一个类的对象(耦合
2.聚合,“has a”,包含
3.继承,“is a”,特殊与一般

4.2 使用预定义类
4 . 2.1 对象与对象变量
对象和对象变量的区别
对象变量不是一个对象,它可以引用一个对象。在引用对象后,才能调用对象的方法,否则编译错误。对象变量的值都是对存储在另一个地方的一个对象的引用

4.2.2 Java 类库中的 LocalDate 类
表示时间点的 Date 类;日历表示法的 LocalDate 类

4.2.3 更改器方法与访器方法

只访问对象而不修改对象的方法,访问器方法(getXxx)
访问对象并修改对象的方法,更改器方法(setXxx)

4.3 用户修改对象
4.3.1 Employee 类
类定义(实例域、构造、方法)

源文件名必须与 public 类的名字相匹配。在一个源文件中, 只能有一个公有类

4.3.3 剖析 Employee 类

关键字 private 确保只有 Employee 类自身的方法能够访问这些实例域, 而其他类的方法不能
够读写这些域。

public 修饰数据域允许程序中的任何方法对其进行读取和修改, 这就完全破坏了封装。

4.3.4 从构造器开始

  • 构造器与类同名
  • 构造器没有返回值
  • 构造器总是伴随着 new 操作一起调用

不要在构造器中定义与实例域重名的局部变量(用this解决)

4.3.5 隐式参数与显式参数

隐式参数(方法调用的目标或接收者):方法名前的对象。在方法中使用,但没有写在方法参数中也没有在方法体内声明的变量。
显式参数:方法名后括号中的数值
在每个方法中this表示隐式参数,解决实例域与局部变量的重名

4 . 3.6 封装的优点

设置或获取实例域的值需要三项

  • 一个私有数据域,保证更改阈值发生在本类。
  • 一个公有域访问器
  • 一个公有域更改器

与提供一个简单的公有数据域相比的好处
1.可以更改内部实现,除了本类的方法外,不影响其他代码
2.更改器可以执行错误检查。判断域值是否在合理的范围

警告:不要编写返回引用可变对象的访问器方法
***若访问器需要返回一个可变对象的引用可以自动改变对象的私有状态,破坏封装性),应该对他进行克隆clone

如果希望 copy 是一个新对象,它的初始状态与 original 相同, 但是之后它们各自会有自己不同的状态, 这种情况下就可以使用 clone 方法。

补充:引用拷贝、浅拷贝、深拷贝区别

1.引用拷贝(给对象起一个新名字),原对象与拷贝对象完全共享数据

2.浅拷贝(在堆中创建一个新对象,若对象的内部属性是引用类型,只拷贝该属性的地址,拷贝对象和原对象共用同一个内部对象),原对象与拷贝对象中的内部引用类型的属性共享

3.深拷贝(在堆中创建一个新对象,若对象的内部属性是引用类型,也拷贝该对象的内部属性),不共享

4.3.8 私有方法
只要方法是私有的,它不会被外部的其他类操作调用,可以将其删去。
4.3.9 final 实例域
final 修饰符大都应用于基本 (primitive) 类型域,或不可变(immutable) 类的域(如果类
中的每个方法都不会改变其对象, 这种类就是不可变的类

final修饰可变的类型变量,表示变量中的对象引用不会指向其他对象,但当前对象内容可以更改

4.4 静态域与静态方法

4 . 4.1 静态域
每一个对象都有一个自己的 实例域, 但这个类的所有实例将共享一个 静态域。静态域属于类。

成员变量实例变量,无static修饰,属于对象,对象.调用,生命周期对象。静态变量(有static修饰,属于类,类名.调用,生命周期方法区加载类的字节码))与局部变量区别

  1. 类中位置,成员变量类中方法外,局部变量方法或代码块中,
  2. 内存中位置,静态变量属于类,实例变量属于对象,对象在堆中。局部变量在栈中。
  3. 生命周期,静态变量,当方法区加载类的字节码,属于类,实例变量生命周期对象,局部变量属于方法
  4. 默认值,成员变量自动以类型的默认值而赋值

4.4.2 静态常量

采用 Math.PI 形式的常量,另一个多次出现的静态常量是 System.out

由于每个类对象都可以对公有域进行修改, 所以,最好不要将域设计为 public。然而, 公有常量(即 final 域)却没问题。 因为 out 被声明为 final, 所以,不允许再将其他打印流陚给它

注释:System 类有一个 setOut 方法, 它可以将 System.out 设置为不同的流。setOut 方法是一个本地方法, 而不是用 Java 语言实现的。 本地方法可以绕过 Java 语言的存取控制机制

4.4.3 静态方法
静态方法不能访问实例域, 因为它不能操作对象

在下面两种情况下使用静态方法:
•一 方法不需要访问对象状态,其所需参数都是通过显式参数提供(例如: Math.pow (10)) 
•一个方法只需要访问类的静态域(例如:Employee.getNextld

4.4.4 工厂方法(什么是工厂方法,怎么做??)

LocalDate 和 NumberFormat 的类使用静态工厂方法 来构造对象
为什么 NumberFormat 类不利用构造器构造对象?

  • 无法命名构造器。
  • 当使用构造器时,无法改变所构造的对象类型

4.4.5 main 方法
每一个类可以有一个 main 方法。常用于对类进行单元测试

4.5 方法参数
1.按值调用:方法接收的是调用者提供的

2.按引用调用: 方法接收的是调用者提供的变量地址(c++中??)

Java 程序设计语言总是采用按值调用。也就是说, 方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。

java中方法参数使用总结(按值调用,方法参数是原值的拷贝)

  1. 不能改基本数据类型的参数
  2. 可改对象参数的状态
  3. 不能让对象参数引用一个新的对象

4 . 6 对 象 构 造

4.6.1 重载
如果多个方法(比如, StringBuilder 构造器方法)有相同的名字、 不同的参数便产生了重载。编译器必须挑选出具体执行哪个方法,重载解析(了解)

要完整地描述一个方法,需要指出方法名以及参数类型,这叫做方法的签名。返回值类型不是方法签名的一部分(了解)
4.6.2 默认域初始化
如果在构造器中没有显式地给域赋予初值,那么就会被自动地赋为默认值数值为 0、布尔值为 false、 对象引用为 null

4.6.3 无参数的构造器
仅当类没有提供任何构造器的时候, 系统才会提供一个默认的构造器

4.6.4 显式域初始化
在执行构造器之前,先执行赋值操作
4 . 6.5 参数名
this 指示隐式参数, 也就是所构造的对象。解决实例域与局部变量重名

4.6.6 调用另一个构造器
如果构造器的第一个语句形如 this(...), 这个构造器将调用同一个类的另一个构造器

好处:对公共的构造器代码部分只编写一次

4.6.7 初始化块
 初始化数据域三种

1.在构造器中设置值

2.在声明中赋值

3.初始化块,只要构造类的对象,这些块就会被执行先运行初始化块,然后才运行构造器的主体部分

调用构造器的具体处理步骤:

1) 所有数据域被初始化为默认值(0、false 或 null。

2 ) 按照在类声明中出现的次序,  依次执行所有域初始化语句和初始化块

3)执行构造方法

静态的初始化块
类第一次加载的时候, 将会进行静态域的初始化。与实例域一样,除非将它们显式地
设置成其他值, 否则默认的初始值是 0、 false 或 null

默认初始代码块,显示初始化语句、构造执行顺序总结:

1.使用static关键字定义的代码块,一般用于初始化静态成员属性静态代码块(属于类)不管生成多少个对象,其只会执行一次且是最先执行的,但执行一个子类时,最先执行其顶层父类的静态初始化

2.本地初始化与普通代码块初始化属于对象书写的先后顺序,写在前面的先执行,每次创建一个子对象时,都需先执行最顶层父类的初始化,构造器

3.构造方法初始化。

4.6.8 对象析构与 finalize 方法
由于 Java 有自动的垃圾回收器,不需要人工回收内存, 所以 Java 不支持析构器
某些对象使用了内存之外的其他资源finalize 方法将在垃圾回收器清除对象之前调用

4 . 7 包
使用包( package ) 将类组织起来,确保类名的唯一性

公司的因特网域名以逆序的形式作为包名,并且对于不同的项目使用不同的子包
所有标准的Java 包都处于java 和javax 包层次中。

4.7.1 类的导入
一个类可以使用所属包中的所有类, 以及其他包中的公有类
import 语句导人一个特定的类或者整个包。import 语句应该位于源文件的顶部
(但位于 package 语句的后面)

注意点:

  1. 只能使用星号(*) 导入一个包, 而不能使用 import java.* 或import java.*.* 导入以 java 为前缀的所有包。
  2. 编译器无法确定程序使用的是哪一个 Date 类(哪个包下的Date类)。可以采用一个特定类的import 语句来
  3. 如果这两个 Date 类都需要使用, 又该怎么办呢? 答案是,在每个类名的前面加上完整的包名

4 . 7.2 静态导入
import static java.lang.System.*;

就可以使用 System 类的静态方法和静态域,而不必加类名前缀

导入特定的方法或域:
import static java.lang.System.out

4 . 7.3 将类放入包中
类放人包中, 就必须将包的名字放在源文件的开头

警告:编译器在编译源文件时不检查目录结构,编译不报错。如果包与目录不匹配, 虚拟机就找不到类 
4.7.4 包作用域

  1. 标记为 public 的部分可以被任意的类使用
  2. protected ,同一包,子孙类
  3. 如果没有指定 public 或 private(默认, 这 个 部分(类、方法或变量)可以被同一个包中的所有方法访问。
  4. 标记为 private 的部分只能被定义它们的类(本类使用。

4.10 类设计技巧

  1. 数据私有
  2. 数据显示初始化。Java 不对局部变量进行初始化, 但是会对对象的实例域进行初始化。提供默认值, 也可以是在所有构造器中设置默认值
  3. 不要在类中使用过多的基本类型
  4. 不是所有的域都需要独立的域访问器和域更改器
  5. 职责过多的类进行分解
  6. 类名和方法名要能够体现它们的职责(名词,形容词+名词,动名词,访问器方法getXxx,更改器方法setXxx)
  7. 优先使用不可变的类(没有方法能修改对象的状态)。对于可变对象,如果多个线程试图同时更新一个对象, 就会发生并发更改线程不安全。
     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值