第四章 面向对象编程(上)

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置于类的成员定义前,用来限定对象对该类成员的访问权限。

修饰符类内部同一个包不同包的子类同一个工程
privateYes
缺省YesYes
protectedYesYesYes
publicYesYesYesYes

        四种权限可用来修饰类的内部结构:属性、方法、构造器、内部类。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();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值