3. Java面对对象基础笔记

面对对象基础

1. 主线

  1. Java类及其成员:属性、方法、构造器;代码块、内部类
  2. 面对对象的三大特征
    • 封装性
    • 继承性
    • 多态性
    • (抽象性)
  3. 其他关键字:this、super、static、final、abstract、interface、package、import

2. 类和对象

类是对一类事物的描述,是抽象的、概念上的定义。

  1. 设计一个类

    • 属性(成员变量、field、域)
    • 方法 (成员函数、method、方法)
    class Person{
        //属性
        String name;
        int age;
        boolean isMale;
        
        //方法
        public void eat(){
            System.out.println("吃饭");
        }
        
        public void sleep(){
            System.out.println("睡觉");
        }
        
        public void talk(String language){
            System.out.println("说" + langue + "语言");
        }
    }
    
  2. 使用类及其对象

    public class Test{
        public static void main(String[] args){
            //创建Person类的对象(类的实例化)
            Person p1 = new Person();
            
            //调用对象的属性和方法
            //调用属性:对象.属性名
            p1.name = "Tom";
            p1.age = 18;
            p1.isMale = true;
            System.out.println(p1.name);
            
            //调用方法:对象.方法名()
            p1.eat();
            p1.sleep();
            p1.talk("Chinese");
            
        }
    }
    
    • 创建类的实例时需要使用new关键字;
    • 类是对象的抽象,对象是类的具体;
    • 由对象可以反推出类(反射机制);
  3. 类中的属性

    • 属性 vs 局部变量
      • 相同点
        • 定义的格式相同
        • 先声明后使用
        • 都有其对应的作用域
      • 不同点:
        • 在类中声明的位置不同:属性直接声明在类中;局部变量声明在方法内、方法形参、代码块内、构造器形参或构造器中
        • 生命周期不同:属性随对象的创建而诞生,随对象的消亡而消失;局部变量自声明起至方法结束完
        • 内存位置不同:属性分配堆中的空间或静态域内;局部变量分配栈中的空间
        • 作用域不同:属性可以使用权限修饰符控制其作用域;局部变量作用域为一对大括号内
        • 默认初始化的值不同:属性有默认初始化值(同数组);局部变量没有默认初始化值,声明后必须赋值才可以使用
  4. 类中的方法

    描述对象所具有的功能。

    • 方法的声明:权限修饰符 返回值类型 方法名(形参列表){方法体}
    • 方法也可以使用权限修饰符
    • static、final、abstract修饰符
    • 方法名为标识符,须遵循命名规则
    • 形参列表:可声明0个、1个或多个形参
    • 类方法中可以调用当前类 的属性,也可以调用当前类的方法
    • 类中的方法可以访问该类对象的私有属性

对象

对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。

public class Test{
    public static void main(String[] args){
        Person p1 = new Person();
        
        p1.name = "Tom";
        p1.age = 18;
        p1.isMale = true;
        System.out.println(p1.name);
        
        p1.eat();
        p1.sleep();
        p1.talk("Chinese");
        
        Person p2 = new Person();
        System.out.println(p2.name);//null
        p2.name = "Petter";
        System.out.println(p2.name);
        
    }
}
  • 每个对象拥有自己独立的内存空间(static修饰的属性和方法除外);
  • 类中未初始化的属性赋予其默认初始化值(参考数组中的默认初始化值);
  1. 对象的内存解析

image-20210726161919914

  • 堆(Heap),此内存区域的唯一目的就是存放对象实例(这里指的是广义上的对象:new出来的),几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
  • 栈(Stack),是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char 、 short 、 int 、 float 、 long 、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。 方法执行完,自动释放。
  • 方法区(Method Area),用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
  • 实例解析:
public static void main(String[] args){
    Person p1 = new Person();
    p1.name = "Tom";
    p1.age = 18;
    p1.isMale = true;
    Person p2 = new Person();
    sysout(p2.name);//null
    Person p3 = p1;
    p3.age = 10;
}
  1. 对象数组

    例题:

    定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
    问题一:打印出3年级(state值为3)的学生信息。
    问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息

    public class Exercise4 {
    	public static void main(String[] args) {
    		Student[] students = new Student[20];
    		Exercise4 demo = new Exercise4();
    		demo.initStudent(students, 20);
    		demo.searchState(students, 3);
    		demo.sortWithScore(students);
    		demo.printInfo(students);
    	}
    	/**
    	 * 
    	* @Description 初始化对象数组
    	* @author zbs
    	* @date Jul 29, 20212:36:24 PM
    	* @param students
    	 */
    	public void initStudent(Student[] students, int num) {
    		for (int i = 0; i < num; i++) {
    			students[i] = new Student();
    			students[i].number = i + 1;
    			students[i].score = (int)(Math.random() * 100) + 1;
    			students[i].state = (int)(Math.random() * 6) + 1;
    		}
    	}
    	/**
    	 * 
    	* @Description 根据年级进行查找
    	* @author zbs
    	* @date Jul 29, 20212:37:15 PM
    	* @param students
    	* @param state
    	 */
    	public void searchState(Student[] students, int state) {
    		System.out.println("三年级的学生有:");
    		System.out.println("学号\t成绩\t年级");
    		for (int i = 0; i < students.length; i++) {
    			if (students[i].state == state) {
    				students[i].showInfo();
    			}
    		}
    	}
    	/**
    	 * 
    	* @Description 根据成绩进行排序
    	* @author zbs
    	* @date Jul 29, 20212:37:43 PM
    	* @param students
    	 */
    	public void sortWithScore(Student[] students) {
    		boolean flag;
    		for (int i = 0; i < students.length; i++) {
    			flag = true;
    			for (int j = 0; j < students.length - i - 1; j++) {
    				if (students[j].score > students[j + 1].score) {
    					Student temp = students[j];
    					students[j] = students[j + 1];
    					students[j + 1] = temp;
    					flag = false;
    				}
    			}
    			if (flag) {
    				break;
    			}
    		}
    	}
    	/**
    	 * 
    	* @Description 输出对象数组的信息
    	* @author zbs
    	* @date Jul 29, 20212:38:18 PM
    	* @param students
    	 */
    	public void printInfo(Student[] students) {
    		System.out.println("按成绩由小到大的排序为:");
    		System.out.println("学号\t成绩\t年级");
    		for (int i = 0; i < students.length; i++) {
    			students[i].showInfo();
    		}
    	}
    }
    
    class Student{
    	/**
    	 * 学号
    	 */
    	int number;
    	/**
    	 * 年级
    	 */
    	int state;
    	/**
    	 * 分数
    	 */
    	int score;
    	
    	public void showInfo() {
    		System.out.print(number + "\t");
    		System.out.print(score + "\t");
    		System.out.println(state + "\t");
    	}
    }
    
  2. 如何理解万物皆对象

    1. 在Java语言的范畴,我们将功能、结构封装到类中,通过类的实例化,来调用具体的功能结构;
      • 自定义的类、对象
      • 文件:File
      • 网络资源、URL
    2. 涉及到Java语言与前端的Html、后端的数据库交互时,都体现为类、对象;
  3. 匿名对象

    创建的对象没有被变量所接收;

    匿名对象只可以调用一次;

    常用作参数传递,如下:

    class Test{
        public static void main(){
            PhoneMall mall = new PhoneMall();
            mall.show(new Phone());	//参数传入匿名对象
        }
    }
    
    class PhoneMall{
        public void show(Phone phone){
            phone.sendMaile();
            phone.playGame();
        }
    }
    
    class Phone{
        double price;
        
        public void sendEmail(){
            System.out.println("发送邮件");
        }
        
        public void playGame(){
            System.out.println("玩游戏");
        }
    }
    
  4. 练习:自定义数组的工具类

    public class ArrayUtil {
    	/**
    	 *返回数组的最大值ֵ
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:25:45 PM
    	* @param array
    	* @return
    	 */
    	public static int getMax(int[] array) {
    		int max = array[0];
    		for (int i = 1; i < array.length; i++) {
    			if (array[i] > max) {
    				max = array[i];
    			}
    		}
    		return max;
    	}
    	/**
    	 * 返回数组的最小值ֵ
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:29:13 PM
    	* @param array
    	* @return
    	 */
    	public static int getMin(int[] array) {
    		int min = array[0];
    		for (int i = 1; i < array.length; i++) {
    			if (array[i] < min) {
    				min = array[i];
    			}
    		}
    		return min;
    	}
    	/**
    	 *返回数组的总和
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:34:02 PM
    	* @param array
    	* @return
    	 */
    	public static int getSum(int[] array) {
    		int sum = 0;
    		for (int i = 0; i < array.length; i++) {
    			sum += array[i];
    		}
    		return sum;
    	}
    	/**
    	 * 返回数组的平均值ֵ
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:37:43 PM
    	* @param array
    	* @return
    	 */
    	public static double getAvarage(int[] array) {
    		int sum = 0; 
    		for (int i = 0; i < array.length; i++) {
    			sum += array[i];
    		}
    		return sum/array.length;
    	}
    	/**
    	 * 反转数组
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:41:50 PM
    	* @param array
    	 */
    	public static void reverse(int[] array) {
    		for (int i = 0; i < array.length / 2; i++) {
    			int index = array.length - 1 - i;
    			int temp = array[i];
    			array[i] = array[index];
    			array[index] = temp;
    		}
    	}
    	/**
    	 *复制数组
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:44:02 PM
    	* @param array
    	* @return
    	 */
    	public static int[] copy(int[] array) {
    		int[] temp = new int[array.length];
    		for (int i = 0; i < array.length; i++) {
    			temp[i] = array[i];
    		}
    		return temp;
    	}
    	/**
    	 * 冒泡排序
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:48:23 PM
    	* @param array
    	 */
    	public static void bullotSort(int[] array) {
    		boolean flag;
    		for (int i = 0; i < array.length - 1; i++) {
    			flag = true;
    			for (int j = 0; j < array.length - 1 - i; j++) {
    				if (array[j] > array[j + 1]) {
    					int temp = array[j];
    					array[j] = array[j+1];
    					array[j+1] = temp;
    					flag = false;
    				}
    			}
    			if (flag) {
    				break;
    			}
    		}
    	}
    	/**
    	 * 输出数组内容
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:50:24 PM
    	* @param array
    	 */
    	public static void toString(int[] array) {
    		System.out.print("[");
    		for (int i = 0; i < array.length - 1; i++) {
    			System.out.print(array[i] + ",");
    		}
    		System.out.print(array[array.length - 1] + "]");
    	}
    	/**
    	 * 查找指定元素的位置
    	* @Description 
    	* @author zbs
    	* @date Jul 29, 20214:52:35 PM
    	* @param array
    	* @param dest
    	* @return
    	 */
    	public static int getElem(int[] array, int dest) {
    		for (int i = 0; i < array.length; i++) {
    			if (array[i] == dest) {
    				return i;
    			}
    		}
    		return -1;
    	}
    }
    
    public class ArrayUtilTest {
    	public static void main(String[] args) {
    		int[] array = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
    		ArrayUtil.bullotSort(array);
    		ArrayUtil.toString(array);
    	}
    }
    

3. 方法重载

重载

  • 概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。

  • 只有下列三种情况属于重载:

    • 参数类型不同
    • 参数个数不同
    • 参数顺序不同
    • 重载只与参数列表中的参数个数及其类型有关,与参数名和返回值类型无关;
    • 参数的顺序不同也是重载;
    • 存在重载的方法时,从低级类型开始匹配;
  • 如何确定对象调用的哪个方法:方法名 —> 参数列表

方法参数的值传递机制

  • 什么是赋值操作

    • 对于基本数据类型来说:

      int m = 10;
      int n = m;
      System.out.println("m = " + m + ", n = " + n);//m = 10, n = 10
      n = 20;
      System.out.println("m = " + m + ", n = " + n);//m = 10, n = 20
      

      在基本数据类型赋值的过程中,是将复制了一份再赋给了新的变量。也就是在内存中有两份相同的值。

    • 对于引用数据类型来说:

      class Order{
          int orderId;
      }
      
      class Test{
          public static void main(String[] args){
              Order o1 = new Order();
              o1.orderId = 1001;
              
              Order o2 = o1;
              
              System.out.println("o1.orderId = " + o1.order + ", o2.orderId = " + o2.orderId);
              //o1.orderId = 1001, o2.orderId = 1001
              
              o2.orderId = 1002;
              System.out.println("o1.orderId = " + o1.order + ", o2.orderId = " + o2.orderId);
              //o1.orderId = 1002, o2.orderId = 1002
          }
      }
      

      引用数据类型的赋值操作是将地址赋给新的变量。也就是说两个变量指向同一个内存空间。

  • 形参的传递机制

    • 值传递

      class Test {
          public static void main(String[] args){
              int a = 10;
              int b = 20;
              System.out.println("a = " + a + ", b = " + b);//a = 10, b = 20
              
              Test test = new Test();
              test.swap(a, b);
              System.out.println("a = " + a + ", b = " + b);//a = 10, b = 20
          }
          
          public void swap(int m, int n){
              int temp = m;
              m = n;
              n = temp;
          }
      }
      

      执行结果:两个数值交换失败。

      执行过程:

      • 首先在main方法中定义了ab两个变量,在swap()函数中定义了mn两个形参以及局部变量temp

      • 紧接着将ab两个实参传给swap()函数中的形参,相当于执行了m = a;n = b的赋值操作,由于是基本数据类型,所以abmn的内存地址不是同一个地址。

      • 然后在swap()函数中通过temp变量对mn的数值进行交换,但是ab的值并没有影响。

      • 函数执行完后释放掉形参和局部变量的内存空间,并没有起到交换ab的效果。

      内存图:

      image-20210731222451268
    • 址传递

      class Data{
          int a;
          int b;
      }
      
      class Test {
          public static void main(String[] args){
              Data data = new Data();
              int data.a = 10;
              int data.b = 20;
              System.out.println("a = " + data.a + ", b = " + data.b);//a = 10, b = 20
              
              Test test = new Test();
              test.swap(data);
              System.out.println("a = " + a + ", b = " + b);//a = 20, b = 10
          }
          
          public void swap(Data data){
              int temp = data.a;
              data.a = data.b;
              data.b = temp;
          }
      }
      

      执行结果:交换成功

      执行过程:

      • 将想要交换的两个数封装在Data类中,在main方法中创建该类的对象并进行初始化。
      • 将data对象最为swap()函数的参数传入方法;
      • 由于data属于引用数据类型,所以使用址传递,将data对象的地址传入方法,即swap()方法中data所指向的内存空间和main方法中data所指向的内存空间相同。
      • 因此在swap()函数中交换数值相当于对main方法中的data交换数值。

      内存图:

    • 总结:

      • 若参数为基本数据类型,函数内对于形参的改变不影响函数外实参的数值;
      • 若参数为引用数据类型,函数内对于形参的改变影响函数外实参的数值。

可变个数的形参

允许直接定义能和多个实参相匹配的形参。

  • 形参定义的格式:数据类型 ... 变量名

  • 使用方法:

    class Test{
        public static void main(String[] args){
            Test test = new Test();
            test.show(1);
            test.show("hello", "world");	//传入可变参数
        }
        
        public void show (int num){
            System.out.println("show(int)");
        }
        
        public void show(String ... strs){	//定义可变参数
            System.out.println("show(String ...)");
            for (int i = 0; i < strs.length; i++){
                System.out.println(strs[i]);
            }
        }
    }
    
  • Notes:

    • 可变参数的形式可与其他同名的方法构成重载;
    • 可变参数与数组参数同名的方法不可同时存在;
    • 可变参数实际上就是数组;
    • 可变形参应该生命在参数列表末尾且只能声明一个;

4. 封装性

程序设计的追求:高内聚、低耦合

  • 高内聚:类内部的数据操作细节自己完成,不允许外部干涉;
  • 低耦合:仅对外暴露少量的方法供使用;

封装性通俗的说就是把该隐藏的隐藏起来,把该暴露的暴露出来。

public class Test{
    public static void main(String[] args){
        Animal animal = new Animal();
        animal.name = "蛋黄";
        
        animal.age = -2;//错误的赋值
        animal.setAnimal(-2);
        
        animal.show();
        
        System.out.println("age: " + animal.getAge());
        
    }
}

class Animal{
    String name;
    private int age;//添加访问修饰符对age变量进行约束
    
    //通过方法对age进行判断、赋值
    public setAge(int age1){
        if (age > 0 && age < 100){
            age = age1;
        } else {
            age = 0;
        }
    }
    //为不能访问的属性能够提供访问方法
    public int getAge(){
        return age;
    }
    
    public void show(){
        System.out.println("name: " + name + ", age: " + age);
    }
}

问题的提出:

当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如:setAge())。同时,我们需要避免用户再使用"对象.属性"的方式对属性进行赋值。则需要将属性声明为私有的(private)。

封装性的体现:

  • 我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
    拓展:封装性的体现:① 如上 ② 不对外暴露的私有的方法 ③ 单例模式 …

  • 访问控制修饰符

    类内本包非本包子类非本包非子类
    public
    default×
    protected××
    private×××

    可以用来修饰类及类的内部结构、属性、方法、构造器、内部类;

    类只可以使用public或default修饰;

    private限制的是类外不能对属性或方法进行访问,但是类内可以。

5. 构造器(constructor)

任何一个类都至少有一个构造器

  1. 构造器的作用
  • 创建对象

    String str = new String();
    //new + 构造器
    
  • 初始化对象

    String str = new String("lhp");
    //初始化str = "lhp"
    
  1. 构造器的定义权限控制修饰符 类名(形参列表){方法体}

    构造器不同于方法;

    构造器的名字必须与类名同名;

    构造器没有返回值;

    在一个类中可定义多个构造器,符合方法重载的规则;

    一旦显示的定义了类的构造器,系统不再提供默认的空参构造器;

    默认构造器的权限与类的权限相同;

    构造器中可调用方法和构造器;

6. this关键字

public class Test{
    Person p1 = new Person();
    
    p1.setAge(19);
    System.out.println(p1.getAge());
    /* 忽略构造器的情况下:
     * case1:输出0
     * case2:输出19
     */
}

class Person{
    private String name;
    private int age;
    
    public Person(){
        
    }
    
    public Person(String name){
        this.name = name;
    }
    
    public Person(int age){
        this.age = age;
    }
    
    public Person(String name, int age){
        //调用空参构造器
        this();
        //调用有参数的构造器
        this(name);
        this(name, age);
        
        this.name = name;
        this.age = age;
    }
    
    public void setName(String name){
        //case1:
        name = name;
        //case2:
        this.name = name;
    }
    
    public void setAge(int age){
        //case1:
        age = age;
        //case2:
        this.age = age;
    }
    
    public String getName(){
        return this.name;
    }
    
    public int getAge(){
        return this.age;
    }
}

thsi修饰属性和方法:

  • this可以理解为当前对象
    • 在类的方法中,可以使用“this.属性”或“this.方法”的方式来调用当前对象的属性或方法。通常情况下可以省略this。特殊情况下,若方法的形参与属性或方法重名时,必须加上this关键字,表明是当前对象的属性,而不是形参。
    • 在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法。但是,通常情况下,我们都选择省略"this."。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。

this修饰构造器:

  • 我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器
  • 构造器中不能通过"this(形参列表)"方式调用自己
  • 如果一个类中有n个构造器,则最多有 n - 1构造器中使用了"this(形参列表)"
  • 规定:"this(形参列表)"必须声明在当前构造器的首行
  • 构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器

练习:

image-20210803144840990
public class Test{
    public static void main(String[] args) {
    	Boy boy = new Boy("zbs", 20);
        Girl girl = new Girl("lhp", 19);
        
        boy.marry(girl);
        girl.marry(boy);
	}
}

class Boy{
    private String name;
    private int age;
    
    public Boy(){
        
    }
    
    public Boy(String name){
        this.name = name;
    }
    
    public Boy(int age){
        this.age = age;
    }
    
    public Boy(String name, int age){
        this.name = name;
        this.age = age;
    }
    
    public void setName(String i){
        name = i;
    }
    
    public String getName(){
        return this.name;
    }
    
    public void setAge(int i){
        age = i;
    }
    
    public int getAge(){
        return this.age;
    }
    
    public void marry(Girl girl){
        System.out.println("我想娶" + girl.getName());
    }
    
    public void shout(){
        if (this.age >= 22){
            System.out.println("可以去结婚了");
        } else {
            System.out.println("再等等吧");
        }
    }
}

class Girl{
    private String name;
    private int age;
    
    public Girl(){
        
    }
    
    public Girl(String name){
        this.name = name;
    }
    
    public Girl(int age){
        this.age = age;
    }
    
    public Girl(String name, int age){
        this.name = name;
        this.age = age;
    }
    
    public void setName(String i){
        name = i;
    }
    
    public String getName(){
        return this.name;
    }
    
    public void marry(Boy boy){
        System.out.println("我想嫁给" + boy.getName());
        boy.marry(this);
    }
    
    /**
	* @Description 比较两个对象的大小
	* @author zbs
	* @date Jul 29, 20212:38:18 PM
	* @param girl
	* @return 正数:当前对象大;负数:当前对象小;0:当前对象与形参对象相等
	 */
    public void compare(Girl girl){
        return this.age - girl.age;
    }
}

7. JavaBean

JavaBean是Java语言写成的可重用组件。

JavaBean指的是符合下列标准的Java类:

  • 类是公共的;
  • 有一个无参数的构造器;
  • 有属性,且有对应的get、set方法;
public class Customer{
    //属性
    private int id;
    private String name;
    
    //空参数构造器
    public Customer (){
        
    }
    
    //get、set方法
    public void setId(int id){
        this.id = id;
    }
    
    public void setName(String name){
        this.name = name;
    }
    
    public int getId(){
        return id;
    }
    
    public String getName(){
        return name;
    }
}

8. UML类图

image-20210803140439742

9. package 关键字

  • 使用package可以更好的实现项目的管理。

  • 使用package声明类或接口所属的包,放在源文件的首行。

  • 包名是标识符,遵循命名规则。

  • 报名中的每一个点都代表一个文件目录。

同一个包下不能命名同名的接口、类;不同的包下可以命名同名的接口、类

image-20210803162006337

10. import 关键字

在源文件中使用import关键字导入指定包下的类、接口;

声明在包的声明和类的声明之间;

导入多个结构并列写出即可;

可以使用==.*==的方式可导入指定包下的所有结构;

java.lang包下的结构默认已经导入,其中放着Sting、System等常用类;

若使用的类或接口是本包下的,则可以省略import结构;

若在源文件中使用了不同包下的同类名的类,应使用全类名的方式;

使用import导入的包只可使用当前包下的类,而当前包下的子包中的类不可使用,还需要导入;

import static可导入类或接口中的静态结构;

11. MVC设计模式

image-20210803162115388

image-20210803162131259

实验

  1. 按照如下的 UML 类图,创建相应的类,提供必要的结构
    image-20210803152544161

    在提款方法 withdraw()中,需要判断用户余额是否能够满足提款数额的要求,如果不能,应给出提示。deposit()方法表示存款。

  2. 按照如下的 UML 类图,创建相应的类,提供必要的结构
    image-20210803152702920

  3. 按照如下的 UML 类图,创建相应的类,提供必要的结构
    image-20210803152751885

    • addCustomer 方法必须依照参数(姓,名)构造一个新的 Customer 对象,然后把它放到 customer 数组中。还必须把 numberOfCustomer 属性的值加 1。

    • getNumOfCustomers 方法返回 numberofCustomers 属性值。

    • getCustomer 方法返回与给出的 index 参数相关的客户。

  4. 创建 BankTest 类,进行测试。

public class Account{
    private double balance;
    
    public Account(double init_balance){
        this.balance = init_balance;
    } 
    
    public double getBalance(){
        return this.balance;
    }
    
    public void deposit(double amt){
        if (amt >= 0){
            balance += amt;
            sysout("存钱成功!");
        } else {
            sysout("存钱数不能为负数!!");
        }
    }
    
    public void withdraw(double amt){
        if (balance >= amt){
            balance -= amt;
            sysout("取钱成功!");
        } else {
            sysout("余额不足,取钱失败!");
        }
    }
}
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 String getFirstName(){
        return this.firstName;
    }
    
    public String getLastName(){
        return this.lastName;
    }
    
    public Account getAccount(){
        return this.account;
    }
    
    public void setAccount(Account acct){
        this.account = acct;
    }
}
public class Bank{
    private Customer[] customers;
    private int numberOfCustomer;
    
    public Bank(){
        customers = new Customer[10];
    }
    
    public addCustomer(String f, String l){
        customers[numberOfCustomer++] = new Custemou(f, l);
    }
    
    public int getNumOfCustomers(){
        return this.numberOfCustomer;
    }
    
    public Customer getCustomer(int index){
        if (index < numberOfCustomer && index >= 0){
            return this.customers[index];            
        }
        return null;
    }
}
public class Test{
    public static void main(String[] args){
        Bank bank = new Bank();
        
        bank.addCustomer("zhao", "binsheng");
        
        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);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值