第03周 预习、实验与作业:面向对象入门2与类的识别
1. 什么样的方法应该用static修饰?不用static修饰的方法往往具有什么特性?
-
应该使用
static
修饰的方法(静态方法):- 工具方法: 不依赖于特定对象的状态,仅通过参数就能完成特定功能的方法A。
- 工厂方法: 用于创建并返回类的实例。
- 辅助方法: 在类内部使用,用于协助其他方法完成功能,但其本身不操作实例变量。通常声明为
private static
。 - 访问或修改静态变量: 因为静态变量属于类,所以操作它的方法通常也设为静态的(除非有特殊设计考虑)。
- 无需对象上下文的方法: 如果一个方法的功能是自包含的,不需要访问对象的属性(非静态字段),那么它就可以考虑设计为静态方法。
-
不用
static
修饰的方法(实例方法/非静态方法)的特性:- 依赖于对象的状态: 它们必须通过类的具体实例来调用,并且可以直接访问和修改该实例的非静态属性(实例变量)。
- 代表对象的行为: 这些方法定义了对象能做什么,是对象行为的体现。
- 多态性: 实例方法可以被重写,是实现面向对象中多态特性的基础。而静态方法不能被重写(只能被隐藏)。
Student的getName应该用static修饰吗?
不应该。
因为getName()
方法的作用是获取某个特定学生对象的姓名。姓名(name
)通常是Student
类的一个实例变量(非静态属性)。每个Student
对象的name
值都可能不同。因此,getName()
方法必须依赖于一个具体的Student
实例才能工作,它不是一个与类相关、而与实例无关的方法。
如果将其设为static
,调用就需要写成Student.getName()
,这暗示着“获取学生类的名字”,而不是“获取某个学生的名字”,这在语义上是错误的。
3. 购物车案例中,使用了什么方法将问题描述中的类、方法、属性找出来?方法与属性到底属于哪个类,要怎么判定呢?
-
方法: 通常使用名词分析法来寻找类,使用职责驱动设计或动词分析法来寻找方法和属性。
- 寻找类: 阅读问题描述,找出其中的名词或名词性短语。这些往往是潜在的类。例如,“用户”、“商品”、“购物车”、“订单”、“订单项”等。
- 寻找属性: 分析每个类,找出描述其特征或状态的名词。例如,“商品”类可能有“商品ID”、“名称”、“价格”、“库存”等属性。“购物车”类可能有“所属用户”、“创建时间”等属性。
- 寻找方法: 分析每个类需要提供哪些行为或功能,找出其中的动词。例如,用户能“登录”、“注册”;购物车能“添加商品”、“删除商品”、“修改数量”、“结算”;商品能“被查询”等。
-
方法与属性到底属于哪个类,要怎么判定呢?
- 基本原则:信息专家模式。将职责(方法或属性)分配给拥有完成该职责所需信息的那个类。
- 判定属性归属: 问“这个信息是描述谁的?”。例如,“价格”是描述“商品”的,所以它属于
Product
类。“购买数量”不是商品固有的属性,而是用户在购物车中针对某商品的行为结果,所以它属于连接商品和购物车的“中间类”——CartItem
(购物车项)。 - 判定方法归属: 问“谁最拥有完成这个方法所需的主要信息?”或“这个方法操作谁的数据?”。
addProduct(Product p, int quantity)
方法:它需要操作购物车内部的商品列表,所以它应该属于ShoppingCart
类。calculateTotalPrice()
方法:计算总价需要遍历购物车中的所有商品项(CartItem
),并获取每个商品项的价格和数量进行计算。ShoppingCart
拥有所有CartItem
的集合,所以这个方法属于ShoppingCart
类。
4. 一个项目中有很多类。怎样才能避免你项目中的类与别人编写的类同名呢?项目中类各种各样要怎么管理这些代码呢?举例说明。
-
避免类同名: 使用 包(Package)。
- 包是一种命名空间机制,它将相关的类组织在一起,并提供了唯一的类名标识。完整的类名是包名 + 类名(如
java.util.ArrayList
),只要包名不同,即使类名相同也被视为不同的类。 - 如何确保包名唯一? 行业惯例是使用公司或组织的互联网域名倒序作为包的前缀。例如,阿里巴巴的域名是
alibaba.com
,其包名可能就是com.alibaba.xxx
。个人开发者可以使用me.[你的名字].xxx
或io.[github用户名].xxx
。
- 包是一种命名空间机制,它将相关的类组织在一起,并提供了唯一的类名标识。完整的类名是包名 + 类名(如
-
管理代码:
- 使用包按功能/模块分层组织: 将功能相近、业务相关的类放在同一个包或子包下。
- 遵循Maven/Gradle等标准目录结构: 这些构建工具规定了源代码、资源文件、测试代码的存放位置,使得项目结构清晰统一。
src/main/java
:存放项目主要Java源代码(按包结构组织)。src/main/resources
:存放配置文件、静态资源等。src/test/java
:存放测试代码。
- 使用版本控制系统(如Git):管理代码的历史版本和团队协作。
- 使用IDE(集成开发环境):如IntelliJ IDEA或Eclipse,它们提供了强大的包视图、文件树、导航和重构功能,极大方便了代码管理。
-
举例:
一个电商项目可能包含以下包结构:com.example.mall
:主包com.example.mall.entity
/domain
/model
:存放实体类,如User
,Product
,Order
。com.example.mall.dao
/repository
:存放数据访问层接口和实现,负责与数据库交互。com.example.mall.service
:存放业务逻辑层接口和实现。com.example.mall.controller
:存放Web控制器,处理HTTP请求。com.example.mall.util
:存放工具类,如StringUtils
,DateUtils
。com.example.mall.config
:存放配置类。
这样,即使有另一个项目也定义了
User
类,只要它们的包名(如com.othercompany.xxx
)不同,就不会产生冲突。
5. 阅读《阿里巴巴Java开发手册》,写出至少7条Java编程规范。
- 变量命名:【强制】 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
反例:_name / __name / $name / name_ / name$ / name__
- 类命名:【强制】 类名使用
UpperCamelCase
(大驼峰)风格,但以下情形例外:DO / BO / DTO / VO / AO / PO / UID 等。正例:UserDAO
- 方法命名:【强制】 方法名、参数名、成员变量、局部变量都统一使用
lowerCamelCase
(小驼峰)风格。正例:localValue / getHttpMessage()
- 常量命名:【强制】 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
正例:MAX_STOCK_COUNT
- 包命名:【强制】 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式。
正例:com.alibaba.ai.util
- 代码格式:【强制】 如果是大括号内为空,则简洁地写成
{}
即可,不需要换行;如果是非空代码块,则左大括号前不换行,后换行。右大括号前换行,后还有else
等代码则不换行;表示终止的右大括号后必须换行。 - OOP规约:【强制】 所有的覆写方法,必须加
@Override
注解。说明:
@Override是编译器校验的有效手段,可以确保方法覆写正确。
- OOP规约:【强制】 相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用
Object
。反例:public void listUsers(String... ids) {...}
可变参数必须放置在参数列表的最后。