Bootstrap

JAVA语言程序设计

计算机、程序和JAVA概述

一、计算机概述和编程语言

一)、Java语言的发展

  1. 60年代->提出对象与实例的概念,并引入了类。 1960年代由Simula 67语言引入面向对象的基本概念。Simula这一语言是Ole-Johan Dahl

    和Kristen Nygaard在挪威奥斯陆计算机中心为模拟环境而设计的。

    麻省理工PDP-1系统

    1963年,Ivan Sutherland的Sketchpad应用

  2. 80年代:面向对象成为主导思想,事件处理式成为面向对象的内容 C++的广泛应用

    适应了GUI图形界面开发的要求

    面向对象思想加入到流行的语言中:LISP、Pascal、Ada、Fortran、Basic

  3. 90年代:不断完善面向对象技术 Java语言

    1991: Green Project、James Gosling

    1993: WWW迅速发展,HotJava浏览器得到关注。

    1995: Java正式发布

  4. 近些年:支持面向对象程序设计,又支持面向过程程序设计的语言日益成熟并使用,以及脚本也开始支持OOP

    Python和Ruby是建立在OOP原理的脚本语言

    Perl和PHP亦分别在Perl 5和PHP 4时加入面向过程特性、函数式编程。

    Groovy也是面向对象的脚本语言,是Java语言的扩展,增加了Python、Ruby和SmallTalk等语言的特性。

二)、Java语言的版本

Java标准版(Java Standard Edition,Java SE)

Java企业版(Java Enterprise Edition,Java EE)

Java微型版(Java Micro Edition, Java ME)

三)、Java语言的特性

  1. 简单性

  2. 面向对象

    Java语言的设计完全是面向对象的,它不支持类似C语言那样的面向过程的程序设计技术 。

  3. 分布式

  4. 健壮性

    Java是一种强类型语言,它在编译和运行时要进行大量的类型检查。类型检查帮助检查出许多开发早期出现的错误。

    Java自已操纵内存减少了内存出错的可能性。Java的数组并非采用指针实现,从而避免了数组越界的可能。

    Java通过自动垃圾收集器避免了许多由于内存管理而造成的错误。Java在程序中由于不采用指针来访问内存单元,从而也避免了许多错误

    发生的可能。

  5. 可移植性

    Java的数据类型具有固定的大小;

    二进制数据以固定形式存储和传输;

    字符串是用Unicode存储

    定义了可移植的接口,在不同操作系统下有不同的实现

  6. 结构中立

    作为一种网络语言,Java编译器将Java源程序编译成一种与体系结构无关的中间文件格式。只要有Java运行系统的机器都能执行这种中

    间代码。从而使同一版本的应用程序可以运行在不同的平台上、

  7. 安全性

    作为网络语言,安全是非常重要的。Java的安全性可从两个方面得到保证。

    一方面,在Java语言里,象指针和释放内存等C++功能被删除,避免了非法内存操作。

    另一方面,当Java用来创建浏览器时,语言功能和一类浏览器本身提供的功能结合起来,使它更安全。Java语言在你的机器上执行前,要

    经过很多次的测试。它经过代码校验,检查代码段的格式,检测指针操作,对象操作是否过分以及试图改变一个对象的类型。

    另外,Java拥有多个层次的互锁保护措施,能有效地防止病毒的入侵和破坏行为的发生。

  8. 解释的

    Java解释器(运行系统)能直接对Java字节码进行解释执行。链接程序通常比编译程序所需资源少。

  9. 高性能

    虽然Java是解释执行程序,但它具有非常高的性能。另外,Java可以在运行时直接将目标代码翻译成机器指令。

  10. 多线程

Java提供的多线程功能使得在一个程序里可同时执行多个小任务,即同时进行不同的操作或处理不同的事件。多线程带来的更大的好处是

具有更好的网上交互性能和实时控制性能,尤其是实现多媒体功能。
  1. 动态性
Java的动态特性是其面向对象设计方法的扩展。它允许程序动态地装入运行过程中所需要的类,而不影响使用这一类库的应用程序的执

行,这是采用C++语言进行面向对象程序设计时所无法实现的。 

四)、Java语言的开发

Java语言的开发工具JDK

JDK的安装  直接执行下载的安装文件后,根据提示就可正常安装。

安装后产生如下目录结构  JDK安装目录*\bin的目录下包含以下主要文件:

javac:Java编译器,用来将Java程序编译成bytecode。

java:Java编译器,执行已经转换成bytecode的Java应用程序。

jdb:Java调试器,用来调试Java程序。

javap:反编译,用来返回Java程序的成员变量及方法等信息。

javadoc:文档生成器,创建HTML文件。

jshell :交互编程环境

jconsole: Java监控和查看程序

设置JDK环境变量 为了能从任何目录编译和运行Java程序,需要在计算机系统中设置PATH和CLASSPATH变量。

(1)定义JAVA_HOME

(2)定义CLASS_PATH:%JAVA_HOME%/lib和.

(3)定义PATH:在PATH路径中增加%JAVA_HOME%/bin目录

集成开发工具
•Intellij IDEA
•NetBeans IDE;
•Eclipse;
•JBuilder;
•JCreator Pro ;

二、基础程序设计

一)、从控制台读取输入

(一)输入输出流

通过系统类System达到访问标准输入输出的功能。System类管理标准输入输出流和错误流,有以下三个对象:

1)System.out:把输出送到默认的显示(通常是显示器)。

2)System.in:从标准输入获取输入(通常是键盘)。

3)System.err:把错误信息送到默认的显示。

(二)利用java.util.Scanner实现控制台读取输入

java.util.Scanner input=new java.util.Scanner(System.in);

输入一行字符串:input.nextLine();

输入一行的单词字符串:input.next();

输入整数:input.nextInt();

输入长整数:input.nextLong();

输入短整数:input.nextShort();

输入单精度数:input.nextFloat();

输入双精度数:input.nextDouble();

输入字节数:input.nextByte();

输入布尔数:input.nextBoolean();

二)、格式化输出
(一)格式化输出格式
在JDK5.0起支持数据的格式化输出。即,利用System.out对象的format和printf方法,数据按照特定的格式输出。

格式化输出形如:

1.将对象args按照format格式输出

System.out.format( String format, Object… args);

System.out.printf( String format, Object… args);

2.将对象args在本地语言环境下按照format格式输出

System.out.format( Locale locale, String format, Object… args);

System.out.printf( Locale locale, String format, Object… args);

(二)格式符
在这里插入图片描述
三)、基于JavaFx的输入和输出
(一)JavaFX库简介
JavaFX是Java的图形用户界面工具包。JavaFX是一组图形和媒体API,用来创建Java的客户端应用。

(二)定义JavaFX的应用程序
形式如下:

public JavaFXAPP extends Application{

@Override

public void start(Stage primaryStage) throws Exception {

    //定义GUI界面

}

public static void main(String[] args){

      //加载参数

       Application.launch(args);

}

}

(三)JavaFX使用Alert实现信息的显示
Alert alert=new Alert(Alert.AlertType.INFORMATION);

(四)TextInputDialog实现信息的输入
TextInputDialog inputDialog=new TextInputDialog();
四)、标识符和保留字
1、标识符

标识符用于标识变量、函数、类和对象的名称,一来说明它们的存在,二来方便地使用它。

2、保留字

具有特定含义的标识符。
JDK 10 出现了var

const和goto保留字没有任何意义

数据类型:boolean、byte、char、double、float、int、long、short、enum、var

控制语句:break、case、continue、default、do、else、for、if、return、switch、while

类和对象:class、extends、super、this 、 instanceof、new

接口:implements、interface

包:import、package

修饰符:abstract、final、native、private、public、protected、strictfp、static、synchronized、transient、volatile、void

异常处理:assert、try、catch、finally、throw、throws

五)、变量和字面值
(一)变量
定义

程序中可能会被改变的值。变量用于存储程序中的值

表达形式

数据类型 变量名;

数据类型 变量名表;

在定义变量时,可以对变量初始化。

(二)字面值
定义

字面值(直接值,Literal),是程序中直接出现的常量值。

数值型字面值

(1)整型字面值

(2)浮点字面值

(3)科学计数法

从JDK7.0开始,开始支持二进制数据表达的语法。

(byte)0b01101101; //8位byte数据

(short)0b0110110100110010; //16位short数据

(long)0b00010110110101101100010111101101; //32位int数据

从JDK7.0开始支持单位级别的数据,一般每三位数据可用“_”将数据之间分割开,形如:

        8_223_352_036_854_555_805L

六)、赋值语句和赋值表达式
(一)赋值语句和赋值表达式

定义:

    赋值语句是将一个值指定给一个变量。

形式如下:

    变量 = 表达式 ;

注意:

表达式的数据类型必须与变量的数据类型一致

(二)增强赋值运算

操作符+、-、*、/、%可以结合赋值运算形成增强赋值运算

+=

-=

*=

/=

%=

七)、命名规则
类命名规则

方法命名规则

变量命名规则

常量命名规则

包的命名规则

八)、基本数据类型
(一)基本数据类型
基本数据类型是指由Java语言本身定义的数据类型。

(二)基本数据类型的操作
数值的操作

+、-、*、/、%

幂运算

(1)java.lang.Math

(2) Math.pow(x,y)=>

(三)装箱和拆箱
每个基本类型都有一个对应的应用类型,称为装箱类型。
在这里插入图片描述

自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。
在这里插入图片描述

(1)基本类型只有值,装箱类型具有同一性;

(2)基本类型只有功能完备的值,装箱类型除了对应基本类型的所有功能值外,还有一个非功能值null

(3)基本类型比装箱类型更节约时间和空间

九)、自增自减操作
(一)自增自减操作符
操作符
在这里插入图片描述

(二)自增自减运算的优先级
从左到右对操作数求值;

在右边操作数的任何求值之前,二元操作符左边的操作数先求值。

例如

int i=1;

int k=++i+i*3;

注意:使用自增操作符和自减操作符可以使表达式更加简短,但也会使它们比较复杂而且难懂

      避免在同一个表达式中使用这些操作符修改多个变量或多次修改同一个变量。

十)、表达式求值及操作符优先级
(一)运算符
在这里插入图片描述
(二)操作符的优先级
单目运算

双目运算

三目运算

赋值运算

十一)、软件开发过程
(一)软件开发过程
1.需求规范

   是一个规范化的过程,旨在理解软件要处理的问题,以及将软件系统功能记录到文档中。通过用户和开发者之间的沟通和交流来获得实现。

2.系统分析

     旨在分析数据流,并确定系统的输入和输出。当进行分析时,先确定输出,然后再确定怎样的输入来产生结果;

3.系统设计

     设计一个从输入获得输出的过程。将问题分解为课管理的组成部分,并设计实现每个组成部分的策略。可以将每个组成部分看作一个执行系统特定功能的子系统。

   系统设计的本质:输入、处理和输出(IPO,Input-Processing-Output)

4.系统实现

   将系统设计翻译成程序。为每个组成部分编写独立的程序,然后集成一起。

5.系统的测试

     确保代码符合需求规范,并且排除错误。通常由一个没有参与产品设计和实现的独立测试团队完成测试。

6.系统的部署

     使得软件可以被使用。按照类型的不同,软件可以安装到用户的机器上,或安装服务器中。

7.维护

 对软件产品进行更新改进。

(二)软件开发的示例
整钱兑零问题:将大额的钱分成较小的货币单位。

十二)、常见的错误和陷阱

(一)基础编程涉及的错误
常见错误1:未声明、未初始化的变量和未使用的变量

常见错误2:整数溢出

常见错误3:舍入错误

常见错误4:非预期的整数除法

常见陷阱:冗余的输入对象

三、选择语句

一)、boolean数据类型和if语句
(一)boolean数据类型
可以声明具有值true或false的变量

关系操作符

在这里插入图片描述

(二)if语句
1.if语句

if(布尔表达式){

  语句(组);

}

2.if~else语句

if(布尔表达式){

  语句(组);

}else{

  语句(组);

}

3.嵌套if语句和多分支if~else语句

if(布尔表达式1){

  语句(组);

}else if(布尔表达式2){

  语句(组);

}else if(布尔表达式3){

  语句(组);

}else{

  语句(组)

}

二)、switch语句
switch语句
switch(switch表达式){

case 值1:语句(组)1;

                 break;   

case 值2:语句(组)2;

                 break;

......

case 值N: 语句(组)N;

                 break;

default: 默认情况下执行语句(组)

}

JDK12的新特性
switch(表达式){

case 值1,值2->语句1;

case 值3,值4->语句2;

[default->语句n;]

}

四、数学函数、字符串应用

一)、数学函数
java.lang.Math 类包含的方法进行基本的数字操作,如基本的指数,对数,平方根和三角函数等

(1)三角运算 sin、cos、tan、toRadians、toDegrees、asin、acos、atan;

(2)指数运算exp、log、log10、pow、sqrt

(3)取整运算ceil、floor、rint、round

(4)min、max、abs

(5)random

二)、BigInteger和BigDecimal
1.java.math.BigInteger

     用于表示任意大小和精度的整数

2.java.math.BigDecimal

      用于表示任意大小和精度的十进制数

三)、String类
字符串常量则是用双引号括起来的字符序列,如“x”,“\n”,“Java”等

Java语言中使用String类来存放字符串常量,有专门的属性和方法

(1)String类的构造方法

String():

创建一个空的String对象;

String(byte[] bytes):

使用操作系统默认的字符集对给定的字节数组bytes参数进行解码后,创建一个新的String对象;

String(char[] value):

通过给定的字符数组value,创建一个新的String对象;

String(char[] value, int offset, int count):

在字符数组value中,从offset为开始,count个字符序列来创建新的String对象;

String(int[] codePoints, int offset, int count):

利用一个Unicode代码数组,从offset开始截取count长度的Unicode代码点的序列创建一个新的String的对象;

String(String original) :

通过给定的字符串常量original创建一个新的String对象;

String(StringBuffer buffer) :在创建一个新的String对象,它包含当前包含在字符串缓冲区buffer的字符序列;

String(StringBuilder builder):在内存中分配一个新的字符串,它包含当前包含在字符串生成器builder中的字符序列。

(2)常见的方法

比较字符串

字符串比较是最常见的应用之一。字符串比较往往包括了两种比较:

(1)字符串对象是否一致的比较;

(2)字符串包含字符内容是否一致的比较。java.lang.String类有定义了

equalsIgnoreCase():

将该字符串和另外的字符串anotherString相比较内容是否相等,忽略大小字母形式;

例如:

String s1=“This is”;

s1.equalsIgnoreCase(“this Is”);

//结果为真;

equals():

compareTo():

比较两个字符串的词典内容即每个字符的Unicode是否一致,如果两个字符串完全相等返回0值

例如:

String s1=“This is”;

s1.compareTo(“This is”);//结果为0;

s1.compareTo(“Example”);//结果为15

s1.compareTo(“Yellow”);//结果是-5

regionMathches():

ignoreCase – 可选项,如果真, 比较字符忽略大小写.其他情况要区分大小写;

toffset – 该字符串的子串的开始偏移位置.

other – 另一个字符串.

ooffset – other字符串的子串的开始偏移位置.

len – 要比较字符的长度.

这些方法来实现对字符串的比较。

例如:

String S=“String”;

String s1=“STRING”;

S.regionMatches(0,s1,0,s1.length());

//结果为假;

S.regionMatches (true,0,s1,0,s1.length())

//结果为真

五、循环语句

一)、基本循环语句
(一)while循环
while(布尔表达式){

   语句(组);

 }

(二)do~while循环
do{

   语句(组);

  }while(布尔表达式);

(三)for循环
for(初始化; 循环条件判断 ; 变更循环条件){

 语句(组);

}

六、一维数组

一)、一维数组的声明和创建
一维数组

声明数组:int[] a ;

             int a[];

创建数组:

(1)基本数据类型

int[] a=new int[10];//a数组的每个元素具有初始值0

(2)其他类型

String[] b=new String[];

//创建数组,但数组的每个元素为null,无意义;

可以执行下列步骤,为每一个元素初始化:

for(int i=0;i<b.length;i++)

b[i] = new String(“hello”+i);

数组的复制

System.arraycopy(原数组,原数组的索引,目标数组,目

标数组的索引,复制元素的个数)

Arrays.copyOf(原数组,复制元素的个数) 返回一个原数组的复本

Arrays类:用于处理数组实例的操作,常见有:

Arrays.binarySearch(数组,关键字):二分法检索算法检索关键字key;

Arrays.copyOf(数组,长度):返回复制指定的数组;

Arrays.copyOfRange(数组,开始位置,结束位置):复制指定的数组到新的数组;

Arrays.equals(数组1,数组2):比较两个数组是否相等;

Arrays.fill(数组,值):将给定的值赋值给定的数组

Arrays.sort(数组):数组排序

Arrays.toString(数组):将数组转换成特定的字符串

二)、数组的复制
Arrays类:用于处理数组实例的操作,常见有:

Arrays.binarySearch(数组,关键字):二分法检索算法检索关键字key;

Arrays.copyOf(数组,长度):返回复制指定的数组;

Arrays.copyOfRange(数组,开始位置,结束位置):复制指定的数组到新的数组;

Arrays.equals(数组1,数组2):比较两个数组是否相等;

Arrays.fill(数组,值):将给定的值赋值给定的数组

Arrays.sort(数组):数组排序

Arrays.toString(数组):将数组转换成特定的字符串

七、多维数组

一)、多维数组的声明和初始化
(一)多维数组的声明
数据类型[][] 数组名;

(二)多维数组的初始化
声明同时初始化
int[][] a={{1,23},{3,45}}

先声明后初始化

int[][] a=new int[3][4];

for(int i=0;i<a.length;i++)

  for(int j=0;j<a[i].length;j++)

         a[i][j]=3;

锯齿数组

数组维度不一致

(三)多维数组的访问
通过循环访问。

八、抽象和封装类

一)、类和对象
(一)面向对象和面向过程的比较

面向过程程序设计是将算法转化成程序代码,由于程序中数据和过程或函数是分开的,如果对程序的功能发生一点变化,假设新增一个功能函数,这可能需要程序员对程序做较大程度的修改。

面向对象程序设计语言是利用面向对象特性可以很好的改善过程设计语言中存在的问题。充分体现了程序的模块化、重用性、可用性。

(二)面向对象

面向对象

   将软件组织成一系列离散的、合并了数据结构和行为的对象。

2.面向对象的特性

   抽象性:抽象就是抽出事物的本质特性而暂时不考虑它们的细节

   封装性:将信息隐蔽的过程称为封装。

   继承性

   多态性

二)、类的定义
一、定义形式

[修饰符] class 类名 [extends 父类] [implements 接口名1,……, 接口名n]

{

构造方法

成员变量声明

成员方法声明

}

二、修饰符
是一些特指的关键字,用于说明类的可访问性(如public)和其他非访问性质(如final、static、abstract等)。

1)访问修饰符

public定义公有类,能被所有的类访问。

默认方式:指没有修饰符定义类的方式,说明类为包私有类,只能被本包内的类访问

private:定义私有类,内部类。

(2)非访问修饰符

是指用于限定类的性质的关键字,它们往往限定类是否是具有某些特征的类。

abstract:抽象类

final:最终类

static:静态内部类

strictfp:声明的类的范围内Java的编译器以及运行环境会完全依照浮点规范IEEE-754来执行

三、代码示例
(1)内部类

public class Student{

  public static class Adress{

     public void test(){

       System.out.println("Address");

      }

   public class Type{

      public void testType(){

        System.out.println("Type");

      }

}

public class Test{

   public  static void main(String... args){

       Student s=new Student();

       new Student.Address().test();

       s.new Type().testType();

    }

}

三、构造方法

要使用对象,首先必须构造它们,并指定它们的初始状态,然后将方法应用于对象。

在Java程序设计语言中,使用构造方法(constructor)来构造新的实例。一个构造方法是一个新的方法,它的作用是构造并初始化对象

构造方法是类的一种特殊方法,它的特殊性主要体现在如下的几个方面:

(1)构造方法的方法名与类名相同。

(2)构造方法没有返回类型。

(3)构造方法的主要作用是完成对类对象的初始化工作。

(4)构造方法不能由编程人员显式地直接调用。

(5)在创建一个类的新对象的同时,系统会自动调用该类的构造方法为新对象初始化。

 (6)一旦用户自定义构造方法,系统就不会在生成默认无参的构造方法


构造方法的特点
默认构造方法

默认构造方法就是无参的构造方法。如前述,当用户没有定义构造方法的时候,系统会自动定义一个默认构造方法。 

构造方法的重载

是定义具有不同参数性质的构造方法。这些参数性质包括了参数类型和参数的个数。通过重载构造方法,创建一个对象在不同条件下可以有不同的初始化行为。

四、this

(1)通过它访问对象的成员

(2)this关键字可以实现在构造方法内部调用其他构造方法

定义一个类的时候,往往为存在不同情况定义多个构造方法。由于构造方法定义的时候部分信息处理相同,为了避免代码的重复,可以用this关键字实现在一个构造方法内调用另一个构造方法。这种在构造方法内通过this关键字调用其他构造方法的特殊情况被称为显式构造方法激活 

五、类之间的关系
1.依赖

TV Controller

//形式一

public class TV{

public void powerOn(){

}

}

public class Controller{

public void turnOn(TV tv){

tv.powerOn();

}

}

//形式二

public class Controller{

public void turnOn(){

TV tv=new TV();

tv.powerOn();

}

}

//形式三

public class Controller{

public TV turnOn(){

TV tv = new TV();

tv.powerOn();

return tv;

}

}

TW34RS$]]C``T[3KBB4I951.png

2.关联

public class XueJi{

public void handle(){

}

}

public class Student{

private Xueji xueji;

public void register(){

  xueji.handle();

}

}

5EK`PJ5XLOBZOAZO1V9~GSP.png

3.聚合(has-a)

public class Keyboard{

public void input(){

}

}

public class Computer{

private Keyboard ky;

public void input(){

  ky.input();

}

}

(CS0RVT69)19UN25B)%`%]4.png

4.组合(contains-a)

public class Enginee{

public void power(){

}

}

public class Car{

private Enginee en;

public void run(){

en.power();

}

}

B2F]Q`3MJXPOHXNK%1$UF.png

5.泛化(is-a)

public class Student{

}

public class GraduateStudent extends Student{

}

F)2RMGA5JCGAFUA9{2NTUTR.png

九、继承性与多态性

一、继承性
一)、继承性
定义

       继承性是软件复用的一种形式。新类由已存在的类生成,通过保留它们的属性和行为,并且根据新类的要求对性能加以修改,添加新的属性和行为。

   2.Java实现继承性
       如果子类只从一个父类继承,则称为单继承;如果子类从一个以上父类继承,则称为多继承。注意 Java不支持多重继承,但它支持“接口”概念。

Java语言中是通过关键字extends来实现单继承的。简单的实现格式如下:

class 子类名 extends 父类名{

类体

}

注意:

如果在格式中没有通过extends关键字来标明父类名,这并不是意味着该类无父类,相反,它表示该类是java.lang.Object的子类。

二)、关于java.lang.Object

Object是所有类的父类(超类),所有类都由Object类扩展而来。

getClass():返回对象的类型

hashCode()和equals(Object):hashCode返回对象的散列码,equals判断对象是否等同

clone():克隆对象的复本

toString():返回对象的字符串表达

finalize():提供一个后退(fallback)机制来释放如文件、socket、图形上下文等非内存的有限资源;

notify()、notifyAll()、wait():用于并发处理机制中

二、super
super关键字表示对类的父类的引用。在子类中有时会使用父类的数据和方法,这时就可以利用super关键字来实现对父类的引用。super关键字不是一个对象的引用,而是调用父类的成员特有的关键字。

super关键字主要应用在三个方面:

1)应用于引用父类的构造方法;

2)调用父类的被子类覆盖的成员变量

3)应用于引用父类中被子类覆盖的成员方法

三、抽象类和接口
1、抽象类

抽象类是用关键字abstract修饰的类为抽象类。语法格式形如:
      abstract class 抽象类名 {
               类体
      }
注意:
抽象类只是具体实体的抽象描述,是不可以实例化对象。

尽管抽象类定义构造方法是没有语法错误,但是没有实际意义。抽象类中可以定义非抽象方法,也可以定义抽象方法。

抽象方法在它的派生子类中可以覆盖,来实现具体功能。

抽象类派生出的子类,必须对抽象类中的抽象方法重写。 

抽象类隐藏的含义是包私有的.

 2.接口
接口是对类的一组需求,”接口提供多重继承类似的功能,还避免了多重继承的复杂性和低效性。

Java语言中,接口是通过关键字interface来实现定义的,具体格式如下:

[访问控制] interface 接口名 [extends 父接口名表]{
    接口体
}

接口的实现:Java语言中通过关键字implements来实现接口,具体的实现是通过类来完成的。接口实现的具体格式如下:
class 类名 implements 接口名表{
     类体
}

3.JDK8.0以后接口的新特性
(1)默认方法

(2)静态方法

(3)私有方法

四、Lambda表达式
lambda表达式,是指匿名函数,Lambda表达式是一个可传递的代码块。

只包含一个抽象方法的接口被称为函数接口(functional interface),Lambda 表达式用用于任何函数接口适用的地方

使用Lambda表达式的前提条件

(1)单个抽象方法的匿名类的定义

(2)必须是针对实现接口,而不是继承抽象类的匿名类

此时,接口可以使用@FunctionalInterface来标注

Lambda表达式的语法一般表现形式

(Type1 param1,Type2 param2,…,TypeN paramN)->{

语句1

      语句2

      …..

      [return 值]

}

五、方法引用
(一)关于方法引用(method reference)
某些lambda表达式里面仅仅是一个方法中调用一个语句。在这种情况下可直接通过方法名称引用方法的形式,可读性更高一些,这种形式就是方法引用,方法引用是一种更简洁易懂的lambda 表达式。

(二)方法引用的表达式方式
Lambda表达式的简写形式,主要形式有:

对象::对象方法

类名::静态方法

类名::对象方法

引用构造方法 类名::new

::作用域解析操作符

可以在方法引用中使用this对象

六、多态性
(一)多态性的概念
多态(Polymorphism)提高了程序可扩充性,调用多态性行为的软件传送给对象的消息(即方法调用)与对象的类型无关,因此能响应已有消息的新类型可以直接加入系统,而不用修改基本系统。

(二)运行时绑定
在运行时自动选择正确的方法进行调用称作动态绑定(dynamic binding)。

在编译时可以选择正确的方法进行调用称作静态绑定(static binding)

(三)多态性的实现
(1)继承机制下多态

(2)接口实现多态

(四)策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

十、集合框架

一、Collection
(一)集合的概念
集合是包含一组元素的整体对象,通过该对象可以实现对内部元素的存储、检索、管理以及相应的处理操作。

在Java语言中定义了关于该集合概念的集合框架(Collections Framework).集合框架有多种接口和类构成。

集合框架的出现,解决了:

降低研发复杂应用的规模,开发Java应用更加容易;

提高了API应用的可重用性;

使得学习API变得更加容易,操作更加方便;

(二)集合的结构
核心集合框架的Collection接口是构造集合框架的基础,它是处理对象集合的根接口,声明了所有集合接口拥有的核心方法。

Collection接口是不能直接实现,必须通过它的子接口(如Set、List、Queue等)来实现。

Collection接口的声明形式如下:

public interface Collection

其中,Collection接口是范型,E是指任何类型

public interface Collection extends Iterable {

// 基本操作

int size();                                                          //集合众包含元素的个数

boolean isEmpty();                                          //判断集合是否有元素

boolean contains(Object element);                  //判断集合中是否包含元素element

boolean add(E element);                                  //可选操作,添加元素到集合中

boolean remove(Object element);                    //可选操作,从集合中移除特定元素

Iterator<E> iterator();                                   //返回包含所有元素的迭代对象

// 主要操作

boolean containsAll(Collection<?> c);             //判断集合是否包含特定集合所有元素

boolean addAll(Collection<? extends E> c);    //可选操作,将集合c的所有元素添加集合

boolean removeAll(Collection<?> c);              //可选操作,将集合c的所有元素从当前集合移除

boolean retainAll(Collection<?> c);                 //可选操作,保留与集合c中相同的元素;

void clear();                                                       //可选操作,将集合所有元素清除;

// 数组操作

Object[] toArray();                                            //返回集合的所有元素构成的数组

<T> T[] toArray(T[] a);                                    //返回集合中与指定数组a类型匹配的元素构成的数组;

//JDK 8

default boolean removeIf(Predicate<? super E> filter) 将符合条件的元素删除

default Spliterator spliterator() // 用于并行计算, 将一个集合分成多个块,并行处

                                                                                  //             理这多个块并将处理结果汇合到一起

default Stream stream() // 返回序列流,单线程处理

default Stream parallelStream() // 返回并行流,多线程并发处理

}

Collection接口中定义了一些方法是可选的,它们的实现不够完善,即:这是指这些方法具有破坏性,它们的方法内部的操作可以重新被修改定义,由于一些操作不能得到支持,如果发生操作不能支持,会抛出“UnSupportedOpreationException

二、List
(一)List概念
List是列表,表示有序的集合。List允许包含重复的元素;也允许包含null元素

用户可以通过指定下标访问元素,并可以指定元素在集合中的存储位置。在List类集中,下标从0开始。

(二)List接口结构
除了继承Collection接口外的操作,List还包括的操作有:

public interface List extends Collection {

// 位置访问

E get(int index);                                              //获取指定位置元素;

E set(int index, E element);                            //可选操作,设置指定位置的元素;

boolean add(E element);                                 //可选操作,增加元素;

void add(int index, E element);                      //可选操作,在指定位置增加元素;

E remove(int index);                                       //可选操作,删除指定位置的元素

boolean addAll(int index, Collection<? extends E> c); 

                                                                        //可选操作,将集合c中所有元素加入到指定位置

// 检索

int indexOf(Object o);                                    //检索元素的第一个位置

int lastIndexOf(Object o);                              //检索元素的最后一个位置



// 迭代 

ListIterator<E> listIterator();                         //返回列表迭代对象

ListIterator<E> listIterator(int index);          //返回从指定位置开始的迭代对象



// 范围处理

List<E> subList(int from, int to);                  //返回指定位置范围的子集

}

(三)常见的列表类
1.ArrayList

ArrayList类实现了List接口,它将元素存储在一个动态数组中,存储空间大小可随存储元素的多少进行动态变化。可以存储null元素;

public class ArrayList extends AbstractList

                                        implements List<E>, 

                                                          RandomAccess, 

                                                          Cloneable, 

                                                          Serializable

2.LinkedList

LinkedList类也实现List接口,它将元素存储在链表(注意:Java中所有的链表都是双链表)中。它实现了List接口中的所有可选方法,它允许保存null元素;

public class LinkedList extends AbstractSequentialList implements List,

                                                             Queue<E>,

                                                             Cloneable, 

                                                             Serializable

三、Set
(一)java.util.Set接口
在Java语言中,Set接口定义的是与数学的Set集合概念一直的接口;

Set接口扩展了Collection接口,Set定义的集合中不能包含相同的元素。Set除了继承Collection定义的方法外,本身并没有定义其他的方法。

通常实现Set接口的类有:

(二)常见的集合类
1.HashSet
java.util.HashSet:定义散列集;

HashSet存储一个元素的时候,HashSet会首先检查元素的哈希码和集的容量的%运算,如果运算结果指向的位置为空,则元素可以加进去;如果指向的位置不为空,这就说明了HashSet中有某个元素与这个元素的哈希码相同,这时候就调用equals方法进行两个元素的比较,如果比较的结果不相同,此元素也可以加进HashSet;如果equals比较的结果还是相同,那么就不能添加此元素。

2.TreeSet
java.util.TreeSet: 定义树型有序集

TreeSet是有序集,内部采用red-black tree(搜索二叉树)数据结构来存储集合的元素,它的执行效率要低于HashSet;

3.LinkedHashSet
java.util.LinkedHashSet:定义链接散列集

LinkedHashSet定义链接散列表,内部采用双链表的数据结构;

与HashSet的无序相比,LinkedHashSet实现了顺序,运用迭代器Iterator对象访问LinkedHashSet,可以按照加入元素的顺序访问;

四、Queue
(一)队列特点

Queue接口是Collection的子接口,可以用来实现元素按照优先顺序存储。一般默认下,Queue按照“FIFO”(先进先出)方式处理集合;

(二)java.util.Queue接口

public interface Queue extends Collection {

boolean add(E e);

        //将特定元素插入队列,如果受到容量的限制,会抛出IllegalStateException;

E element();  

        //返回队列的头元素,检索失败会抛出NoSuchElementException;

boolean offer(E e);

        //如果容量许可,将插入特定元素;

E peek(); 

        //返回队列的头元素,如果为空,返回null;

E poll(); 

       //返回并删除队列的头元素,如果头元素为空,则返回null;

E remove(); 

       //返回并删除队列的头元素,删除失败会抛出NoSuchElementException

}

(三)优先队列PriorityQueue

一个基于优先级堆的极大优先级队列。

队列中的元素可以按照任意顺序插入,但是按照排序的顺序对队列中的元素进行检索。

此队列排序的顺序按照在构造时所指定的顺序对元素排序,既可以根据元素的自然顺序 来指定排序,也可以根据 Comparator来指定,这取决于使用哪种构造方法。

优先级队列不允许null元素。依靠自然排序的优先级队列还不允许插入不可比较的对象

五、Map
(一)映射特点

Map接口用于存储元素和关键字的映射关系,在Map中关键字相当于List中的下标值,用于检索元素的对象。

在Map中关键字可以定义为任意类型的对象,但必须是唯一的,不能有重复。每个关键字都对应于一个存放在Map对象中的元素,元素的值是可以重复的

(二)java.util.Map

public interface Map<K,V> {

// 基本操作

V put(K key, V value);//在当前Map对象中将value和关键字key进行关联,若在Map对象中已存在和key关联的元素,则该元素被value替换

V get(Object key);                                  //获取关键字对应的值;

V remove(Object key);                           //若关键字key存在于当前Map对象中,则删除该关键字对应的映射内容

boolean containsKey(Object key);         //若当前Map对象中包含了key作为关键字,则返回true,否则返回false

boolean containsValue(Object value);    //若当前Map对象中包含了value作为元素值,则返回true,否则返回false

int size();                                                 //返回当前Map对象中“关键字/元素值”对的个数

boolean isEmpty();                                 //若当前Map对象是空的则返回true,否则返回false

// 主要操作

void putAll(Map<? extends K, ? extends V> m);          //将映射m的内容全部添加到当前Map对象中

void clear();                                                                    //从当前Map对象中删除所有的关键字和元素    

// 集合视图

public Set<K> keySet();                                 //返回当前Map对象的所有关键字的集合视图

public Collection<V> values();                      //返回当前Map对象的所有元素值构成的集合

public Set<Map.Entry<K,V>> entrySet();     //返回当前Map对象的所有映射的集合视图 // entrySet元素的接口    

public interface Entry {

    K getKey();

    V getValue();

    V setValue(V value);

}

}

(三)常见的映射类

HashMap

java.util.HashMap<K,E>

HashMap类使用散列表来实现Map接口,该类实现了所有Map接口定义的操作,并且允许空值和空关键字存在于对象中。

Properties

表示一个持久的一套详细属性,属性可以被保存到一个流或从流中加载的类。

以下是关于属性的要点:

属性列表中每个键及其对应值是一个字符串。

一个属性列表可包含另一个属性列表作为它的“默认”,第二个属性可在列表中搜索,如果没有在原有的属性列表中找到的属性键。

十一、用户图形界面

一、JavaFX编程
(一)MVC模式
MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。

Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。

View(视图) - 视图代表模型包含的数据的可视化。

Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

(二)JavaFX
JavaFX 是一个强大的图形和多媒体处理工具包集合,它允许开发者来设计、创建、测试、调试和部署富客户端程序,并且和 Java 一样跨平台。从 JDK 11 开始,JavaFX 模块与 JDK 分开提供。

十二、异常处理

一、异常类
一、什么是异常?

异常是在一个程序执行过程中,阻碍程序指令流的正常运行一个错误事件。

当一个方法中有错误发生的时候,方法就会创建一个对象并把它传递给运行系统。这个对象就称为异常对象,异常对象包含了错误信息,包括错误类型、错误发生时候程序的状态。

运行系统会在调用堆栈中寻找处理异常的代码。这些代码称为异常处理器(Exception Handler)。查找异常处理器是从调用堆栈中从发现错误的方法开始反向进行的。当异常处理器(异常处理程序段)被发现,运行系统将异常传递给异常处理器。该异常处理器就可以处理抛出相对应类型的异常。这一过程就是捕捉异常(Catch an Exception)。如果没有异常处理器,程序就会终止。

二、异常类的定义

所有的Throwable类的子孙类所产生的对象都是异常。

每个异常类都代表了一种运行错误,

异常类中包含了该运行错误的信息和处理错误的方法等内容

1.异常的分类

Error:由Java虚拟机生成并抛出,Java程序不做处理.描述了Java运行时系统内部错误和资源耗尽错误.

Exception(程序中的问题,可预知的): Java编译器要求Java程序必须捕获或声明所有的非运行时异常

RuntimeException(被0除等系统错误,数组下标超范围,访问空指针,类型转换):由系统检测, 用户的Java 程序可不做处理,系统将它们交给缺省的异常处理程序.如果程序出现RuntimeException异常,代码就一定存在问题。

用户自己定义异常

常见的异常类

ArithmeticException 算术异常

ClassCastException 两个类型间的转换不兼容时引发的异常

IllegalStateException 非法或不适当调用方法产生的错误状态异常

IllegalArgumentException 向方法传递错误或非法的参数所产生的异常

NumberFormatException IllegalArgumentException的子类,是字符串转换成数字抛

                                                         出的异常

IndexOutOfBoundsException 排序索引超出范围抛出的异常,是

ArrayIndexOutOfBoundsException (数组越界异常)和StringIndexOutOfBoundsException

                                                            (字符串越界异常)的父类

NullPointerException 对null对象的非法引用抛出的异常

SecurityException 安全异常

UnsupportedOperationException 不支持请求操作抛出的异常

…….

2.未检异常和必检异常

Java语言将派生RuntimeException和Error的所有异常称为“未检查异常”,而其他异常称为“必检异常”。Java程序中,可以不处理未检查异常。一旦出现“未检查异常”通常表示程序存在错误,需要修改。

对抛出的“必检异常”的程序中要做出相应的处理,使得程序进入可恢复运行的状态。如果没有异常处理器对“必检异常”进行处理,当前执行的线程会出现中断,程序无法执行。

3.异常类的常见方法

Exception类从父亲Throwable那里还继承了若干方法,其中常用的有:

1)public String toString();

toString()方法返回描述当前Exception 类信息的字符串。

2)public void printStackTrace();

printStackTrace()方法没有返回值,它的功能是完成一个打印操作,在当前的标准输出(一般就是屏幕)上打印输出当前异常对象的堆栈使用轨迹,也即程序先后调用执行了哪些对象或类的哪些方法,使得运行过程中产生了这个异常对象。

二、抛出异常和捕获异常
用throw语句抛出的格式

返回类型 方法名(参数列表) throws 要抛出的异常类名列表{

throw 异常类实例;

}

注意:throws是声明抛出的异常,一般是抛出一个“已检查异常”和用throw语句直接抛出异常时,最好用throws语句进行异常声明

2.异常的捕获

try{ //可能出现异常的程序代码

语句1

语句n

}

catch(异常类型1 异常对象e1){

… //进行异常类型1的处理

}

catch(异常类型2 异常对象e2){

… //进行异常类型2的处理

}

catch(异常类型3 异常对象e3){

… //进行异常类型3的处理

}

finally{ //其他处理程序代码

语句1

语句n

}

try-with-resource语句

Java SE 8.0增加了try-with-resource语句。try-with-resource语句的作用将执行完声明的一个或多个资源操作后,会将资源关闭。例如,控制台输入时,使用的java.util.Scanner类就是一个实现java.lang.AutoCloseable接口的类。在使用try-with-resource实现控制台输入前可以写成如下形式:

try(Scanner scanner=new Scanner(System.in)){

int num1=scanner.nextInt();

}catch(Exception e){

}

在上述表达中,会将资源对象scanner的操作依次完成,无论完成顺利与否都会将执行scanner.close(),关闭资源scanner对象。try子句的括号内可以定义一个或多个资源,资源之间用分号“;”隔开。

十三、文件处理

一、File类
(1)File类
Java提供了一个java.io.File类来实现对真实文件的抽象。

值得注意的是,File类毕竟是对真实文件的抽象,用File对象可以用来读取或处理与磁盘文件相关的信息,例如:权限、时间、日期和目录路径等。它并不是真正的代表一个文件。这就意味着,用户并不能对File类的对象进行文件内容的读取、写入、修改、存储等操作。

(2)JavaFX组件中选择文件GUI对话框javafx.stage.FileChooser
实现对文件的选择

FileChooser fileChooser = new FileChooser();

fileChooser.setTitle(“打开源文件”);

fileChooser.getExtensionFilters().addAll(

     new ExtensionFilter("Text Files", "*.txt"),

     new ExtensionFilter("All Files", "*.*"));

File selectedFile = fileChooser.showOpenDialog(primaryStage);

二、Java的类库
(1)字符流类
Java语言中, 抽象类java.io.Reader和java.io.Writer是所有基于字符的数据流类的父类。

类Reader是输入字符流

Writer是输出字符流

Reader和Writer它们可以处理16位的字符。它们的子类以及相应的继承关系根据功能可以分成两个类别:一个是只处理读取和写入的类;另一个是执行其他处理的类。

(2)字节流
在Java语言中,字节流有两大基本类:抽象类java.io.InputStream和java.io.OutputStream,它们是所有基于字节的数据流类的父类。

类InputStream是输入字节流

OutputStream是输出字节流

InputStream和OutputStream它们则处理8位的字节数据。它们的子类以及相应的继承关系根据功能可以分成两个类别:一个是只处理读取和写入的类;另一个是可以执行其他处理的类。

三、序列化
(1)序列化
Java语言中允许实现java.io.Serializable接口的对象作为一个整体单位进行读写。处理对象读写的流成为对象流。对象流实现了对象信息字节化。在Java语言中也是特指对象字节输入流java.io.ObjectInputStream和字节输出流java.io.ObjectOutputStream。对象字节输出流java.io.ObjectOutputStream实例调用writeObject()方法将Java对象写入到字节输出流中,而对象字节输入流则是调用readObject()方法将接受的字节信息进行重构成Java对象。

具体步骤:
第一步:为了实现可序列化的对象,该对象所在的类必须是可以实现java.io. Serializable接口的类。例如,

public class MyObject implements Serializable{//定义类

int number;

String information;

public MyObject(int n,String s){

number=n;

information=s;

}

}

第二步:定义一个可序列化的对象。例如:

MyObject myObject=new MyObject(23,”Hello");

第三步:创建对象的输入和输出流。在java.io包中,能和对象的输入和输出流结合起来的类就只能是通过ObjectInputStream类和ObjectOutputStream类。例如:

//序列化过程

ObjectOutputStream

output=new ObjectOutputStream(new FileOutputStream(“source.txt”));

try{

 output.writeObject(myObject);//将序列化对象写入到文件中;

 output.close();//关闭对象输出流;

}catch(IOException e){

 e.printStackTrace();

}

(2)反序列化
步骤

ObjectInputStream

Input=new ObjectInputStream(new FileInputStream(“source.txt”));

try{

 myObject=(MyObject)input.readObject();

 input.close();

}catch(IOException e){

 e.printStackTrace();

}

十四、数据库

一、访问数据库
(1)导入JDBC类;
import java.sql.*;

类或接口

描述

java.sql.DriverManager

驱动程序管理

java.sql.Connection

实现连接数据的处理

java.sql.SQLException

处理任何SQL操作失败引起的异常

java.sql.Statement

java.sql.PreparedStatement

java.sql.CallableStatement

实现SQL的相关处理

java.sql.ResultSet

实现SQL的相关处理的结果

(2)装载/注册驱动程序;
驱动程序是一个软件,一般由开发商提供。驱动程序名主要查看对应的帮助文件。

例如:

MySQL有mySql for Java的驱动程序.

Class.forName(“com.mysql.jdbc.Driver");

Class.forName(“com.mysql.cj.jdbc.Driver”);

(3)连接数据库;
Connection

conn=DriverManager.getConnection(jdbcURL,userName,password);

jdbcURL是字符串对象,定义定位数据库的JDBC URL;

userName是字符串对象,指定的是访问数据库的用户名;

password是字符串对象,指定的是访问数据库的用户密码。

Connection conn =

                 DriverManager.getConnection(“jdbc:mysql://localhost:3306/dataname",

                        “ username”,“password");

或:

String url =

“jdbc:mysql://localhost:3306/dataname?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8”;

Connection conn = DriverManager.getConnection(url,“用户名”,"密码”);

(4)创建语句(Statement)对象;
JDBC有三个接口可以实现SQL语句和检索,它们是:

Statement接口、

PreparedStatement接口

CallableStatement接口。

其中PreparedStatement继承了Statement,CallableStatement是PreparedStatement子接口。通过创建这些接口的实现对象,可以达到向数据库发送SQL语句的作用。

(5) 执行SQL语句;
一旦执行语句有效对象创建成功,就可以执行相应的SQL命令和操作了。有多种方法可以实现SQL语句的调用。有一种常用的方式是通过Statement的对象executeQuery()、executeUpdate()、execute()、方法来处理各种数据操作

(6)处理结果集;
(7)关闭连接

二、视图层
(1)视图层View示例:(代码部分)

<BorderPane prefHeight=“400.0” prefWidth=“600.0”

        xmlns="http://javafx.com/javafx/8.0.121"

        xmlns:fx="http://javafx.com/fxml/1"

        fx:controller="cn.edu.ncu.chenyi.chapter10.bank.controller.AccountController">

<top>

    <HBox alignment="CENTER">

        <Label text="账户管理子系统"/>

    </HBox>

</top>

<center>

    <VBox alignment="CENTER">

        <GridPane alignment="CENTER">

            <Label text="编号"  GridPane.columnIndex="0" GridPane.rowIndex="0"/>

            <TextField fx:id="idTxt" GridPane.columnIndex="1" GridPane.rowIndex="0"/>

            <Label text="姓名" GridPane.columnIndex="0" GridPane.rowIndex="1"/>

            <TextField fx:id="nameTxt" GridPane.columnIndex="1" GridPane.rowIndex="1"/>

            <Label text="出生日期" GridPane.columnIndex="0" GridPane.rowIndex="2"/>

            <TextField fx:id="birthdayTxt" GridPane.columnIndex="1" GridPane.rowIndex="2"/>

            <Label text="性别" GridPane.columnIndex="0" GridPane.rowIndex="3"/>

            <TextField fx:id="genderTxt" GridPane.columnIndex="1" GridPane.rowIndex="3"/>

            <Label text="存款" GridPane.columnIndex="0" GridPane.rowIndex="4"/>

            <TextField fx:id="moneyTxt" GridPane.columnIndex="1" GridPane.rowIndex="4"/>

            <ImageView fx:id="photoImageView" GridPane.columnIndex="2" GridPane.rowIndex="0" GridPane.rowSpan="4">

                <image>

                    <Image url="@../images/boy.png" />

                </image>

            </ImageView>

            <Button alignment="CENTER" text="浏览图片" onAction="#selectPhoto" GridPane.columnIndex="2" GridPane.rowIndex="4"/>

        </GridPane>

        <HBox alignment="CENTER" spacing="5.0">

            <Button text="新建记录" onAction="#createRecord"/>

            <Button text="修改记录" onAction="#updateRecord"/>

            <Button text="删除记录" onAction="#deleteRecord"/>

            <Button text="检索记录" onAction="#queryRecord"/>

        </HBox>

    </VBox>

</center>


三、实体层
实体层Account

import java.io.Serializable;

import java.sql.Blob;

import java.sql.Timestamp;

import java.util.List;

/**

  • Account.java

  • Copyright: Nanchang University Information School Chen Yi

  • @author 陈轶

  • Created on 2019-05-20 15:44

  • Description:定义账户实体

**/

public class Account implements Serializable {

private int id;

private String name;

private Timestamp birthday;

private String gender;

private double money;

private Blob photo;



private List<Transaction> transactionList;



public int getId() {

    return id;

}



public void setId(int id) {

    this.id = id;

}



public String getName() {

    return name;

}



public void setName(String name) {

    this.name = name;

}



public Timestamp getBirthday() {

    return birthday;

}



public void setBirthday(Timestamp birthday) {

    this.birthday = birthday;

}



public String getGender() {

    return gender;

}



public void setGender(String gender) {

    this.gender = gender;

}



public double getMoney() {

    return money;

}



public void setMoney(double money) {

    this.money = money;

}



public Blob getPhoto() {

    return photo;

}



public void setPhoto(Blob photo) {

    this.photo = photo;

}



public void addTransaction(Transaction transaction){

    transactionList.add(transaction);

}



public void displayTransactions(){

    transactionList.forEach(System.out::println);

}



@Override

public String toString() {

    return "账号{" +

            "id=" + id +

            ", name='" + name + '\'' +

            ", birthday=" + birthday +

            ", gender='" + gender + '\'' +

            ", money=" + money +

            '}';

}

}

四、数据访问层
数据访问层DAO层

a)AccountDAO

package cn.edu.ncu.chenyi.chapter10.bank.dao;

/**

  • @author 陈轶

*/

import cn.edu.ncu.chenyi.chapter10.bank.entity.Account;

import java.io.File;

import java.sql.Timestamp;

import java.util.List;

public interface AccountDAO {

public void insertAccount(String name, Timestamp birthday,

                          String gender, double money,File file);

public void deleteAccountById(int id);

public List<Account> findAll();

public List<Account> findByName(String name);

public Account findById(int id);

public void updateAccount(int id,Account account);

public void updateAccount(int id,String name,

                          Timestamp birthday,String gender,

                          double money,File file);

}

b)实现AccountDAO的AccountDAOImpl

import cn.edu.ncu.chenyi.chapter10.bank.entity.Account;

import cn.edu.ncu.chenyi.chapter10.bank.utils.DataConvertor;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.sql.*;

import java.util.ArrayList;

import java.util.List;

/**

  • AccountDAOImpl.java

  • Copyright: Nanchang University Information School Chen Yi

  • @author 陈轶

  • Created on 2019-05-20 15:56

  • Description:

**/

public class AccountDAOImpl extends DBConnection implements AccountDAO {

@Override

public void insertAccount(String name, Timestamp birthday,

                          String gender, double money, File file) {

    String sql = "insert into account(accountName," +

                 "accountBirthday," +

                 "accountGender," +

                 "accountMoney, " +

                 "accountPhoto)  values(?,?,?,?,?)" 

    try (Connection conn = getConnection();

         FileInputStream fin=new FileInputStream(file)){

        PreparedStatement pstmt = conn.prepareStatement(sql);

        pstmt.setString(1,name);

        pstmt.setTimestamp(2,birthday);

        pstmt.setString(3,gender);

        pstmt.setDouble(4,money);

        if(fin!=null)

            pstmt.setBinaryStream(5,fin,fin.available());

        else

            pstmt.setBinaryStream(5,null);

        pstmt.executeUpdate();

    } catch (SQLException | IOException e) {

        e.printStackTrace();

    }

}

@Override

public void deleteAccountById(int id) {

    String sql = "delete from account where accountId = ?";

    try(Connection conn = getConnection();) {

        PreparedStatement pstmt = conn.prepareStatement(sql);

        pstmt.setInt(1,id);

        pstmt.execute();

    } catch (SQLException e) {

        e.printStackTrace();

    }

}

@Override

public List<Account> findAll() {

    String sql = "select * from account";

    List<Account> list = new ArrayList<>();

    try(Connection conn = getConnection();

        PreparedStatement pstmt = conn.prepareStatement(sql);

        ResultSet rs =pstmt.executeQuery()){

        while(rs.next()){

            Account account = new Account();

            account.setId(rs.getInt(1));

            account.setName(rs.getString(2));

            account.setBirthday(rs.getTimestamp(3));

            account.setGender(rs.getString(4));

            account.setMoney(rs.getDouble(5));

            list.add(account);

        }

    }catch(SQLException e){

        e.printStackTrace();

    }

    return list;

}

@Override

public List<Account> findByName(String name) {

    String sql = "select * from account where accountName=?";

    List<Account> list = new ArrayList<>();

    Connection conn = getConnection();

    try(PreparedStatement pstmt = conn.prepareStatement(sql)){

        pstmt.setString(1,name);

        ResultSet rs =pstmt.executeQuery();

        while(rs.next()){

            Account account = new Account();

            account.setId(rs.getInt(1));

            account.setName(rs.getString(2));

            account.setBirthday(rs.getTimestamp(3));

            account.setGender(rs.getString(4));

            account.setMoney(rs.getDouble(5));

            list.add(account);

        }

    }catch(SQLException e){

        e.printStackTrace();

    }

    return list;

}

//…以下略

}

五、控制层
控制层

package cn.edu.ncu.chenyi.chapter10.bank.controller;

import cn.edu.ncu.chenyi.chapter10.bank.dao.AccountDAO;

import cn.edu.ncu.chenyi.chapter10.bank.dao.AccountDAOImpl;

import cn.edu.ncu.chenyi.chapter10.bank.entity.Account;

import cn.edu.ncu.chenyi.chapter10.bank.utils.DataConvertor;

import javafx.fxml.FXML;

import javafx.fxml.Initializable;

import javafx.scene.control.TextField;

import javafx.scene.image.Image;

import javafx.scene.image.ImageView;

import javafx.stage.FileChooser;

import java.io.File;

import java.io.FileInputStream;

import java.net.URL;

import java.sql.Timestamp;

import java.util.ResourceBundle;

/**

  • AccountController.java

  • Copyright: Nanchang University Information School Chen Yi

  • @author 陈轶

  • Created on 2019-05-20 19:52

  • Description:

**/

public class AccountController implements Initializable {

@FXML

private TextField idTxt;

@FXML

private TextField nameTxt;

@FXML

private TextField genderTxt;

@FXML

private TextField birthdayTxt;

@FXML

private TextField moneyTxt;

@FXML

private ImageView photoImageView;



private AccountDAO dao;

private File curPhotoFile;

/**

 * 初始化

 * @param location

 * @param resources

 */

@Override

public void initialize(URL location, ResourceBundle resources) {

    dao = new AccountDAOImpl();   //利用多态性,初始化AccountDAO的对象dao

}



@FXML

public void selectPhoto(){

    FileChooser fileChooser = new FileChooser();

    fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("jpg文件","*.jpg"),

            new FileChooser.ExtensionFilter("png文件","*.png"),

            new FileChooser.ExtensionFilter("gif文件","*.gif"),

            new FileChooser.ExtensionFilter("所有文件","*.8"));

    curPhotoFile = fileChooser.showOpenDialog(null);

    if(curPhotoFile!=null)

        photoImageView.setImage(new Image(curPhotoFile.toURI().toString()));

}

@FXML

public void createRecord(){

    String name = nameTxt.getText();

    String gender = genderTxt.getText();

    String birthdayString = birthdayTxt.getText();

    Timestamp birthday = DataConvertor.frmStringToTimeStamp(birthdayString);

    String moneyString = moneyTxt.getText();

    double money = DataConvertor.frmStringToDouble(moneyString);

    if(curPhotoFile!=null){

        dao.insertAccount(name,birthday,gender,money,curPhotoFile);//调用dao

        reset();

        idTxt.setDisable(false);

        curPhotoFile = null;

    }

}



@FXML

public void updateRecord(){

    idTxt.setDisable(false);

    String idString=idTxt.getText();

    int id= Integer.valueOf(idString);

    String name = nameTxt.getText();

    String gender = genderTxt.getText();

    String birthdayString = birthdayTxt.getText();

    Timestamp birthday = DataConvertor.frmStringToTimeStamp(birthdayString);

    String moneyString = moneyTxt.getText();

    double money = DataConvertor.frmStringToDouble(moneyString);



    if(curPhotoFile!=null) {

        dao.updateAccount(id,name,birthday,gender,money,curPhotoFile);

        curPhotoFile = null;

    }else{

        Account account = dao.findById(Integer.valueOf(idTxt.getText()));

        account.setName(name);

        account.setGender(gender);

        account.setBirthday(birthday);

        account.setMoney(money);

        dao.updateAccount(id,account);

    }



    reset();

}



@FXML

public void deleteRecord(){

   String id=idTxt.getText();

   dao.deleteAccountById(Integer.valueOf(id));

   reset();

}



@FXML

public void queryRecord(){

    String idString=idTxt.getText();



    Account account = dao.findById(Integer.valueOf(idString));

    if(account == null)

        return;

    nameTxt.setText(account.getName());

    genderTxt.setText(account.getGender());

    birthdayTxt.setText(DataConvertor.frmTimestampToString(account.getBirthday()));

    moneyTxt.setText(""+account.getMoney());

    File file=DataConvertor.frmBlobToFile(account.getPhoto());

    Image image = new Image(file.toURI().toString());

    photoImageView.setImage(image);

}



private void reset(){

    idTxt.setText("");

    nameTxt.setText("");

    genderTxt.setText("");

    birthdayTxt.setText("");

    moneyTxt.setText("");

    curPhotoFile = null;

}

}

;