查看“核心技术:对象与类”的源代码
←
核心技术:对象与类
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:JavaCore]] == oop == <pre> 面向对象的程序时由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。 </pre> # 面向对象: # 面向过程: # 面向切面: [[File:面向过程与面向对象.png|400px]] === 类 与 对象 === # 类是构造对象的模板或蓝图,对象是类的实例化 # 由类构造(construct)对象的过程称为创建类的实例(instance) # 封装(encapsulation,有时称为数据隐藏):将数据(实例域,instance field)和行为(方法,用于操纵数据)组合在一个包中,并对对象的使用者隐藏了数据的实现方式 # 对象的实例域的几个就是这个对象的当前状态(state) # 通过扩展一个类来建立另一个类的过程称为继承(inheritance) * “Object”是所有类的超类 * 对象状态的改变必须通过调用方法实现(封装的意义) * 开发过程中,分析问题中的名词对应着类和类的实例域,动词对应着类的方法; * 对象的封装应该实现: *: 一个私有的数据与; *: 一个公有的域访问器方法; *: 一个共有的域更改器方法; === 类之间的关系 === # 依赖(“uses-a”):一个类的方法操纵另一个类的对象 # 聚合(“has-a”):一个类中包含另一个类的对象 # 继承(“is-a”):一个类由另一个类扩展而来 [[File:类关系的UML符号.png|800px]] ==== 实例(UML)==== ===== 关联(Association) ===== # 单向关联: #: [[File:单向关联.png|400px]] # 双向关联: #: [[File:双向关联.png|400px]] # 自身关联: #: [[File:自身关联.png|400px]] # 多维关联: #: [[File:多维关联.png|400px]] ===== 聚合(Aggregation) ===== :[[File:聚合(Aggregation).png|400px]] ===== 组合(复合,Composition) ===== :[[File:组合(复合,Composition).png|400px]] * 聚合的成员可独立,复合的成员必须依赖于整体才有意义 ===== 泛化(Generalization) ===== 泛化指的是类与类之间的继承关系和类与接口之间的实现关系。 # 继承: #: [[File:泛化(Generalization):继承.png|400px]] # 实现: #: [[File:泛化(Generalization):实现.png|400px]] == 使用预定义类 == * 并非所有的类都具有面向对象特征;(如,Math、Date类,只封装了功能,没有也不需要隐藏数据) === 对象与对象变量 === # 构造器(constructor)是一种特殊的方法,用来构造并初始化对象; # 构造器的名字应该与类名相同; # 一个对象变量并不包含一个对象,而是引用一个对象; # 局部变量不会自动地初始化为null,必须通过new或将其设置为null来进行初始化; * Java中要获得对象的完整拷贝,应该使用“clone”方法; === Date 与 LocalDate 类 === <pre> Date类的时间,使用一个固定时间点(纪元,epoch)的毫秒数(可正可负)来表示的; 纪元:UTC时间 1970年1月1日 00:00:00 UTC(Coordinated Universal Time),与GMT(Greenwich Mean Time,格林威治时间)一样。 </pre> Date 类提供的日期处理并没有太大的用途。如“December 31, 1999, 23:59:59”这样的时间只是阳历的固有习惯,虽然遵循了世界上大多数地区使用的阳历表示法。但是,统一时间点采用中国的农历或希伯来的阴历表示就很不一样。<br/> 类库设计者决定将保存时间与给时间点命名分开,所以标准Java类库分别包含了两个类: # 一个是用来表示时间点的'''Date'''类 # 另一个是用来表示大家熟悉的日历表示法的'''LocalDate'''类 *(Java SE 8 引入了另一些类来处理日期和时间的不同方面) 将时间与日历分开就是一种很好的面向对象设计。 关于LocalDate的使用: * 不要使用构造器来构造LocalDate的对象,而应该使用静态工厂方法; # 用当前时间构造一个新对象: #: <syntaxhighlight lang="java"> LocalDate.now() </syntaxhighlight> # 提供年月日来构造一个特定时间的对象: #: <syntaxhighlight lang="java"> LocalDate.of(1999, 12, 31) </syntaxhighlight> # 将构造的对象保存在一个对象变量中: #: <syntaxhighlight lang="java"> LocalDate newYearEve = LocalDate.of(1999, 12, 31); </syntaxhighlight> # 有了LocalDate对象,就可以使用getYear、getMonthValue、getDayOfMonth来得到年、月、日,以及其他操纵日历的方法: #: <syntaxhighlight lang="java"> int year = newYearEve.getYear(); ... </syntaxhighlight> * '''不应该使用Date类中诸如getYear、getMonth、getDay等方法'''。 * 调用后会修改对象状态的方法是“更改器方法”,只访问对象而不修改对象的方法是“访问器方法” == 用户自定义类 == * 构造器总是伴随 new 操作符的执行被调用;而不能对一个已经存在的对象调用构造器来重设实例域。 * 不应该在构造器中定义域实例域重名的局部变量 构造器: # 与类同名 # 每个类可以有一个以上的构造器 # 构造器可以有0、1或多个参数 # 构造器没有返回值 # 构造器总是伴随着 new 操作一起调用 == 静态域与静态方法 == === 静态变量 === 静态域、类域,即静态变量; 如: <syntaxhighlight lang="java"> public static int nextId = 1; </syntaxhighlight> * 类的所有实例将会共享一个静态域 === 静态常量 === # 静态:static # 常量:final <syntaxhighlight lang="java"> public static final double PI = 3.1415926; </syntaxhighlight> * 对于 public: *# 不应该把域设置为 public,因为每个类对象都可以对共有域进行修改; *# 但将公用常量设置为 public 没问题,因为被 final修饰,不会被更改; * 关于final: *: “System”类中有“setOut”方法,可以将“System.out”,设置为不同的流(“public final static PrintStream out = null;”) *: 此处可以修改 final 变量 out的值,是因为“setOut”调用了一个“Native”方法(“private static native void setOut0(){}”),可以绕过Java的存取控制机制。 === 静态方法 === # 静态方法可以使用类名、类的实例调用; # 静态方法只能访问静态域,而不能访问实例域,即不能操作对象; * 关于静态方法main:每个类可以有一个main方法,用作单元测试 === 工厂方法 === 静态方法的另一种常见用途:类似 LocalDate 和 NumberFormat 的类使用静态工厂方法来构造对象。 == 方法参数 == # 按值调用(“call by value”):表示方法接受的是调用者提供的值。 # 按引用调用(“call by reference”):表示方法接收的是调用者提供的变量地址。 # 一个方法可以修改传递引用锁对应的变量值,而不能修改值传递调用所对眼的变量值 '''Java 总是采用 <div><span style="color:Chocolate; font-weight:bold; font-size:150%;">按值调用</span></div>'''!!! 即,方法得到的是所有参数值的一个拷贝,并不能修改传递值给它的变量的内容。 Java中方法参数的使用情况: # 一个方法'''不能修改一个基本数据类型的参数'''; # 一个方法'''可以更改一个对象参数的状态'''; # 一个方法'''不能让对象参数引用一个新的对象'''; == 对象构造 == === 重载 === * 重载(overloading):多个方法有相同的名字、不同的参数。如参数个数或类型不同的构造函数; * 方法的签名(signature):方法名以及参数类型(返回值不是方法签名的一部分); === 默认域初始化 === 如果在构造器中没有显示地给域赋予初值,那么就会被自动地赋为默认值(数值为0,布尔值为false,对象引用为null)。 === 显示域初始化 === 在执行构造器之前,先执行赋值操作(当一个类的所有构造器都希望把相同的值赋予某个特定的实例域时,十分有用)。 <syntaxhighlight lang="java"> class Employee { private static int nextId; private int id = assingId(); ... private static int assingId() { int r = nextId; nextId++; return r; } } </syntaxhighlight> === 无参构造器 === * 当类没有提供任何构造器时,系统会提供一个默认的无参构造器。 *: 这个构造器将所有的实例域设置为默认值; * 当类中提供了至少一个构造器,但未提供无参构造器时,如果构造对象没有提供参数会被视为不合法。 === 调用另一个构造器 === 如果构造器的第一个语句形如“this(...)”,则构造器将会调用同一个类的另一个构造器: <syntaxhighlight lang="java"> public Employee(double s) { this("Employee #" + nextId, s); nextId++; } </syntaxhighlight> * 这样公共的构造器代码部分只编写一次即可。 === 初始化块 === 初始化数域的方法: # 在构造器中设置值 # 在声明中赋值 # 初始化块 <syntaxhighlight lang="java"> class Employee { private static int nextid; private int id; private String name; private double salary; //初始化块 { id = nextId; nextId++; } public Employee(String n, double s) { name = n; salary = s; } public Employee() { name = ""; s = 0; } ... } </syntaxhighlight> * 首先运行初始化块,然后再运行构造器的主体部分 即,无论使用哪个构造器构造对象,id域都在对象初始化块中被初始化。 ==== 【关于:Java类对象初始化顺序】 ==== # 父:静态变量 #: 静态初始化块 # 子:静态变量 #: 静态初始化块 # main # 父:变量 #: 初始化块 #: 构造器 # 子:变量 #: 初始化块 #: 构造器 * 先初始化静态内容 * 先初始化父类的内容 * 变量先于初始块,初始快先于构造器 === 对象析构 与 finalize方法 === # 面向过程的程序设计语言,有显示的析构刚嘎,如C++ # 而Java中有GC,不需要手动回收内存,所以Java不支持析构器 但,当某些对象使用了内存以外的资源(如文件等),这种情况下当资源不再需要时,将其回收和再利用将十分重要。<br/> 可以为任何一个类添加'''finalize'''方法,用于回收资源: * finalize 将在垃圾回收器清楚对象之前调用; * 但是不能知道调用的时间,所以不应该依赖于它进行资源回收; == 包 == Java中使用包(package)来将类组织起来,用于确定类名的唯一性(不同包下的同名类不冲突)。 * 所有标准的Java包,都处于java(核心)和javax(扩展)包层次中; * 嵌套的包之间没有任何关系,如“java.util”与“java.util.jar” === 类的导入 === 一个类可以使用所属包中的所有类,以及其他包中的公有类(pubic class)。 使用其他包的公有类: # <syntaxhighlight lang="java"> java.time.LocalDate today = java.time.LocalDate.now(); </syntaxhighlight> # <syntaxhighlight lang="java"> //源文件头部 import java.util.*; //代码中 LocalDate today = LocalDate.now(); </syntaxhighlight> * 只能使用“*”导入一个包,而不能使用“import java.*”或“import java.*.*”来导入所有java前缀的包; === 静态导入 === import 导入静态方法和静态域: <syntaxhighlight lang="java"> // 源文件头部 import static java.lang.System.*; // 或导入特定的方法或域“import static java.lang.System.out”、“import static java.lang.System.exit” //代码中,可以使用System类的静态方法和静态域,而不必加类名前缀 out.println("Goodbyr, world!"); // System.out exit(0); // System.exit </syntaxhighlight> === 将类放入包中 === 要将类放入包中,则必须将包的名字放在源文件的开头: <syntaxhighlight lang="java"> package com.eijux.wiki; public class Wikioe { ... } </syntaxhighlight> === 包作用域 === 包密封(package sealing):如果将一个包密封起来,就不能再向这个包添加类了。 == 类路径 == == 文档注释 ==
返回至“
核心技术:对象与类
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息