Java编程中的Applet、JDBC与面向对象设计
1. Applet基础
Applet是一种可以通过
<applet>
标签嵌入网页并在网页浏览器中运行的Java程序。它继承自
JApplet
类,拥有强大的功能,具备操作声音和图像文件的方法。
Applet有四个生命周期阶段,分别是初始化(initialization)、启动(start)、停止(stop)和销毁(destroy),每个阶段会调用对应的生命周期方法,即
init()
、
start()
、
stop()
和
destroy()
。不过,Applet不一定要实现所有的生命周期方法。
init()
方法类似于构造函数,通常用于放置Applet状态初始化代码。如果需要,Applet也可以有构造函数,其中必须有一个无参构造函数。而清理代码则应放在
destroy()
方法中。
Applet在受限环境中运行,被视为不可信代码。一般来说,它无法访问本地文件系统,也不能发起或接收除提供它的计算机之外的任何计算机的网络连接。
可以使用
<param>
标签在HTML页面中嵌入Applet参数,通过
Applet
类的
getParameter()
方法获取参数值并在程序中使用,必要时可使用包装类将参数值字符串转换为基本类型值。
2. JDBC基础
JDBC(Java Database Connectivity)是一个允许Java程序访问数据源的API,它包含两个包:
java.sql
包包含JDBC核心API,
javax.sql
包包含JDBC可选包API。JDBC API主要由接口组成,这些接口必须由Java平台供应商实现,数据库供应商还需提供JDBC驱动类,以方便实现与他们数据库产品的JDBC连接。
MySQL是一种关系型数据库服务器。在使用JDBC连接MySQL数据库之前,需要安装MySQL、创建数据库、创建数据库表并建立必要的数据库访问权限。MySQL的访问控制主要通过位于
mysql
数据库中的五个表来管理,分别是
user
、
db
、
host
、
tables_priv
和
columns_priv
。在学习环境中可以忽略数据库安全问题以减轻复杂度,但在生产环境中必须高度重视。
使用JDBC的一般步骤如下:
1. 使用
Class.forName()
方法加载数据库供应商的JDBC驱动类。
2. 使用
DriverManager.getConnection()
方法建立与数据库的连接。
3. 使用连接对象创建
Statement
或
PreparedStatement
对象。
4. 使用
Statement
或
PreparedStatement
对象对数据库执行SQL语句。
5. 如果适用,操作返回的
ResultSet
对象中的数据。
处理简单查询时可使用JDBC
Statement
,为了提高效率和易用性,其他情况建议使用
PreparedStatement
。
3. 技能构建练习
以下是一系列有助于提升相关技能的练习:
1.
跟踪Applet生命周期阶段
:运行相关的
BasicApplet
程序,跟踪Applet的生命周期阶段。记录首次访问Applet网页、离开页面、点击页面刷新按钮和退出浏览器时的效果。打开两个浏览器窗口,访问
BasicApplet
页面,跟踪每个窗口文本区域打印的生命周期阶段消息,并尝试解释看到的现象。
2.
<object>
标签
:将相关的Applet示例从使用
<applet>
标签转换为使用
<object>
标签。
3.
API研究
:研究
java.sql
和
javax.sql
这两个JDBC包,列出并描述所有类、接口和异常,记录每个接口和类的方法、所需参数和返回值。
4.
定向学习
:拓展对结构化查询语言(SQL)的了解,获取一本SQL参考资料并阅读,比较MySQL对SQL的实现与SQL标准的差异,找出MySQL未实现的SQL语言特性(如果有)。
5.
Applet安全
:研究浏览器安全策略和签名Applet的使用。
6.
关系型数据库设计
:获取并阅读一本关于关系型数据库设计的书籍。
7.
正则表达式
:在员工培训管理系统的
EmployeeTrainingApplet
中,当前使用的两个对话框类未实现用户输入错误检查。学习Java对正则表达式的实现,并修改程序以使用正则表达式,确保只有可接受的数据被发送到数据库进行持久化。
8.
编程练习
:修改
Poetry
Applet,使其可以通过Applet参数设置画布和瓷砖颜色。
9.
编程练习
:修改员工培训管理系统,使用
JTable
显示员工和员工培训数据。
10.
JDBC RowSet
:研究JDBC RowSet,并修改员工培训管理系统以使用RowSets。
4. 建议项目
以下是一些具有实际应用价值的建议项目,可以帮助你将所学知识应用到实际开发中:
1.
库存照片数据库
:设计并实现一个应用程序,允许用户按不同类别(如主题、摄影师等)浏览和下载数字图像,使用RMI进行客户端 - 服务器通信,以MySQL作为数据库引擎。
2.
物业管理数据库
:设计并实现一个应用程序,让物业管理专业人员能够管理他们的物业。该应用程序应允许他们输入新管理的物业信息以及每个物业的一张或多张图片。新物业信息可能包括地址、卧室数量、浴室数量和其他相关描述元素、租金金额、业主和租户信息等。需要考虑业主可以拥有多个物业,租户可以租赁多个物业,允许用户根据搜索条件(如地址、邮政编码、卧室数量等)浏览可用物业。
3.
网络研究数据库
:设计并实现一个应用程序,允许你在进行网络研究时摄入感兴趣网站的URL链接和描述信息。
4.
个人图书馆管理系统
:设计并实现一个应用程序,让用户能够管理他们的个人图书馆藏书,无论藏书的媒介是什么。该应用程序应允许用户输入和操作每个物品的信息,并根据主题、作者、艺术家、ISBN等在数据库中搜索物品。
5.
家庭库存管理系统
:设计并实现一个应用程序,让用户能够管理他们的个人家庭库存。该应用程序应允许用户输入和操作每个物品的信息,包括原始成本、更换成本、描述、型号、品牌、位置等。
6.
在线医疗记录系统
:设计并实现一个应用程序,让医生能够输入和检索患者治疗信息。为简单起见,在本次练习中可将系统设计得简单一些。
7.
在线员工绩效评估系统
:设计并实现一个员工绩效评估系统。该应用程序应允许员工通过创建新评估并添加他们一年的输入和成就来启动评估过程。当他们“提交”评估时,评估应可供员工的主管查看,主管可以添加评论并提交给公司人力资源部门。
8.
在线简历提交系统
:设计并实现一个应用程序,让用户能够在线提交基于文本的简历。该应用程序应允许潜在员工用户将他们简历的ASCII版本粘贴到文本区域。当他们点击提交时,应用程序应处理文本区域并提取关键字,这些关键字可以与简历文本一起插入数据库。该应用程序应允许公司人员根据关键字搜索简历数据库以寻找潜在的招聘对象。
9.
全国性犯罪者跟踪数据库
:设计并实现一个全国性犯罪者登记和跟踪数据库,供执法人员使用,以监控相关人员并促进机构间的信息共享。
10.
全国手枪购买授权数据库
:设计并实现一个在线应用程序,用于确保客户确实有权利持有和携带手枪。客户的信息应提交到该应用程序,该应用程序将搜索犯罪历史数据库。如果匹配,则拒绝其购买权利。
5. 自我测试问题及答案
以下是一些自我测试问题及其答案,可帮助你巩固所学知识:
| 问题 | 答案 |
| — | — |
| 1. Applet与应用程序有何不同? | Applet可以在浏览器中运行。 |
| 2. 列出至少四个Applet安全限制。 | - 不能监听小于或等于1024的网络端口
- 不能注册或创建
URLStreamHandlerFactory
、
ContentHandlerFactory
或
SocketImplFactory
- 不能调用
System.exit()
或
Runtime.exit()
- 不能调用
Runtime.exec()
方法
- 不能使用
System
或
Runtime
类的
load()
或
loadLibrary()
方法动态加载库模块
- Applet创建的Swing窗口底部有警告
- 不能打印、访问剪贴板或访问系统事件队列
- 对某些系统属性的访问受限
- 不能创建或访问外部线程或线程组
- 加载类的能力有限
- 使用反射的能力有限 |
| 3. 列出并简要讨论Applet的四个生命周期状态及其相关的生命周期方法。 | 初始化(
init()
)、启动(
start()
)、停止(
stop()
)、销毁(
destroy()
) |
| 4. (判断对错)Applet可以发起与网络中任何计算机的网络连接,并接受来自任何计算机的传入网络连接。 | 错误 |
| 5. 列出并描述每个
<applet>
标签属性的用途。 |
<applet code = applet_class_name
width = width_in_pixels
height = height_in_pixels
[archive = jar_file_name, [jar_file_name],...]
[codebase = base_applet_uri]
[object = serialized_applet]
[alt = alternative_text]
[name = applet_name]
[align = applet_alignment]
[vspace = vertical_margin_space_in_pixels]
[ hspace = horizontal_margin_space_in_pixels] >
[<param name = parameter_name value = parameter_value>]
...
[alternative_text]
</applet>
|
| 6. 如何从HTML页面向Applet传递信息? | 通过Applet参数。 |
| 7. 列出并简要讨论在MySQL中创建数据库所需的一般步骤。 | 创建数据库,创建一个或多个表,为每个表定义列和表之间的关系,并使用MySQL权限表在数据库上建立所需的细粒度权限。 |
| 8. 列出并简要讨论在程序中使用JDBC所需的步骤。 | - 配置好的数据库(如表格、关系、访问权限等)
- 合适的数据库JDBC驱动类(由数据库供应商提供)
- 关系型数据库设计知识(如果访问关系型数据库)
- 要访问的数据库模式的知识
- SQL知识
- 使用JDBC API连接数据库的Java程序 |
| 9. 哪两个包包含JDBC类和接口? |
java.sql
,
javax.sql
|
| 10. 描述使用Applet相对于应用程序的至少一个好处。 | 比应用程序更容易分发。 |
| 11. Applet可以有哪种类型的构造函数? | 无参构造函数。 |
| 12. 在运行Applet之前必须编写哪些额外的代码? | 引用Applet代码的HTML页面。 |
| 13. JDBC
Statement
和
PreparedStatement
有什么区别? |
PreparedStatement
提前创建,带有变量占位符,并且是预编译的。 |
| 14.
PreparedStatement
中用作变量占位符的字符是什么? |
?
|
| 15. 描述一个你会选择使用
PreparedStatement
而不是
Statement
的场景。 | 当需要反复执行相同的语句,但变量值不同时。 |
6. 面向对象设计中的继承与组合
在面向对象设计和编程中,继承、接口、组合和多态是四个关键因素。继承和组合在代码复用方面各有特点,关于它们的使用存在不同的观点。
存在三个哲学阵营:
1.
组合主义者
:认为实现代码复用的唯一方式是通过组合设计,所有形式的继承作为复用机制都值得怀疑,应避免使用。
2.
继承主义者
:认为继承是一种有效的代码复用形式,但对组合的处理较为肤浅,缺乏在生产环境中进行面向对象编程的实际经验。
3.
设计实用主义者
:理解“工程权衡”的含义,在合适的地方使用继承,在必要时使用组合。他们明白为了取得进展需要妥协,同时会采取一切实际措施确保实现设计目标。他们认识到人类对世界的理解存在不足,设计和实现都会存在不完美,因此争论完美设计是浪费时间。他们会在每一步都尝试实现复用,其设计方法基于做出明智的工程权衡。
7. 良好设计的目标
好的设计的最终目标是构建一个灵活、模块化、可靠且稳定的应用程序架构。
1.
灵活的应用程序架构
:应用程序架构必须足够灵活,能够优雅地适应预期的功能添加。这通常是一个隐含的应用程序需求,在设计开始时就应考虑到,否则在添加新功能时可能会破坏应用程序的架构基础。
2.
模块化和可靠性
:应用程序组件必须既模块化又可靠。在面向对象应用程序中,类是模块化的自然边界。如果能最大化类的内聚性(即给类一个明确的目的)并最小化类的耦合性(即限制其对其他类的依赖),将更容易复用这些类。虽然模块化不一定意味着可靠,但设计良好的类(即内聚性高且耦合性低)更便于进行全面测试。
3.
通过管理依赖实现架构稳定性
:应用程序架构必须稳定,即对应用程序的更改应具有可预测的结果。正确预测更改对应用程序的影响能力与模块间的依赖数量成反比,依赖越多,越难预测更改的影响。
4.
何时接受“足够好”的设计
:判断设计何时达到“足够好”取决于应用程序的预期目的和相关需求。通常在将应用程序架构完全通用化所花费的时间(个人从未遇到过这样的需求)与构建一个足够灵活以适应上下文相似功能添加的架构之间进行权衡后做出决策。
总之,设计实用主义者利用面向对象设计机制的全谱,在所有可能的方面实现复用。良好设计的关键在于构建一个能够适应变化、模块化、可靠且稳定的应用程序架构。
Java编程中的Applet、JDBC与面向对象设计
8. 继承与组合的实际应用分析
为了更清晰地理解继承与组合的区别和应用场景,我们可以通过一个简单的例子来分析。假设我们要设计一个图形处理系统,有圆形(Circle)和矩形(Rectangle)两种图形。
- 使用继承的实现 :
// 定义一个抽象的图形类
abstract class Shape {
abstract double area();
}
// 圆形类继承自图形类
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
}
// 矩形类继承自图形类
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
}
在这个例子中,
Circle
和
Rectangle
类继承自
Shape
类,通过继承,它们复用了
Shape
类的抽象接口
area()
,并且各自实现了具体的计算面积的方法。
- 使用组合的实现 :
// 定义一个面积计算接口
interface AreaCalculator {
double calculateArea();
}
// 圆形面积计算器类
class CircleAreaCalculator implements AreaCalculator {
private double radius;
public CircleAreaCalculator(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
// 矩形面积计算器类
class RectangleAreaCalculator implements AreaCalculator {
private double width;
private double height;
public RectangleAreaCalculator(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
// 图形类,使用组合的方式
class Shape {
private AreaCalculator areaCalculator;
public Shape(AreaCalculator areaCalculator) {
this.areaCalculator = areaCalculator;
}
double area() {
return areaCalculator.calculateArea();
}
}
在这个组合的实现中,
Shape
类包含一个
AreaCalculator
接口的引用,通过传入不同的面积计算器实现类(如
CircleAreaCalculator
和
RectangleAreaCalculator
)来计算不同图形的面积。
从这个例子可以看出,继承是一种“是一个”(is-a)的关系,而组合是一种“有一个”(has-a)的关系。继承适用于当子类和父类之间有明显的层次关系,并且子类需要复用父类的行为和属性时;而组合适用于当对象之间的关系更倾向于协作,并且需要更灵活地组合不同的功能时。
9. 多态在程序设计中的作用
多态是面向对象编程的一个重要特性,它允许不同的对象对同一消息做出不同的响应。在上述图形处理系统的例子中,多态就体现在
Shape
类的使用上。
public class Main {
public static void main(String[] args) {
// 创建圆形对象
Shape circle = new Circle(5);
// 创建矩形对象
Shape rectangle = new Rectangle(3, 4);
// 调用相同的方法,根据对象的实际类型做出不同的响应
System.out.println("Circle area: " + circle.area());
System.out.println("Rectangle area: " + rectangle.area());
}
}
在这个
main
方法中,
circle
和
rectangle
都是
Shape
类型的引用,但它们分别指向
Circle
和
Rectangle
对象。当调用
area()
方法时,会根据对象的实际类型调用相应的实现,这就是多态的体现。
多态在程序设计中有很多好处:
-
提高代码的可扩展性
:当需要添加新的图形类型时,只需要创建一个新的类继承自
Shape
类,并实现
area()
方法,而不需要修改现有的代码。
-
增强代码的可维护性
:通过多态,可以将不同对象的行为封装在各自的类中,使得代码更加清晰和易于维护。
10. 接口的使用与功能解耦
接口是一种抽象类型,它定义了一组方法的签名,但不包含方法的实现。在面向对象设计中,接口可以用来打破代码模块之间的功能依赖。
继续以图形处理系统为例,我们可以定义一个
Drawable
接口来表示图形的绘制功能。
// 定义一个可绘制接口
interface Drawable {
void draw();
}
// 圆形类实现可绘制接口
class Circle extends Shape implements Drawable {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
@Override
public void draw() {
System.out.println("Drawing a circle with radius " + radius);
}
}
// 矩形类实现可绘制接口
class Rectangle extends Shape implements Drawable {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
@Override
public void draw() {
System.out.println("Drawing a rectangle with width " + width + " and height " + height);
}
}
在这个例子中,
Circle
和
Rectangle
类实现了
Drawable
接口,通过接口,我们将绘制功能从图形类中分离出来,使得图形类只关注自己的核心属性和行为(如计算面积),而绘制功能可以由不同的实现类来完成。这样,当需要修改绘制功能时,只需要修改实现
Drawable
接口的类,而不会影响到图形类的其他部分。
11. 设计模式中的继承、组合与多态应用
设计模式是在软件开发中反复出现的问题的通用解决方案,很多设计模式都运用了继承、组合和多态的思想。
- 策略模式 :策略模式使用组合来实现不同的算法策略。例如,在图形处理系统中,我们可以定义不同的图形绘制策略。
// 定义一个绘制策略接口
interface DrawingStrategy {
void drawShape(Shape shape);
}
// 简单绘制策略类
class SimpleDrawingStrategy implements DrawingStrategy {
@Override
public void drawShape(Shape shape) {
System.out.println("Simple drawing of shape");
}
}
// 详细绘制策略类
class DetailedDrawingStrategy implements DrawingStrategy {
@Override
public void drawShape(Shape shape) {
System.out.println("Detailed drawing of shape");
}
}
// 图形绘制器类,使用组合的方式
class ShapeDrawer {
private DrawingStrategy drawingStrategy;
public ShapeDrawer(DrawingStrategy drawingStrategy) {
this.drawingStrategy = drawingStrategy;
}
public void draw(Shape shape) {
drawingStrategy.drawShape(shape);
}
}
在这个例子中,
ShapeDrawer
类包含一个
DrawingStrategy
接口的引用,通过传入不同的绘制策略实现类(如
SimpleDrawingStrategy
和
DetailedDrawingStrategy
),可以实现不同的绘制效果。这就是组合在策略模式中的应用。
- 模板方法模式 :模板方法模式使用继承来定义一个算法的骨架,具体的步骤由子类来实现。例如,我们可以定义一个图形处理的模板方法。
// 定义一个图形处理模板类
abstract class ShapeProcessor {
// 模板方法
public final void processShape(Shape shape) {
// 预处理
preProcess(shape);
// 处理核心逻辑
process(shape);
// 后处理
postProcess(shape);
}
// 预处理方法,可由子类重写
protected void preProcess(Shape shape) {
System.out.println("Preprocessing shape");
}
// 核心处理方法,由子类实现
protected abstract void process(Shape shape);
// 后处理方法,可由子类重写
protected void postProcess(Shape shape) {
System.out.println("Postprocessing shape");
}
}
// 圆形处理类,继承自图形处理模板类
class CircleProcessor extends ShapeProcessor {
@Override
protected void process(Shape shape) {
System.out.println("Processing circle");
}
}
// 矩形处理类,继承自图形处理模板类
class RectangleProcessor extends ShapeProcessor {
@Override
protected void process(Shape shape) {
System.out.println("Processing rectangle");
}
}
在这个例子中,
ShapeProcessor
类定义了一个图形处理的模板方法
processShape()
,其中包含了预处理、核心处理和后处理三个步骤。核心处理步骤由子类(如
CircleProcessor
和
RectangleProcessor
)来实现,这就是继承在模板方法模式中的应用。
12. 总结
在Java编程中,Applet、JDBC和面向对象设计是非常重要的知识点。Applet为在网页中嵌入Java程序提供了一种方式,但需要注意其安全限制和生命周期管理。JDBC则是Java与数据库交互的重要API,掌握其使用步骤和不同类型的语句(如
Statement
和
PreparedStatement
)可以提高数据库操作的效率和安全性。
在面向对象设计方面,继承、组合、接口和多态是实现代码复用、提高代码可扩展性和可维护性的关键机制。设计实用主义者应该根据具体的应用场景和需求,灵活运用这些机制,做出明智的工程权衡。通过合理的设计和实现,可以构建出灵活、模块化、可靠且稳定的应用程序架构。
以下是一个简单的mermaid流程图,展示了使用JDBC连接数据库的基本流程:
graph LR
A[加载JDBC驱动类] --> B[建立数据库连接]
B --> C[创建Statement或PreparedStatement对象]
C --> D[执行SQL语句]
D --> E{是否有结果集}
E -- 是 --> F[操作结果集数据]
E -- 否 --> G[结束操作]
F --> G
通过这个流程图,可以更直观地理解使用JDBC连接数据库的步骤。在实际编程中,我们应该根据具体的需求和场景,灵活运用这些知识和技术,不断提升自己的编程能力和设计水平。
超级会员免费看

1956

被折叠的 条评论
为什么被折叠?



