声明:本系列教程为本人目前编写的一部教材,请勿擅自转载。
如需使用请联系本人:lilizong【at】gmail.com
因图片较多,未将图片一一展示!
教程 4 信用卡应用程序
4.1 类和对象
4.2 包
4.3 方法
4.4 方法的参数
4.5 字符串
4.6 构造函数
4.7 关键字 this
4.8 if选择语句
4.9 if…else选择语句
4.9 if…else if…else选择语句
教学目标
通过本教程的学习,读者将了解一下内容:
l 类和对象
l 包
l 方法
l 方法的参数
l 字符串
l 构造函数
l 关键字 THIS
l 选择语句
面向对象的程序设计( Object Oriented programming, 简称 OOP )是将现实世界中的实体进行抽象而组成的一个程序实体。
在面向对象的程序设计中,对象用来表述某一具体的实体。类是面向对象程序设计的核心和本质,是对象的抽象描述与表示。
现实世界中,人们经常提取出某些实体的共同特征,然后将它们归属到同一类别中。例如,把鸡、猫、狗、牛等都归结为动物。对应面向对象程序设计,这里的鸡、猫、狗、牛就是对象,而动物就是类。 Java 语言中,通常先定义类,然后再根据当前类定义对象。定义的方式为:
类名 对象名 =new 类名 ();
类是一个抽象,因此可以有自己的属性,该属性通常用某一个变量来进行描述。类的属性是所有对象所共有的,是抽象的,而对象的属性微观的、具体的。例如上述的动物中,如果把腿(脚)的个数作为属性,那么每种动物都有这个属性,但是并不能具体描述动物的腿(脚)的个数,而每个对象(鸡、猫、狗、牛)对应这个属性都有具体的值。
当需要引用该属性时,通过通过下述方式:
对象名 . 属性名
下面定义一个信用卡的类,类中定义了 float 型变量 money ,用它来表示当前账户的余额。
1 public class CreditCard1 {
2 float money;
3 public static void main(String args[])
4 {
5 CreditCard1 john=new CreditCard1();
6 john.money=1000;
7 System.out.println("john 的账户上有 "+john.money+" 元 ");
8 john.money=john.money-800; //john 买了一块手表,消费了 800 元。
9 System.out.println("john 购买手表花了 800 元 ");
10 System.out.println(" 此时, john 的账户上有 "+john.money+" 元 ");
11 }
12 }
在程序中首先定义了一个类“ CreditCard1 ”,类中有一个变量 money 用来存取当前的账户余额。在程序的第 5 行定义了当前类的一个对象 john ,表示开了一张具体的信用卡 john 。在第 6 行,对信用卡进行了充值,充值后账面的余额为 1000 元。在第 7 行对当前的账户余额进行了显示。在第 8 行将对象 john 的 money 属性进行算数运算,即从其账面上减去 800 元,此操作用来模拟该信用卡的购买手表消费。第 9 、 10 行对账户信息进行显示,显示购买手表后账户余额情况。
运行程序,程序的运行结果如图 4.1 所示。
图 4.1 程序运行结果
Java 语言中每个类都包含在一个包中,包是唯一命名的类的集合。简单理解,包就是管理若干源文件的一个文件夹,因此有效使用包,能够提高程序的可读性和开发效率。包语句的格式如下:
Package packageName;
包名的第一个字母通常小写。
下面将新建的文件建在包 lesson4 中,具体代码如下:
1 package lesson4;
2
3 public class CreditCard2 {
4 float money;
5 public static void main(String args[])
6 {
7 CreditCard2 john=new CreditCard2();
8 john.money=1000;
9 System.out.println("john 的账户上有 "+john.money+" 元 ");
10 john.money=john.money-800;
11 System.out.println("john 购买手表花了 800 元 ");
12 System.out.println(" 此时, john 的账户上有 "+john.money+" 元 ");
13 }
14 }
首先对程序进行编译,在当前目录“ e:/book/demo/lesson4 ”下执行“ javac CreditCard2.java ”后按回车键,如图 4.2 所示。
图 4.2 编译源程序
在当前目录下执行“ cd.. ”回到上一级目录,然后执行“ java lesson4.CreditCard2 ”,得到运行结果如图 4.3 所示。执行语句“ java lesson4.CreditCard2 ”的含义为执行当前目录下“ lesson4 ”包中的类文件“ CreditCard2 ”。
图 4.3 程序运行结果
在现实世界中,每个实体通常除了具有自身的属性外,大多还具有动态行为特征。例如动物不仅仅有体重、腿(脚)个数等静态属性,还具有跑、跳、吃等动态行为特征。在面向对象程序设计中,类由变量和方法来描述,变量对应的是静态属性,方法对应的是动态属性。因此,通常应用方法来完成一个特定的操作。
方法的定义格式为:
返回值数据类型 方法名 ( )
{
语句块
}
返回值类型值方法操作完成后所返回数据的数据类型,如果当前没有任何的返回值,则定义为“ void ”表示无返回值。语句块即为方法的具体实现。
定义了方法后,就可以对其进行引用,引用(调用)方法的方式为:
对象名 . 方法名 ()
下面在信用卡的应用程序中定义两个方法,其中一个是购买手表( buyWatch )的方法,该方法首先实现将账户余额减去 800 元,然后显示“购买手表花了 800 元”;另外一个是显示( show )的方法,该方法能够显示当前信用卡上的余额信息。
修改后的程序为:
1 package lesson4;
2
3 public class CreditCard3 {
4 float money;
5 void buyWatch()
6 {
7 money=money-800;
8 System.out.println(" 购买手表花了 800 元 ");
9 }
10 void show()
11 {
12 System.out.println(" 当前账上余额为 "+money+" 元 ");
13 }
14 public static void main(String args[])
15 {
16 CreditCard3 john=new CreditCard3();
17 john.money=1000;
18 john.show();
19 john.buyWatch();
20 john.show();
21 }
22 }
程序第 5 ~ 9 行定义了一个 buyWatch 方法,表示购买一块 800 元的手表。方法体内首先将账面余额减去 800 元,然后打印了提示信息。第 10 ~ 13 行定义了方法 show ,用来显示当前账上余额。在 main 函数中, 18 行、 20 行对函数 show 进行了调用以显示账上余额;第 19 行对 buyWatch 进行了调用,首先处理了账面余额然后打印了账面余额信息。
对该程序进行编译,运行,结果如图 4.4 所示。
图 4.4 程序运行结果
上述的方式实现了购买手表和打印输出。在实际使用过程中信用卡可能需要购买不同价格的物品。为了实现更多功能,需要使用带有参数的方法。带有参数的方法,能够通过更灵活的方式来实现对当前对象的操作。
在方法定义过程中使用的参数称为形式参数,在程序运行过程中,方法调用时所使用的参数称为实际参数。参数在传递过程中应该保证实参和形参在个数、类型上的一致性。
修改上述程序如下:
1 package lesson4;
2
3 public class CreditCard4 {
4 float money;
5 void shopping(float goodsMoney)
6 {
7 money=money-goodsMoney;
8 System.out.println(" 购物刷卡,花掉 "+goodsMoney+" 元 ");
9 }
10 void show()
11 {
12 System.out.println(" 当前账上余额为 "+money+" 元 ");
13 }
14 public static void main(String args[])
15 {
16 CreditCard4 john=new CreditCard4();
17 john.money=1000;
18 john.show();
19 john.shopping((float)200);
20 john.show();
21 }
22 }
程序中第 5 行定义了一个 shopping 方法,该方法有一个参数 goodsMoney ,用来表示每次刷卡消费的金额。方法中首先,通过算数运算减去刷卡金额,然后通过输出语句对当前的消费情况进行打印输出。
程序第 19 行“( float ) 200 ”表示强制类型转换。因为当前的实参类型为 int ,而形参为 float ,它们的类型不一致,为了保证类型的一致需要进行强制类型转换。强制类型转换的形式为在需要转换的变量前加上由括号组成的要转化成的数据类型。
编译并运行该程序,如图 4.5 所示。
图 4.5 编译运行过程
Java 语言中,字符串是作为对象而存在的,每个字符串都是 String 类的对象。定义字符串的方法为:
String 字符串名 = 字符串常量值
定义时,可以根据需要选择是否对字符串进行赋初值。例如,定义一个名字为 goodsName 的字符串变量,可以采用如下方式:
String goodsName ;
或者
String goodsName ="TV";
在实际操作中,通常需要用用户名等信息来对不同的信用卡进行识别、管理等操作。为了便于管理,在信用卡类中定义持卡人姓名( name )这个属性。
修改后的程序如下:
1 package lesson4;
2
3 public class CreditCard5 {
4 double money;
5 String name;
6 void shopping(String goodsName,double goodsMoney)
7 {
8 money=money-goodsMoney;
9 System.out.println(name+" 购买 "+goodsName+", 刷卡花掉 "+goodsMoney+" 元 ");
10 }
11 void show()
12 {
13 System.out.println(name+" 当前账上余额为 "+money+" 元 ");
14 }
15 public static void main(String args[])
16 {
17 CreditCard5 john=new CreditCard5();
18 john.name="Ross John";
19 john.money=1000;
20 CreditCard5 MW=new CreditCard5();
21 MW.name="Mke walt";
22 MW.money=2000;
23 john.show();
24 john.shopping("MP3",200.50);
25 john.show();
26 MW.show();
27 MW.shopping("TV", 500);
28 MW.show();
29 }
30 }
编译运行该程序,如图 4.6 所示。
图 4.6 编译运行示意图
在定义一个对象后,可以通过给对象赋值的方式来完成对象的初始化工作。但是,这样操作起来比较麻烦,而且不直观。因此, Java 在类里提供了一个特殊的成员函数,叫做构造函数( Constructor )。一个构造函数是对象被创建时初始对象的成员函数。它具有和它所在的类完全一样的名字。一旦定义好一个构造函数,创建对象时就会自动调用它。构造函数没有返回类型,即使是 void 类型也没有。这是因为一个类的构造函数的返回值的类型就是这个类本身。构造函数的任务是初始化一个对象的内部状态,所以用 new 操作符创建一个实例后,立刻就会得到一个清楚、可用、具体的对象。
需要注意的是, Java 语言中在定义类的过程中会自动定义没有参数的构造函数。在编写程序的过程中,如果创建了自己的构造函数,那么原先的没有参数的构造函数便不再存在。以后在定义对象过程中,必须按照自定义构造函数的格式来定义新的对象。
修改上述程序代码,在类中添加构造函数,实现如下:
1 package lesson4;
2
3 public class CreditCard6{
4 double money;
5 String name;
6 CreditCard6(String sName,double sMoney)
7 {
8 name=sName;
9 money=sMoney;
10 }
11 void shopping(String goodsName,double goodsMoney)
12 {
13 money=money-goodsMoney;
14 System.out.println(name+" 购买 "+goodsName+", 刷卡花掉 "+goodsMoney+" 元 ");
15 }
16 void show()
17 {
18 System.out.println(name+" 当前账上余额为 "+money+" 元 ");
19 }
20 public static void main(String args[])
21 {
22 CreditCard6 mike=
23 new CreditCard6("ROBER MIKE",2356);
24 CreditCard6 ross=
25 new CreditCard6("RIGHT ROSS",8957);
26 mike.show();
27 mike.shopping("MP3",200.50);
28 mike.show();
29 ross.show();
30 ross.shopping("TV", 500);
31 ross.show();
32 }
33 }
程序中,第 6 ~ 10 行定义了一个构造函数。该函数内有 3 参数,分别用来实现对 ID , nmae , money 的初始化工作。在第 22 ~ 25 行定义了两个对象 mike 、 ross 。在定义对象的过程中均使用了在第 6 ~ 10 行定义的构造函数。
编译、运行该程序,如图 4.7 所示。
图 4.7 编译、运行显示
this 代表的是当前类的对象。因此,在定义构造函数的过程中,可以应用 this 来有效区分参数和对象本身的参数。
为了提高程序的可读性和安全性,通常将构造函数的参数名定义成和要赋值的变量具有同样的变量名,然后再通过应用 this 来对两者进行区分。
进一步完善程序,修改程序代码如下:
1 package lesson4;
2
3 public class CreditCard7{
4 double money;
5 String ID;
6 String name;
7 CreditCard7(String ID,String name,double money)
8 {
9 this.ID=ID;
10 this.name=name;
11 this.money=money;
12 }
13 void shopping(String goodsName,double goodsMoney)
14 {
15 money=money-goodsMoney;
16 System.out.println(name+" 购买 "+goodsName+", 刷卡花掉 "+goodsMoney+" 元 ");
17 }
18 void show()
19 {
20 System.out.println(" 持卡人为: "+name);
21 System.out.println(" 账号为: "+ID+" 的账上余额为 "+money+" 元 ");
22 }
23 public static void main(String args[])
24 {
25 CreditCard7 mike=
26 new CreditCard7("9558 8726 8956 3201","ROBER MIKE",2356);
27 CreditCard7 ross=
28 new CreditCard7("9558 8588 7777 3205","RIGHT ROSS",8957);
29 mike.show();
30 mike.shopping("MP3",200.50);
31 mike.show();
32 ross.show();
33 ross.shopping("TV", 500);
34 ross.show();
35 }
36 }
程序第 7 ~ 12 行定义了构造函数,构造函数内的参数名与变量名相同,因此在赋值的过程中采用了关键字 this 来进行区分。
编译、运行程序,如图 4.8 所示。
图 4.8 编译、运行情况
信用卡在使用的过程中,是不能够无限透支的。因此,在购物时需要对当前的消费额和卡上余额进行比较。如果当前的消费额超过了卡上余额和透支额度,那么消费应当被禁止。
对两个数进行比较时需要用到关系运算符。常用关系运算符有 < 、 > 、 <= 、 >= 、 = = 、 != 等。如果判断比较的结果符合给定关系,则关系运算的结果为真 (true) ;否则,为假 (false) 。
If 选择语句根据关系运算表达式结果的真假来决定是否执行某个语句。如果关系运算为真,则执行一个语句;否则,什么也不做。它是程序设计中经常用到的一种语句,格式如下:
if (关系运算表达式)
语句块
1 package lesson4;
2
3 public class CreditCard8{
4 final double CREDIT=-1000;// 信用额度为 1000 ,即可以透支 1000 元。
5 double money;
6 String ID;
7 String name;
8 CreditCard8(String ID,String name,double money)
9 {
10 this.ID=ID;
11 this.name=name;
12 this.money=money;
13 }
14 void shopping(String goodsName,double goodsMoney)
15 {
16 System.out.println(" 持卡人为: "+name);
17 System.out.println(" 账号为: "+ID);
18 System.out.println(" 消费前卡上余额为 "+money+" 元 ");
19 System.out.println("---------------------------");
20 if(money-goodsMoney>=CREDIT)
21 {
22 money=money-goodsMoney;
23 System.out.println(name+" 购买 "+goodsName);
24 System.out.println(" 刷卡花掉 "+goodsMoney+" 元 ");
25 System.out.println(" 消费后卡上余额为 "+money+" 元 ");
26 System.out.println("---------------------------");
27 }
28 }
29 public static void main(String args[])
30 {
31 CreditCard8 mike=
32 new CreditCard8("9558 8726 8956 3201","ROBER MIKE",100);
33 CreditCard8 ross=
34 new CreditCard8("9558 8588 7777 3205","RIGHT ROSS",100);
35 mike.shopping("MP3",500.50);
36 ross.shopping("TV", 5000);
37 }
38 }
程序代码中第 20 ~ 27 行对当前的消费情况进行判断,如果当前的消费在信用额度内,则允许持卡人消费,并打印消费信息;如果消费的金额超过了信用额度,则拒绝当前的消费。
编译、运行该程序,如图 4.9 所示。从运行情况可以看出,用户 ROBER MIKE 的消费在信用额度内,消费成功。用户 RIGHT ROSS 的消费超过了信用额度,消费失败。
图 4.9 编译、运行情况
程序应该能够很好地跟用户进行交流,对于出现的问题应该能够给出反馈信息。因此,在不能够消费的情况下要给出一些必要的提示。这就要用到 if…else 语句,它的格式为:
if (关系运算表达式)
语句块 1
else
语句块 2
当关系运算表达式结果为真时,执行语句块 1 ;否则执行语句块 2 。
修改程序,代码如下:
1 package lesson4;
2
3 public class CreditCard9{
4 final double CREDIT=-1000;// 信用额度为 1000 ,即可以透支 1000 元。
5 double money;
6 String ID;
7 String name;
8 CreditCard9(String ID,String name,double money)
9 {
10 this.ID=ID;
11 this.name=name;
12 this.money=money;
13 }
14 void shopping(String goodsName,double goodsMoney)
15 {
16 System.out.println(" 持卡人为: "+name);
17 System.out.println(" 账号为: "+ID);
18 System.out.println(" 消费前卡上余额为 "+money+" 元 ");
19 System.out.println("---------------------------");
20 if(money-goodsMoney>=CREDIT)
21 {
22 money=money-goodsMoney;
23 System.out.println(name+" 购买 "+goodsName);
24 System.out.println(" 刷卡花掉 "+goodsMoney+" 元 ");
25 System.out.println(" 消费后卡上余额为 "+money+" 元 ");
26 System.out.println("---------------------------");
27 }
28 else
29 {
30 System.out.println(" 消费金额超过信用额度 , 请选择其他方式 ");
31 System.out.println(" 此时卡上余额仍旧为 "+money+" 元 ");
32 System.out.println("---------------------------");
33 }
34 }
35 public static void main(String args[])
36 {
37 CreditCard9 mike=
38 new CreditCard9("9558 8726 8956 3201","ROBER MIKE",100);
39 CreditCard9 ross=
40 new CreditCard9("9558 8588 7777 3205","RIGHT ROSS",100);
41 mike.shopping("MP3",500.50);
42 ross.shopping("TV", 5000);
43 }
44 }
程序第 21 ~ 33 行为 if…else 选择语句。当关系运算表达式 money-goodsMoney>=CREDIT 成立时,执行第 22 ~ 26 行代码;否则,执行第 30 ~ 32 行代码。
编译,运行程序,如图 4.10 所示。
图 4.10 编译、运行情况
信用卡在丢失后应该允许持卡人挂失,挂失后任何人不能应用信用卡进行消费;当持卡人找回信用卡后,应该能够将信用卡解挂,解挂后的信用卡应该能够正常使用。
因此,在消费时就要对多个条件进行判断,既要判断当前的信用卡是否已经被挂失,又要判断当前的消费是否超过信用额度。这就要用到 if…else if…else 语句,进行多条件判断,其格式如下:
if (关系运算表达式 1 )
语句块 1
else if (关系运算表达式 2 )
语句块 2
else
语句块 3
程序运行时,首先判断关系运算表达式 1 的结果,如果结果为真,则执行语句块 1 ;否则继续判断关系表达式 2 ,如果关系表达式 2 为真,则执行语句块 2 ;否则,执行语句块 3 。根据需要,可以有若干个 else if 语句。
根据需要,对程序进行修改,如下:
1 package lesson4;
2
3 public class CreditCard10{
4 final double CREDIT=-1000;// 信用额度为 1000 ,即可以透支 1000 元。
5 double money;
6 String ID;
7 String name;
8 // 定义变量 flag 表示挂失情况
9 // 当 flag=1 ,表示账户被挂失,处于锁定状态
10 // 当 flag=1 时,表示账户状态正常
11 int flag;
12 CreditCard10(String ID,String name,double money)
13 {
14 this.ID=ID;
15 this.name=name;
16 this.money=money;
17 }
18 // 定义一个方法 lost ,用于挂失账户
19 void lost()
20 {
21 this.flag=1;
22 System.out.println(" 持卡人为: "+name);
23 System.out.println(" 账号为: "+ID);
24 System.out.println(" 挂失成功,账户处于锁定状态 ");
25 System.out.println("---------------------------");
26 }
27 // 定义一个方法 find ,用于将账户解挂
28 void find()
29 {
30 this.flag=0;
31 System.out.println(" 持卡人为: "+name);
32 System.out.println(" 账号为: "+ID);
33 System.out.println(" 解挂成功,账户处于正常状态 ");
34 System.out.println("---------------------------");
35 }
36 void shopping(String goodsName,double goodsMoney)
37 {
38 System.out.println(" 持卡人为: "+name);
39 System.out.println(" 账号为: "+ID);
40 System.out.println(" 消费前卡上余额为 "+money+" 元 ");
41 if(flag==1)
42 {
43 System.out.println(" 此时信用卡处于挂失锁定状态,无法进行消费 ");
44 System.out.println(" 卡上余额仍旧为 "+money+" 元 ");
45 System.out.println("---------------------------");
46 }
47 else if(money-goodsMoney
48 {
49
50 System.out.println(name+" 想购买 "+goodsName);
51 System.out.println(" 此时,消费金额超过信用额度 , 请选择其他方式 ");
52 System.out.println(" 卡上余额仍旧为 "+money+" 元 ");
53 System.out.println("---------------------------");
54 }
55 else
56 {
57 money=money-goodsMoney;
58 System.out.println(name+" 购买 "+goodsName);
59 System.out.println(" 刷卡花掉 "+goodsMoney+" 元 ");
60 System.out.println(" 消费后卡上余额为 "+money+" 元 ");
61 System.out.println("---------------------------");
62 }
63 }
64 public static void main(String args[])
65 {
66 CreditCard10 mike=
67 new CreditCard10("9558 8726 8956 3201","ROBER MIKE",100);
68 CreditCard10 ross=
69 new CreditCard10("9558 8588 7777 3205","RIGHT ROSS",100);
70 mike.shopping("book", 5);
71 mike.lost();
72 mike.shopping("MP3",500.50);
73 mike.find();
74 mike.shopping("MP3",500.50);
75 mike.shopping(" 汽车 ",50000);
76 ross.shopping("TV", 5000);
77 }
78 }
程序中第 11 行定义了一个变量 flag 用来标识信用卡的状态。当 flag=1 时即表示信用卡处于挂失锁定状态,当 flag=0 时,表示信用卡处于正常状态。第 19 ~ 26 行定义了函数 lost ,用来挂失信用卡。第 21 行将标量 flag 赋值为 1 ,表示信用卡进入挂失锁定状态,第 22 ~ 25 用来显示挂失信息。第 28 ~ 35 行定义了函数 find ,用来对信用卡进行解挂。第 30 行将标量 flag 赋值为 0 ,表示信用卡进入正常状态,第 31 ~ 34 行用来显示解挂成功信息。
编译、运行程序,输出结果如下所示:
持卡人为: ROBER MIKE
账号为: 9558 8726 8956 3201
消费前卡上余额为 100.0 元
ROBER MIKE 购买 book
刷卡花掉 5.0 元
消费后卡上余额为 95.0 元
---------------------------
持卡人为: ROBER MIKE
账号为: 9558 8726 8956 3201
挂失成功,账户处于锁定状态
---------------------------
持卡人为: ROBER MIKE
账号为: 9558 8726 8956 3201
消费前卡上余额为 95.0 元
此时信用卡处于挂失锁定状态,无法进行消费
卡上余额仍旧为 95.0 元
---------------------------
持卡人为: ROBER MIKE
账号为: 9558 8726 8956 3201
解挂成功,账户处于正常状态
---------------------------
持卡人为: ROBER MIKE
账号为: 9558 8726 8956 3201
消费前卡上余额为 95.0 元
ROBER MIKE 购买 MP3
刷卡花掉 500.5 元
消费后卡上余额为 -405.5 元
---------------------------
持卡人为: ROBER MIKE
账号为: 9558 8726 8956 3201
消费前卡上余额为 -405.5 元
ROBER MIKE 想购买汽车
此时,消费金额超过信用额度 , 请选择其他方式
卡上余额仍旧为 -405.5 元
---------------------------
持卡人为: RIGHT ROSS
账号为: 9558 8588 7777 3205
消费前卡上余额为 100.0 元
RIGHT ROSS 想购买 TV
此时,消费金额超过信用额度 , 请选择其他方式
卡上余额仍旧为 100.0 元
---------------------------