1.面向对象学习的三条主线
1)Java类及类的成员:属性、方法、构造器、代码块、内部类;
2)面向对象三大特性:继承、封装性、多态、(抽象性);
3)其他关键字:this、super、static、final、abstract、interface、package、import等
2.面向过程和对象
面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做,如:1.打开冰箱;2。把大象装进冰箱;3.把冰箱门关住。
面向对象:强调具备功能的对象,以类/对象为最小单位,考虑谁来做。
人{
打开(冰箱){
冰箱.开门();
}
抬起(大象){
大象.进入(冰箱);
}
关闭(冰箱){
冰箱.闭合();
}
}
冰箱{
开门(){}
闭合(){}
}
大象{
进入(冰箱){}
}
2.1.类和对象
面向对象中,类和对象是最基本、最重要的组成单元。类是概念模型,像图纸,定义对象的所有特征和所需的操作;对象是一个具体的实体。
对象 | 用来描述客观事物的一个实体 |
属性 | 对象具有的各种特征 |
方法 | 对象执行的操作 |
类 | 具有相同属性和方法的一组对象的集合,类是对象的抽象,对象是类的具体 |
2.2.面向对象的概述
程序员从面向过程的执行者转化成面向对象的指挥者;面向对象分析方法问题的思路和步骤:1.根据问题需要,选择问题所针对的现实世界中的实体;2.从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类;3.把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构;4.将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。
面向对象的思想概述:类:对一类事务的描述,是抽象的,概念上的定义;对象:实际存在的该类事务的每个个体,因而也称为实例(instance)。
面向对象的理解:类是抽象概念的人;对象是实实在在的某个人;面向对象程序设计的重点是类的设计;类的设计,其实就是设计类的成员。
2.3.万事万物皆对象
在Java语言范畴中,将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构,如:Scanner、String等类;文件:File;网络资源:URL等。涉及到Java语言域前端的Html、后端的数据库交互式,前后端在Java层面交互时,都体现为类、对象。
3.类的设计
属性 = 成员变量 = field = 域、字段;方法 = 成员方法 = 函数 = method;场景类的对象 = 类的实例化 = 实例化类。
类和对象的使用:创建类:设计类的成员;创建类的对象;通过“对象.属性”或“对象.方法”调用对象的结构。
// 类的语法格式
修饰符 class 类名 {
属性声明;
方法声明;
}
说明:修饰符public:类可以被任意访问
类的正文要用{}括起来
// 举例
public class Person{
private int age ; // 声明私有变量 age
public void showAge(int i) { // 声明方法showAge( )
age = i;
}
}
Java类及类成员的使用:Java实例化,即创建类的对象,类名 对象名 = new 类名()。
类的访问机制:同一个类中:类中的方法可以直接访问类中的成员变量(static方法访问非static,编译不通过);不同类中:先创建要访问类的对象,再用对象访问类中定义的成员。
public static void main(String[] args) {
//创建Person类的对象
Person p1 = new Person();
//调用对象的结构、属性和方法
//调用:属性:“对象.属性”
p1.name = "Tom";
p1.isMale = true;
System.out.println(p1.name);
//调用方法:“对象.方法”
p1.eat();
p1.sleep();
p1.talk("Chinese");
System.out.println("------------------------");
Person p2 = new Person();
System.out.println(p2.name);//null
System.out.println("------------------------");
//将p1变量保存的对象地址复制给p3,导致p1和p3指向了堆空间中的同一对象实体。
Person p3 = p1;
System.out.println(p3.name);//Tom
p3.age = 10;
System.out.println(p1.age);
}
}
class Person{
//属性
String name;
int age = 1;
boolean isMale;
//方法
public void eat(){
System.out.println("人可以吃");
}
public void sleep(){
System.out.println("人可以睡觉");
}
public void talk(String language){
System.out.println("人可以说话,使用" + language);
}
创建一个类的多个对象,每个对象都独立拥有一套互不干扰类的属性(非static)。意味着:修改一个对象的属性a,则不影响另一个对象属性a。如:修改xb的legs属性,不影响xh的legs属性。
3.1.内存解析
堆(Heap),此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存 。Java虚拟机规范中的描述:所有的对象实例以及数组都要在堆上分配。
栈(Stack)是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放编译期可知长度的各种基本数据类型、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。 方法执行完自动释放。
方法区(Method Area),用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
引用类型的变量,只能存储两类型:null或地址值(含变量的类型)。
Person person = new Person()内存解析和代码块:1.new用到了Person.class先找到Person.class文件并加载到内存中;2.执行该类中static代码块,如果有的话,给Person.class类进行初始化;3.在堆内存中开辟空间,分配内存地址;4.在堆内存中建立对象的特有属性,并进行默认初始化;5.对属性进行显示初始化;6.对对象进行构造代码块初始化;7.对对象进行对应的构造函数初始化;8.将内存地址赋值给栈内存中的P变量。
4.匿名对象
可不定义对象句柄,而直接调用对象的方法的对象(创建对象没显示赋给一个变量名)。使用情况:一个对象只需要进行一次方法调用,就可使用匿名对象;经常将匿名对象作为实参传递给一个方法调用。
public static void main(String[] args) {
Phone phone = new Phone();
System.out.println(phone);
phone.senEmail();
phone.playGame();
//匿名对象
new Phone().senEmail();
new Phone().playGame();
new Phone().price = 1999;
new Phone().showPrice();//0.0
System.out.println("--------------");
PhoneMall mall = new PhoneMall();
mall.show(phone);
//匿名对象使用
mall.show(new Phone());
}
class PhoneMall{
public void show(Phone phone){
phone.senEmail();
phone.playGame();
}
}
class Phone{
double price;//价格
public void senEmail(){
System.out.println("发送邮件");
}
public void playGame(){
System.out.println("玩游戏");
}
public void showPrice(){
System.out.println(price);
}
}
5.类成员属性
语法格式:修饰符 数据类型 属性名 = 初始化值。修饰符:private、缺省、protected、public;其他修饰符:static、final。数据类型:任何基本数据类型(如int、Boolean) 或任何引用数据类型。属性名:属于标识符,符合命名规则和规范即可。
5.1.属性(成员变量) vs 局部变量
相同点:定义格式:数据类型 变量名 = 变量值;先声明后使用;变量都有对应的作用域。成员变量:类的属性,也是全局变量;局部变量:方法中的参数。
不同点 | 属性(成员变量) | 局部变量 |
类中位置 | 直接定义再类的一对{}内 | 声明再方法内、方法形参、代码块内、构造器形参、构造器内部的变量 |
权限修饰符 | 声明属性时,指明其权限,使用权限修饰符。常用的权限修饰符:private、public、缺省、protected。目前,大家声明属性时,使用缺省的就行 | 不可以使用权限修饰符 |
默认初始化值 | 类的属性,根据其类型,都有默认初始化值。 整形(byte、short、int、long):0; 浮点型(float、double):0.0 字符型(char):0(或'\u0000') 布尔型(boolean):false 引用类型(类、数组、接口):null | 没有默认初始化值。 在调用局部变量前,一定要显示赋值。 |
内存加载位置 | 加载到堆空间(非static) | 加载到栈空间 |
在同一个方法中,不允许有同名的局部变量;在不同的方法中,可以有同名的局部变量。局部变量可以和成员变量同名,并在使用时,局部变量具有更高的优先级。
class User {
// 属性(或成员变量)
String name;
int age = 1;
boolean isMale;
public void talk(String language) {//language:形参,局部变量
System.out.println("人可以说话,使用" + language);
}
public void eat(){
String food = "烙饼";//局部变量
System.out.println("北方人喜欢吃" + food);
}
}
5.2.访问控制修饰符
修饰符 | 定义 |
private | 只能被该类自身的方法访问和修改;该类自身,private修饰符具有最高的保护级别。 |
默认修饰符default | 该类只能被同一包中的类访问和使用,而不能其他包中的类使用;该类自身、同包中的其他类。 |
protected | 该类自身、同包中的其他类、其他包中的子类。 |
public | 可被同一个包或不同包的其他类访问默认修饰符;只可被同一个包的其他类访问。一般情况下,属性就用private修饰;方法就用public修饰 |
5.3.练习对象数组
定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。问题一:打印出3年级(state值为3)的学生信息。问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息。
提示:生成随机数:Math.random(),返回值类型double; 四舍五入取整:Math.round(double d),返回值类型long。此代码是对属性练习的改进:将操作数组的功能封装到方法中。
public class StudentTest {
public static void main(String[] args) {
// Student s1 = new Student();
// Student s1 = new Student();
// Student s1 = new Student();
// Student s1 = new Student();
// Student s1 = new Student();
// Student s1 = new Student();
// 声明Student类型的数组
Student[] stus = new Student[20]; // String[] arr = new String[10];
for (int i = 0; i < stus.length; i++) {
// 给数组元素赋值
stus[i] = new Student();
// 给Student对象的属性赋值
stus[i].number = (i + 1);
// 年级:[1,6]
stus[i].state = (int) (Math.random() * (6 - 1 + 1) + 1);
// 成绩:[0,100]
stus[i].score = (int) (Math.random() * (100 - 0 + 1));
}
// 遍历学生数组
for (int i = 0; i < stus.length; i++) {
// System.out.println(stus[i].number + "," + stus[i].state
// + "," + stus[i].score);
System.out.println(stus[i].info());
}
System.out.println("********************");
// 问题一:打印出3年级(state值为3)的学生信息。
for (int i = 0; i < stus.length; i++) {
if (stus[i].state == 3) {
System.out.println(stus[i].info());
}
}
System.out.println("********************");
// 问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
for (int i = 0; i < stus.length - 1; i++) {
for (int j = 0; j < stus.length - 1 - i; j++) {
if (stus[j].score > stus[j + 1].score) {
// 如果需要换序,交换的是数组的元素:Student对象!!!
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
// 遍历学生数组
for (int i = 0; i < stus.length; i++) {
System.out.println(stus[i].info());
}
}
}
class Student {
int number;// 学号
int state;// 年级
int score;// 成绩
// 显示学生信息的方法
public String info() {
return "学号:" + number + ",年级:" + state + ",成绩:" + score;
}
}
6.类的成员方法
方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为函数或过程;将功能封装为方法的目的:可实现代码复用,简化代码;Java里的方法不能独立存在,必须定义在类里。如:Math类中的sqrt()\random()\...等方法;Scanner类中的nextXxx()...等方法等。
// 定义方法
权限修饰符 返回值 方法名(参数类型1 参数名1,参数类型2 参数名2){
方法体;
return 返回值;
}
// 返回值问题
// 无返回值
public void eat() {
System.out.println("正在吃。。。");
}
// 有返回值
public String eat() {
return "已吃饱";
}
// 参数问题
// 无参
public void sleep() {
System.out.println("正在睡。。。 ");
}
// 有参
public void sleep(String name,int hour) {
System.out.println( name + "正在睡。。。 ,睡了" + hour + "个小时");
}
// 可变参数
public void print(String...names) {
int count = names.length;
System.out.println("本次参加考试的有" + count + "个人:");
System.out.println("名单如下:");
for (int i = 0; i < names.length; i++) {
System.out.println(names[i]);
}
}
public static void main(String[] args) {
Test t = new Test();
t.print("xiaoA","xiaoB","xiaoC");
t.print("xiaoD","xiaoE");
}
没有返回值,使用void来修饰,一般不使用return,如果使用return;用于结束此方法。有返回值:声明方法时,声明出返回值的类型,与方法体中“return 返回值”搭配使用。
方法名:属于标识符,命名时遵循标识符命名规则和规范,“见名知意”
形参:定义方法的时传的参数叫形参,形式上的参数。实参:在调用方法的时候,传入的值叫实参。形参列表:可以包含零个,一个或多个参数。多个参数时,中间用“,”隔开。
方法体:方法功能的体现。返回值:方法在执行完毕后返还给调用它的程序的数据。
方法的调用:可通过方法名调用方法,且被调用才会执行;方法调用中,可调用当前类的属性或方法。普通方法: 对象.方法;静态方法: 类名.方法。方法A调用方法A称为递归方法。
public class CustomerTest {
public static void main(String[] args) {
Customer cust1 = new Customer();
cust1.eat();
// 测试形参是否需要设置的问题
// int[] arr = new int[]{3,4,5,2,5};
// cust1.sort();
cust1.sleep(8);
}
}
// 客户类
class Customer {
// 属性
String name;
int age;
boolean isMale;
// 方法
public void eat() {
System.out.println("客户吃饭");
return;
// return后不可以声明表达式
// System.out.println("hello");
}
public void sleep(int hour) {
System.out.println("休息了" + hour + "个小时");
eat();
// sleep(10);
}
public String getName() {
if (age > 18) {
return name;
} else {
return "Tom";
}
}
public String getNation(String nation) {
String info = "我的国籍是:" + nation;
return info;
}
// 体会形参是否需要设置的问题
// public void sort(int[] arr){
//
// }
// public void sort(){
// int[] arr = new int[]{3,4,5,2,5,63,2,5};
// //。。。。
// }
public void info() {
// 错误的
// public void swim(){
//
// }
}
}
注意:方法中,只能调用方法或属性,不能定义方法;方法被调用一次,就会执行一次;无返回值使用void;定义方法时,方法的结果应该返回给调用者,交由调用者处理。
6.1.toString、getter和setter方法
toString():返回对象的详细信息;getter:获取对象属性值;setter:给对象属性赋值。
public class Person {
int id;
String name;
public static void main(String[] args) {
Person zs = new Person();
System.out.println(zs);// day719.Person@7852e922
System.out.println(zs.toString());// day719.Person@7852e922
}
}
public class Person {
int id;
String name;
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + "]";
}
public static void main(String[] args) {
Person zs = new Person();
System.out.println(zs);// Person [id=0, name=null]
System.out.println(zs.toString());// Person [id=0, name=null]
}
}
public class Person {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
Person zs = new Person();
zs.setName("张小三");
System.out.println("姓名:" + zs.getName());// 姓名:张小三
}
}
6.2.数组常用方法
求最大值、最小值、总和、平均值、数组反转、数组复制、数组排序、两数交换位置、遍历数组和查找某值等方法。
public class ArrayUtil {
// 求数组的最大值
public int getMax(int[] arr) {
int maxValue = arr[0];
for (int i = 1; i < arr.length; i++) {
if (maxValue < arr[i]) {
maxValue = arr[i];
}
}
return maxValue;
}
// 求数组的最小值
public int getMin(int[] arr) {
int minValue = arr[0];
for (int i = 1; i < arr.length; i++) {
if (minValue > arr[i]) {
minValue = arr[i];
}
}
return minValue;
}
// 求数组的总和
public int getSum(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
// 求数组的平均值
public int getAvg(int[] arr) {
return getSum(arr) / arr.length;
}
// 如下的两个同名方法构成了重载
// 反转数组
public void reverse(int[] arr) {
for (int i = 0; i < arr.length / 2; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = temp;
}
}
// 复制数组
public int[] copy(int[] arr) {
int[] arr1 = new int[arr.length];
for (int i = 0; i < arr1.length; i++) {
arr1[i] = arr[i];
}
return arr1;
}
// 数组排序
public void sort(int[] arr) {
// 冒泡排序
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;
// 错误的:
// swap(arr[j],arr[j + 1]);
// 正确的:
swap(arr, j, j + 1);
}
}
}
}
// 错误的:交换数组中指定两个位置元素的值
// public void swap(int i,int j){
// int temp = i;
// i = j;
// j = temp;
// }
// 正确的:交换数组中指定两个位置元素的值
public void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 遍历数组
public void print(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
System.out.println();
}
// 查找指定元素
public int getIndex(int[] arr, int dest) {
// 线性查找:
for (int i = 0; i < arr.length; i++) {
if (dest == arr[i]) {
return i;
}
}
return -1;// 返回一个负数,表示没有找到
}
}
// 测试
public class ArrayUtilTest {
public static void main(String[] args) {
ArrayUtil util = new ArrayUtil();
int[] arr = new int[] { 32, 34, 32, 5, 3, 54, 654, -98, 0, -53, 5 };
int max = util.getMax(arr);
System.out.println("最大值为:" + max);
System.out.println("排序前:");
util.print(arr);
util.sort(arr);
System.out.println("排序后:");
util.print(arr);
// System.out.println("查找:");
// int index = util.getIndex(arr, -5);
// if(index >= 0){
// System.out.println("找到了,索引地址为:" + index);
// }else{
// System.out.println("未找到");
// }
// util.reverse(arr);
}
}
6.3.方法的重载overload
重载的概念 |
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。即“两同一不同”:同一个类、相同方法名、参数列表不同:参数个数、类型不同。 |
重载的特点 |
与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。 |
判断是否重载 |
跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系。 |
public class OverLoadTest {
public static void main(String[] args) {
OverLoadTest test = new OverLoadTest();
test.getSum(1, "df");
}
// 如下的4个方法构成了重载
public void getSum(int i, int j) {
System.out.println("1");
}
public void getSum(double d1, double d2) {
System.out.println("2");
}
public void getSum(String s, int i) {
System.out.println("3");
}
public void getSum(int i, String s) {
System.out.println("4");
}
}
public class Person {
// name、age、sex 成员属性----特征
String name = "张三";// 名字
int age = 22;// 成员变量--全局变量--类属性
String sex = "男";
// 哭,成员方法--功能,方法描述是功能
public void cry() {
System.out.println("哭啊aaaa");
}
// 无参方法,有返回值
public int sum() {
int a = 3;
int b = 6;
return a + b;
}
// 有参方法,有返回值
public int sum(int a, int b) {// a,b是局部变量==》作用范围只限于大括号(方法中使用)
// int a = 8;// 同一个方法中不可以定义重名的变量名
return a + b;
}
// 以上2个sum方法构成方法重载,特性:在同一个类中,方法名一样,参数个数和类型不一样,和返回值无关
// 写方法的步骤
// 1.分析是否有返回值2.实现这个方法|功能,是否需要参数,参数的数量和类型
public void speak() {
System.out.println("我叫:" + name + ",年龄:" + age + ",性别:" + sex);
}
public void c1(int num) {// num 是形式参数
num += 1;
System.out.println(num);
}
public static void main(String[] args) {
// new 一个对象 这个对象为person
Person person = new Person();
person.speak();// 调用成员方法
person.age = 19;
System.out.println(person.age);
int sum = person.sum();
System.out.println("和为:" + sum);
System.out.println("sum = " + person.sum(100, 90));
person.c1(10); // 传参
}
6.4.可变个数形参的方法
JavaSE 5.0 中提供了Varargs(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。可用一种更简单的方式,来传递个数可变的实参。
说明:声明格式:方法名(参数的类型名 ...参数名);可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个;可变个数形参的方法与同名的方法之间,彼此构成重载;可变参数方法的使用与方法参数部分使用数组是一致的;方法的参数部分有可变形参,需要放在形参声明的最后;在一个方法的形参位置,最多只能声明一个可变个数形参。
public class MethodArgsTest {
public static void main(String[] args) {
MethodArgsTest test = new MethodArgsTest();
test.show(12);
// test.show("hello");
// test.show("hello","world");
// test.show();
test.show(new String[] { "AA", "BB", "CC" });
}
public void show(int i) {
}
public void show(String s) {
System.out.println("show(String)");
}
public void show(String... strs) {
System.out.println("show(String ... strs)");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
}
// 不能与上一个方法同时存在
// public void show(String[] strs){
// }
// The variable argument type String of the method
// show must be the last parameter
// public void show(String ...strs,int i){
//
// }
}
6.5.方法参数的值传递机制
Java方法的参数传递方式只有一种:值传递。将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
方法传参:基本数据类型,操作传递的是变量的值,改变一个变量的值不会影响另一个变量的值。引用数据类型(类、数组和接口),赋值是把原对象的引用(可理解为内存地址)传递给另一个引用。如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
public static void main(String[] args) {
Data data = new Data();
data.m = 10;
data.n = 20;
// m = 10,n = 20
System.out.println("m = " + data.m + ",n = " + data.n);
// 交换两个变量的值的操作
// int tem = data.m;
// data.m = data.n;
// data.n = tem;
ValueTransferTest2 test = new ValueTransferTest2();
test.swap(data);
// m = 20,n = 10
System.out.println("m = " + data.m + ",n = " + data.n);
}
public void swap(Data data) {
int tem = data.m;
data.m = data.n;
data.n = tem;
}
}
class Data {
int m;
int n;
}
6.6.递归方法
递归方法:一个方法体内调用它自身。方法递归包含了一种隐式的循环,会重复执行某段代码块,但这种重复执行无需循环控制。递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
public static void main(String[] args) {
// 例1:计算1-100之间所有自然数的和
// 方式一:
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println(sum);
// 方式二:
RecursionTest test = new RecursionTest();
int sum1 = test.getSum(100);
System.out.println(sum1);
System.out.println("*****************");
int value = test.f(10);
System.out.println(value);
}
// 例1:计算1-n之间所有自然数的和
public int getSum(int n) {// 3
if (n == 1) {
return 1;
} else {
return n + getSum(n - 1);
}
}
// 例2:计算1-n之间所有自然数的乘积:n!
public int getSum1(int n) {
if (n == 1) {
return 1;
} else {
return n * getSum1(n - 1);
}
}
// 例3:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),
// 其中n是大于0的整数,求f(10)的值。
public int f(int n) {
if (n == 0) {
return 1;
} else if (n == 1) {
return 4;
} else {
// return f(n + 2) - 2 * f(n + 1);
return 2 * f(n - 1) + f(n - 2);
}
}
7.面向对象特征封装与隐藏
问题引入:创建类的对象后,可通过“对象.属性”进行赋值。赋值操作要受到属性类型和数据存储范围制约及其他制约条件。这些条件不能在属性声明时体现,只能通过方法进行限制。还需避免使用“对象.属性”的方式进行赋值。
封装的思想:隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。把该隐藏的隐藏起来,该暴露的暴露出来,就是封装性的设计思想。
封装的特点:只能通过规定的方法访问数据;隐藏类的细节、方便修改和实现。
封装性的体现:将类的属性私有化(private),同时提供公共的public方法来获取getXxx和设置setXxx属性的值。
封装的步骤:1.修改属性的可见性(权限修饰符)改为private;2.创建共有的getter/setter方法,用于属性的读写;3.在getter/setter方法中加入属性控制语句,对属性值的合法性进行判断。
public class AnimalTest {
public static void main(String[] args) {
Animal a = new Animal();
a.name = "大黄";
// a.age = 1;
// a.legs = 4;//The field Animal.legs is not visible
a.show();
// a.legs = -4;
// a.setLegs(6);
a.setLegs(-6);
// a.legs = -4;//The field Animal.legs is not visible
a.show();
System.out.println(a.name);
}
}
class Animal {
String name;
private int age;
private int legs;// 腿的个数
// 对属性的设置
public void setLegs(int l) {
if (l >= 0 && l % 2 == 0) {
legs = l;
} else {
legs = 0;
// 抛出一个异常(暂时没有讲)
}
}
// 对属性的获取
public int getLegs() {
return legs;
}
public void eat() {
System.out.println("动物进食");
}
public void show() {
System.out.println("name = " + name + ",age = " + age + ",legs = " + legs);
}
// 提供关于属性age的get和set方法
public int getAge() {
return age;
}
public void setAge(int a) {
age = a;
}
}
封装的目的:隐藏一个类中不需要对外提供的实现细节;使用者只能通过事先定制好的方法来访问数据,加入合适的控制逻辑,限制对属性的不合理操作;便于修改,增强代码的可维护性。
拓展:不对外暴露的私有的私有方法;单例模式
7.1.四种访问权限修饰符
权限访问修饰符private、缺省、protected、public置于类的成员定义前,用来限定对象对该类成员的访问权限。
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
private | Yes | |||
缺省 | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
四种权限可用来修饰类的内部结构:属性、方法、构造器、内部类。class只能用public和default(缺省)修饰;public类可在任意地方被访问;default类只可被同一个包内部的类访问。
public class Order {
private int oderPrivate;
int orderDefault;
public int orderPublic;
private void methodPrivate() {
oderPrivate = 1;
orderDefault = 2;
orderPublic = 3;
}
void methodDefault() {
oderPrivate = 1;
orderDefault = 2;
orderPublic = 3;
}
public void methodPublic() {
oderPrivate = 1;
orderDefault = 2;
orderPublic = 3;
}
}
// 测试类
public class OrderTest {
public static void main(String[] args) {
Order order = new Order();
order.orderDefault = 1;
order.orderPublic = 2;
// 出了Order类之后,私有的结构就不可以调用了
// order.orderPrivate = 3;//The field Order.orderPrivate is not visible
order.methodDefault();
order.methodPublic();
// 出了Order类之后,私有的结构就不可以调用了
// order.methodPrivate();//The method methodPrivate() from the type
// Order is not visible
}
}
总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。
8.类的成员构造器/构造方法
构造器/构造方法constructor:construct:建设、建造;constructor:建造者。
特征:它具有与类相同的名称;它不声明返回值类型(与声明为void不同);不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值。
作用:创建对象;初始化对象的信息。
语法格式:
修饰符 类名 (参数列表) {
初始化语句;
}根据参数不同,构造器可以分为如下两类:
隐式无参构造器(系统默认提供);
显式定义一个或多个构造器(无参、有参)。
注意:Java语言中,每个类都至少有一个构造器;默认构造器的修饰符与所属类的修饰符一致;一旦显式定义了构造器,则系统不再提供默认构造器;一个类中可定义多个构造器,彼此构成重载;父类的构造器不可被子类继承。
public class PersonTest {
public static void main(String[] args) {
Person person = new Person();
//创建类对象:new + 构造器
person.eat();
Person p1 = new Person("Tom");
}
}
class Person {
//属性
String name;
int age;
//构造器
public Person(){
System.out.println("Person().......");
}
public Person(String n){
name = n;
}
//方法
public void eat() {
System.out.println("人吃饭");
}
public void study() {
System.out.println("人可以学习");
}
}
构造方法:构造方法用于创造对象和对类进行初始化。new类名可生成对象。
this关键字:当前对象的默认引用;调用成员变量时,解决成员变量和局部变量同名冲突;用于调用成员方法;调用重载的构造方法时,必须是构造方法的第一条语句。注意:this 是在对象内部指代自身的引用,所以this只能调用实例变量、实例方法和构造方法。this不能调用类变量和类方法,this也不能调用局部变量。
public class Person {
String name = "张三";
int age = 22;
String sex = "男";
// 自我介绍方法
public void speak() {
System.out.println("我叫:" + name + ",年龄:" + age + ",性别:" + sex);
}
// 自我介绍方法
public void speak(String content) {
System.out.println("我叫:" + name + ",年龄:" + age + ",性别:" + sex + "理念:" + content);
}
// alt + shift + s 快捷键生成如下2个方法(构造方法)
public Person() {// 无参构造
System.out.println("无参构造被调用");
}
public Person(String name, int age, String sex) {// 有参构造
this(name, age);// this调用重载的构造方法,而且必须是第一行
this.sex = sex;
System.out.println("有参构造3个参数被调用");
System.out.println(name + ":" + age + ":" + sex);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参构造2个参数被调用");
System.out.println(name + ":" + age + ":" + this.name);
}
}
public class TestPerson {
public static void main(String[] args) {
Person person = new Person();// 调用无参构造--初始化
person.name = "来福";
person.age = 28;
person.sex = "男";
System.out.println("姓名:" + person.name);
// 调用有参构造--初始化对象的属性等相关信息
Person person1 = new Person("小米", 22, "女");// 调用3个参数的有参构造
person1.speak();
Person person2 = new Person("东东", 16);// 调用2个参数的有参构造
person2.speak("发展家乡");
}
}
带参数的构造方法叫有参构造,不带参数的构造方法叫无参构造;若写有参构造,一般都要写一个无参构造。因为Java默认写无参构造,如果写了有参构造之后,会把无参构造覆盖。
9.属性赋值
①默认初始化、②显示初始化、③构造器初始化、④通过”对象.方法“或”对象.属性“的方式进行赋值,赋值的先后顺序①②③④。
10.JavaBean
JavaBean是一种Java的可重用组件。要求:类是公共的;有一个无参的公共的构造器;有属性,且有对应的get、set方法。
用户可使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包,并且其他的开发者可通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可认为JavaBean提供一种随时随地的复制和粘贴的功能,而不用关心任何改变。
public class Customer {
private int id;
private String name;
public Customer() {
}
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;
}}
11.UML类图
+ 表示 public 类型, - 表示 private 类型,#表示protected类型;方法的写法:方法的类型(+、-) 方法名(参数名: 参数类型):返回值类型。
12.this关键字
this可修饰:属性、方法、构造器。修饰属性和方法表示当前对象或当前正在创建的对象。
this修饰属性表示本类的属性,修饰方法表示本类的方法,this只能修饰普通方法,不能再静态方法和类中使用this。
类的方法中,可使用”this.属性”或“this.方法”调用当前对象属性或方法,但通常情况下选择省略“this.",特殊情况下,方法的形参和类的属性名相同时,必须显式的使用”this.变量“的方式,表明此变量是属性,而非形参;在类的构造器中,也可使用”this.属性”或“this.方法”的方式。
this调用构造器:在类的构造器中,可显式使用”this(形参列表)“方式,调用本类中指定的其他构造器;构造器中不能通过”this(形参列表)“方式调用自己;如果一个类中有n个构造器,则最多有n - 1个构造器中使用了”this(形参列表)“;规定:”this(形参列表)“必须声明在当前构造器的首行;构造器内部,最多声明一个”this(形参列表)“,用来调用其他的构造器。
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.setAge(1);
System.out.println(p1.getAge());
}
}
class Person {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void eat() {
System.out.println("人吃饭");
this.study();
}
public void study() {
System.out.println("人学习");
}
public Person() {
}
public Person(String name) {
this();//调用空参构造器
this.name = name;
}
}
13.关键字package、import的使用
13.1.包(package)
package在源文件的第一条语句,指明文件中所在包。(若缺省该语句,则指定为无名包)。它的格式为:package 顶层包名.子包名 ;
包的作用是实现项目中类更好的管理;使用package声明类或接口所属的包,声明在源文件的首行;每"."一次,就代表一层文件目录;包属于标识符,遵循标识符的命名规则、规范(yy.xx)。同一个包下,不能命名同名的接口、类。不同的包下,可命名同名的接口、类。
package com.school.dao;
13.2.包的使用
java中包就相当于电脑中的文件夹。作用:区分相同名称的类;能够较好的管理大量的类;控制访问范围。创建包:通常包名为公司域名的反写,小写字母。注意:可创建级联包,中间用点隔开;把一个类建在一个包下时,这个类的第一行(相对)必须是包名,不能删除。
13.3.JDK中主要的包介绍
包 | 内容 |
java.lang | 包含一些Java语言的核心类,如String、Math、Integer、 System和Thread,提供常用功能 |
java.net | 包含执行与网络相关的操作的类和接口 |
java.io | 包含能提供多种输入/输出功能的类 |
java.util | 包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数 |
java.text | 包含了一些java格式化相关的类 |
java.sql | 包含了java进行JDBC数据库编程的相关类/接口 |
java.awt | 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 B/S C/S |
13.4.导入(import)
import表示导入,在源文件中显式使用import结构导入指定包下的接口、类;在包的声明和类的声明之间声明导入的包。用import语句可引入指定包下全部类或接口(.*)。import语句告诉编译器到哪里去寻找类。语法格式:import 包名. 类名;
需导入多个结构,并列写出;可使用”xxx.*"的方式,表示可以导入xxx包下的所有结构;使用类或接口是java.lang包或定义本包下的,可省略import结构;在源文件中,使用不同包下的同名的类,必须至少有一个类使用全类名。import static:导入指定类或接口中的静态结构:属性或方法。
导入包:import java.util.Scanner; 导入java.util.下的Scanner类、import java.util.*;导入java.util.下所有类。如果已导入java.a包下的类,需使用a包的子包下的类,仍然需要导入。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Scanner;
import com.geguigu.exer2.Account;
import com.geguigu.exer2.Bank;
public class PackageImportTest {
public static void main(String[] args) {
String info = Arrays.toString(new int[] { 1, 2, 3 });
Bank bank = new Bank();
ArrayList list = new ArrayList();
HashMap map = new HashMap();
Scanner s = null;
System.out.println("hello!");
Person p = new Person();
Account acct = new Account(1000);
// 全类名的方式显示
com.geguigu.exer2.Account acct1 = new com.geguigu.exer2.Account(1000);
Date date = new Date();
java.sql.Date date1 = new java.sql.Date(5243523532535L);
}
}
14.实验
Account类模拟账户,属性:账号 id,余额 balance,年利率 annualInterestRate;方法:访问器方法(getter 和 setter方法),取款方法 withdraw(),存款方法 deposit()。
Account |
private int id private double balance private double annualInterestRate |
public Account (int id, double balance, double annualInterestRate ) |
public int getId() public double getBalance() public double getAnnualInterestRate() public void setId( int id) public void setBalance(double balance) public void setAnnualInterestRate(double annualInterestRate) public void withdraw (double amount)//取钱 public void deposit (double amount)//存钱 |
提款方法withdraw中,需判断用户余额是否满足提款数额,不满足给出提示。2. 创建 Customer 类。
Customer |
private String firstName private String lastName private Account accoun |
public Customer(String f,String l) |
public String getFirstName() public String getLastName() public Account getAccount() public void setAccount(Account account) |
属性:firstName、lastName 和 account;(f 和 l)对应构造器;方法 getFirstName 、getLastName、setAccount、 getAccount。
3.测试程序:(1) 创建一个Customer ,名字叫 Jane Smith账号为1000,余额为2000元,年利率为1.23%的账户。(2)对Jane Smith操作。存入100元再取出960元。再取出2000 元。打印出Jane Smith基本信息:成功存入:100.0;成功取出:960.0;余额不足,取款失败。
// Account类
public class Account {
private double balance;
public double getBalance() {
return balance;
}
public Account(double init_banlance) {
this.balance = init_banlance;
}
// 存钱操作
public void deposit(double amt) {
if (amt > 0) {
balance += amt;
System.out.println("存款成功,取了" + amt);
}
}
// 取钱操作
public void withdraw(double amt) {
if (amt < balance) {
balance -= amt;
System.out.println("取款成功,取了" + amt);
return;
}
System.out.println("取款失败");
}
}
// Customer 类
public class Customer {
private String firstName;
private String lastName;
private Account account;
public Customer(String f, String l) {
this.firstName = f;
this.lastName = l;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
addCustomer 方法必须依照参数(姓,名)构造一个新的 Customer 对象,然后把它放到 customer 数组中。还必须把 numberOfCustomer 属性的值加 1。getNumOfCustomers 方法返回 numberofCustomers 属性值。
addCustomer 方法必须依照参数(姓,名)构造一个新的 Customer 对象,然后把
它放到 customer 数组中。还必须把 numberOfCustomer 属性的值加 1。getNumOfCustomers 方法返回 numberofCustomers 属性值。getCustomer 方法返回与给出的 index 参数相关的客户。
// Bank类
public class Bank {
private Customer[] customers;// 存放多个客户的数组
private int numberOfCustomers;// 记录客户的个数
public Bank() {
customers = new Customer[10];
}
// 添加客户
public void addCustomer(String f, String l) {
Customer cust = new Customer(f, l);
// customers[numberOfCustomers] = cust;
// numberOfCustomers++;
// 或
customers[numberOfCustomers++] = cust;
}
// 获取客户的个数
public int getNumOfCustomers() {
return numberOfCustomers;
}
// 获取指定位置上的客户
public Customer getCustomer(int index) {
// return customers[index];//可能报异常
if (index >= 0 && index < numberOfCustomers) {
return customers[index];
}
return null;
}
}
// 测试类
public class BankTest {
public static void main(String[] args) {
Bank bank = new Bank();
bank.addCustomer("Jane", "Smith");
//连续操作
bank.getCustomer(0).setAccount(new Account(2000));
bank.getCustomer(0).getAccount().withdraw(500);
double balance = bank.getCustomer(0).getAccount().getBalance();
System.out.println("客户:" + bank.getCustomer(0).getFirstName() + "的账户余额为:" + balance);
System.out.println("***********************");
bank.addCustomer("万里", "杨");
System.out.println("银行客户的个数为:" + bank.getNumOfCustomers());
}
}
15.项目二
该软件能够实现对客户对象的插入、修改和删除(用数组实现),并能够打印客户明细表。项目采用分级菜单方式。主菜单如下:
每个客户的信息被保存在Customer对象中;以一个Customer类型的数组来记录当前所有的客户;每次“添加客户”(菜单1)后,客户(Customer)对象被添加到数组中;每次“修改客户”(菜单2)后,修改后的客户(Customer)对象替换数组中原对象;每次“删除客户”(菜单3)后,客户(Customer)对象被从数组中清除;执行“客户列表 ”(菜单4)时,将列出数组中所有客户的信息。
CMUtility工具类:将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。
public class CMUtility {
private static Scanner scanner = new Scanner(System.in);
/**
用于界面菜单的选择。该方法读取键盘,如果用户键入’1’-’5’中的任意字符,则方法返回。返回值为用户键入字符。
*/
public static char readMenuSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1, false);
c = str.charAt(0);
if (c != '1' && c != '2' &&
c != '3' && c != '4' && c != '5') {
System.out.print("选择错误,请重新输入:");
} else break;
}
return c;
}
/**
从键盘读取一个字符,并将其作为方法的返回值。
*/
public static char readChar() {
String str = readKeyBoard(1, false);
return str.charAt(0);
}
/**
从键盘读取一个字符,并将其作为方法的返回值。
如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
*/
public static char readChar(char defaultValue) {
String str = readKeyBoard(1, true);
return (str.length() == 0) ? defaultValue : str.charAt(0);
}
/**
从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
*/
public static int readInt() {
int n;
for (; ; ) {
String str = readKeyBoard(2, false);
try {
n = Integer.parseInt(str);
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
*/
public static int readInt(int defaultValue) {
int n;
for (; ; ) {
String str = readKeyBoard(2, true);
if (str.equals("")) {
return defaultValue;
}
try {
n = Integer.parseInt(str);
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
从键盘读取一个长度不超过limit的字符串,并将其作为方法的返回值。
*/
public static String readString(int limit) {
return readKeyBoard(limit, false);
}
/**
从键盘读取一个长度不超过limit的字符串,并将其作为方法的返回值。
如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
*/
public static String readString(int limit, String defaultValue) {
String str = readKeyBoard(limit, true);
return str.equals("")? defaultValue : str;
}
/**
用于确认选择的输入。该方法从键盘读取‘Y’或’N’,并将其作为方法的返回值。
*/
public static char readConfirmSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1, false).toUpperCase();
c = str.charAt(0);
if (c == 'Y' || c == 'N') {
break;
} else {
System.out.print("选择错误,请重新输入:");
}
}
return c;
}
private static String readKeyBoard(int limit, boolean blankReturn) {
String line = "";
while (scanner.hasNextLine()) {
line = scanner.nextLine();
if (line.length() == 0) {
if (blankReturn) return line;
else continue;
}
if (line.length() < 1 || line.length() > limit) {
System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
continue;
}
break;
}
return line;
}
}
Customer为实体对象,用来封装客户信息
public class Customer {
private String name;// 客户姓名
private char gender;// 性别
private int age;// 年龄
private String phone;// 电话号码
private String email;// 电子邮箱
// 省略getter、setter、toString和有参无参构造方法
}
CustomerList为Customer对象的管理模块,内部用数组管理一组Customer对象,并提供相应的添加、修改、删除和遍历方法, 供CustomerView调用
public class CustomerList {
private Customer[] customers;// 用来保存客户对象的数组
private int total;// 记录已保存客户对象的数量
// 用来初始化customers数组的构造器
public CustomerList(int totalCustomer) {
customers = new Customer[totalCustomer];
}
// 将指定的客户添加到数组中
// true:添加成功 false:添加失败
public boolean addCustomer(Customer customer) {
if (total >= customers.length) {
return false;
}
// customers[total] = customer;
// total++;
// 或
customers[total++] = customer;
return true;
}
// 修改指定索引位置的客户信息
// 修改成功 false:修改失败
public boolean replaceCustomer(int index, Customer cust) {
if (index < 0 || index >= total) {
return false;
}
customers[index] = cust;
return true;
}
// 删除指定索引位置上的客户
// 删除成功 false:删除失败
public boolean deleteCustomer(int index) {
if (index < 0 || index >= total) {
return false;
}
for (int i = index; i < total - 1; i++) {
customers[i] = customers[i + 1];
}
// 最后有数据的元素需要置空
// customers[total - 1] = null;
// total--;
// 或
customers[--total] = null;
return true;
}
// 所有的客户信息
public Customer[] getAllCustomers() {
Customer[] custs = new Customer[total];
for (int i = 0; i < total; i++) {
custs[i] = customers[i];
}
return custs;
}
// 获取指定索引位置上的客户
// 如果找打了元素,则返回;如果没有找到,则返回null
public Customer getCustomer(int index) {
if (index < 0 || index >= total) {
return null;
}
return customers[index];
}
// 获取存储的客户的数量
public int getTotal() {
return total;
// return customers.length;//错误的
}
}
CustomerView为主模块,负责菜单的显示和处理用户操作
public class CustomerView {
private CustomerList customerList = new CustomerList(10);
public CustomerView() {
Customer customer = new Customer("王涛", '男', 23, "13212341234", "wt@gmail.com");
customerList.addCustomer(customer);
}
// 显示《客户信息管理软件》界面的方法
public void enterMainMenu() {
boolean isFlag = true;
while (isFlag) {
System.out.println("\n-----------------客户信息管理软件-----------------\n");
System.out.println(" 1 添 加 客 户");
System.out.println(" 2 修 改 客 户");
System.out.println(" 3 删 除 客 户");
System.out.println(" 4 客 户 列 表");
System.out.println(" 5 退 出\n");
System.out.print(" 请选择(1-5):");
char menu = CMUtility.readMenuSelection();
switch (menu) {
case '1':
addNewCustomer();
break;
case '2':
modifyCustomer();
break;
case '3':
deleteCustomer();
break;
case '4':
listAllCustomers();
break;
case '5':
// System.out.println("退出");
System.out.print("确认是否退出(Y/N):");
char isExit = CMUtility.readConfirmSelection();
if (isExit == 'Y') {
isFlag = false;
}
// break;
}
}
}
// 添加客户的操作
private void addNewCustomer() {
// System.out.println("添加客户的操作");
System.out.println("---------------------添加客户---------------------");
System.out.print("姓名:");
String name = CMUtility.readString(10);
System.out.print("性别:");
char gender = CMUtility.readChar();
System.out.print("年龄:");
int age = CMUtility.readInt();
System.out.print("电话:");
String phone = CMUtility.readString(13);
System.out.print("邮箱:");
String email = CMUtility.readString(30);
// 将上述数据封装到对象中
Customer customer = new Customer(name, gender, age, phone, email);
boolean isSuccess = customerList.addCustomer(customer);
if (isSuccess) {
System.out.println("---------------------添加完成---------------------");
} else {
System.out.println("-------------------客户目录已满,添加失败---------------");
}
}
// 修改客户的操作
private void modifyCustomer() {
// System.out.println("修改客户的操作");
System.out.println("---------------------修改客户---------------------");
Customer cust;
int number;
for (;;) {
System.out.print("请选择待修改客户编号(-1退出):");
number = CMUtility.readInt();
if (number == -1) {
return;
}
cust = customerList.getCustomer(number - 1);
if (cust == null) {
System.out.println("无法找到指定客户!");
} else {// 找到了相应编号的客户
break;
}
}
// 修改客户信息
System.out.print("姓名(" + cust.getName() + "):");
String name = CMUtility.readString(10, cust.getName());
System.out.print("性别(" + cust.getGender() + "):");
char gender = CMUtility.readChar(cust.getGender());
System.out.print("年龄(" + cust.getAge() + "):");
int age = CMUtility.readInt(cust.getAge());
System.out.print("电话(" + cust.getPhone() + "):");
String phone = CMUtility.readString(13, cust.getPhone());
System.out.print("邮箱(" + cust.getEmail() + "):");
String email = CMUtility.readString(30, cust.getEmail());
Customer newCust = new Customer(name, gender, age, phone, email);
boolean isRepalaced = customerList.replaceCustomer(number - 1, newCust);
if (isRepalaced) {
System.out.println("---------------------修改完成---------------------");
} else {
System.out.println("---------------------修改失败---------------------");
}
}
// 删除客户的操作
private void deleteCustomer() {
// System.out.println("删除客户的操作");
System.out.println("---------------------删除客户---------------------");
int number;
for (;;) {
System.out.print("请选择待删除客户编号(-1退出):");
number = CMUtility.readInt();
if (number == -1) {
return;
}
Customer customer = customerList.getCustomer(number - 1);
if (customer == null) {
System.out.println("无法找到指定客户!");
} else {
break;
}
}
// 找到了指定的客户
System.out.print("确认是否删除(Y/N):");
char isDelete = CMUtility.readConfirmSelection();
if (isDelete == 'Y') {
boolean deleteSuccess = customerList.deleteCustomer(number - 1);
if (deleteSuccess) {
System.out.println("---------------------删除完成---------------------");
} else {
System.out.println("---------------------删除失败---------------------");
}
} else {
return;
}
}
// 显示客户列表的操作
private void listAllCustomers() {
// System.out.println("显示客户列表的操作");
System.out.println("---------------------------客户列表---------------------------\n");
int total = customerList.getTotal();
if (total == 0) {
System.out.println("没有客户记录!");
} else {
System.out.println("编号\t姓名\t性别\t年龄\t电话\t\t邮箱");
Customer[] custs = customerList.getAllCustomers();
for (int i = 0; i < custs.length; i++) {
Customer cust = custs[i];
System.out.println((i + 1) + "\t" + cust.getName() + "\t" + cust.getGender() + "\t" + cust.getAge()
+ "\t" + cust.getPhone() + "\t" + cust.getEmail());
}
}
System.out.println("-------------------------客户列表完成-------------------------");
}
public static void main(String[] args) {
CustomerView view = new CustomerView();
view.enterMainMenu();
}
}