面向对象编程(全)

面向对象编程

第一章 面向对象编程

1.1基于面向对象的开发过程

基本面向对象分析 OOA (Object Oriented Analysis)

基本面向对象设计 OOD(Object Oriented Design)

基于面向对象编程 OOP (Object Oriented Programming)

1.2 面向过程和面向对象

面向过程开发 : 将系统按照事物的发展顺序设计,每个过程用函数体现(c语言 ,核心是函数)

面向对象开发 : 将系统当中存在事物归类,按照类别体现(java语言 ,核心是对象)

超市系统:

面向过程 : 1. 登录系统 2. 客户购买 3.收银 4. 进货 5. 退出 小红超市买苹果,付钱

面向对象 : 1.客户类 2. 商家类 3. 商品类 4. 结算订单

思考:五子棋游戏: 白方 黑方 棋盘系统类

1.3 面向对象的优势

1.最大的好处就是:代码重用 (避免代码的冗余)

2.不同的分析可以有不同的实现方式

1.4 面向对象的核心

面向对象的核心是类(对象)

类: 一类事物的抽象,概括统一说法 文具,抽象的说法

对象: 实际存在的个体 文具盒,具体的事物

学生类/张雨

老师类/小喵

动物类 /猫

类 : 类是对象的抽象说法,不占内存 ,分析写代码时候抽象的

对象 : 对象是类的具体化说法,占内存, 需要将类付诸于具体的对象的

注意:

先规划出类,设计类的特征和行为,将来把类的对象创建出来

1.5 类的构成

1.5.1属性

用于描述一类事物的特征,特点,如 学生的学号,性别,年龄....

1.5.2方法

用于描述一类事物的行为,动作和能力。 如学生吃饭,学习,运动....

类的语法规则:

 控制权限  class  类名{
     //属性
     
     //方法
     
 }

注意:

  1. 控制权限 public 不加 ; 只有一个加public 的,和文件名相同

  2. class 声明类的关键字

  3. 类名 : 合法标识符 首字母大写 含义 不能是关键字

属性的语法规则:

 控制权限    数据类型   属性名 [=初始值];

注意:

  1. 控制权限 public

  2. 数据类型 : 基本+引用类型

  3. 属性名: 同变量名

  4. 属性可以给初始值,也可以不给,有默认值: int 0 double 0.0 char \u0000 boolean false 引用 null

方法的语法规则:(重点

 控制权限   [修饰符]   返回类型   方法名(形参类型  形参变量,形参类型  形参变量){
     方法体;
     [return  返回值];
 }

注意:

  1. 控制权限 public

  2. 返回类型 :

    1. 有返回类型 指定一种类型:int double String... ,指定返回值方法的最后一定要有return 值;

      return 的值只能是一个,返回给调用者

    2. 无返回类型 void

  3. 方法名 同变量名

  4. 方法的参数:

    1. 方法声明时 形参 外部传入数据 ,必须逐一指明类型

    2. 方法调用时 实参

 public class Student {
     //属性
     
     public int sno ;//学号    
     public String sName;//姓名    
     public int age = 20; //年龄   
     public double weight; //体重
     
     /**
      * 吃饭
      */
     public void eat() {
         System.out.println(sName + "在吃饭");
     }   
     /**
      * 跑步:返回跑公里数
      */
     
     public int run() {
         System.out.println(sName + "在跑步");
         //return "公里:" + 10 + ";卡路里: " + 300;
         return 10;
     }   
     /**
      * 算题
      */
     public int calc(int a,int b) {
         
         return a + b;
     }
 }

练习:定义一个动物类

属性: 名字,年龄,品种

方法:

1.睡觉: 返回睡几小时

2.吃饭 : 传入吃的东西,返回吃了多少克

3.跑动 :无参数 无返回

 public class Animal {
     public String name;
     public int age;
     public String type;
     
     public double sleep() {
         return 10;
     }
     
     public double eat(String food) {
         System.out.println(name + "吃" + food);
         //返回吃掉
         return 5.5;
     }
     
     public void run() {
         System.out.println(name + "在跑动");
     }
 }

1.5.3 类图面向对象编程(全)_第1张图片

 

 package com.qf.oop;
 ​
 public class Player {
     public char gender;//性别
     public String name;//角色名
     public int level; //等级
     
     //键盘按键行走,根据性别决定速度
     public String run(char code) {
         //确定速度
         double speed = 0;
         if(gender == '男') {
             speed =  60;
         }
         else if(gender == '女') {
             speed =  40;
         }
         //确定方向
         if(code == 'a') {
             return name + "向左以" + speed + "速度奔跑";
         }else if(code == 's') {
             return name + "向下以" + speed + "速度奔跑";
         }else if(code == 'd') {
             return name + "向右以" + speed + "速度奔跑";
         }else if(code == 'w') {
             return name + "向上以" + speed + "速度奔跑";
         }else {
             return name + "原地不动";
         }            
     }
     
     //攻击,传入武器
     public void fight(String weapon) {
         System.out.println(name + "使用" + weapon + "战斗");
     }   
 }

1.5.4 对象的创建

类只是从设计的角度分析,如果使用类,必须创建该类的对象,真正的对象实例(堆中开辟内存)

 类名  对象名  =  new  类名();

 Player monkey = new Player();

当类创建了对象,在堆中开辟内存,根据类中定义的属性个数决定开辟,堆中分配所有属性。

面向对象编程(全)_第2张图片

 

1.5.5 对象成员的访问

成员: 属性和方法

属性的调用:

 对象名.属性名 //获取
 对象名.属性名 = 值; //赋值

方法的调用:

 数据类型  返回值  = 对象名.方法名(实参1,实参2...);//有返回值的方法
 ​
 对象名.方法名(实参1,实参2...); //没有返回值

注意:

  1. 当调用方法时,如果类中方法设定过形参,调用的时候传入实参

    形参: 类中方法声明定义的参数 , 形参是变量

    实参: 对象调用方法时候的参数, 实参是数值

    实参把值赋给形参, 形参 = 实参; 个数一致,类型一致,顺序一致

  2. 当方法内部设定了返回值,将值还给调用方法的位置,调用位置需要接收返回值

 //类里定义位置
 //weapon是形参
 public void fight(String weapon) {
         System.out.println(name + "使用" + weapon + "战斗");
 }
 ​
 ​
 //对象调用位置
 monkey.fight("金箍棒");//实参
 ​

玩家测试类:

 public class TestPlayer {
     public static void main(String[] args) {
         //创建玩家对象
         Player monkey = new Player();
         //System.out.println(monkey);//地址
         //System.out.println(monkey.name);//null
         //System.out.println(monkey.level);//0
         //System.out.println(monkey.gender);//\u0000
         
         monkey.name = "美猴王";
         monkey.level = 2;
         monkey.gender = '男';
         
         System.out.println(monkey.name);
         System.out.println(monkey.level);
         System.out.println(monkey.gender);
         
         monkey.fight("金箍棒");
         System.out.println("啊哈哈哈哈哈");
     }
 }

1.5.6 变量的分类

变量分为两大类: 全局变量(属性),局部变量。

全局变量 局部变量
位置 类里方法外 方法里,方法的形参
权限 必须有权限 没有权限
默认值 有默认值 没有默认值
作用范围 整个类{ } 所在的{ }
生命周期 对象创建时产生,对象销毁消失 语句块{ }
内存 堆(对象实例,大块空间) 栈(临时变量存储)

注意:

  1. 当全局变量和局部变量重名,局部变量会将全局变量覆盖

  2. 如果在方法中想要调用被覆盖的属性,this.属性

1.5.7 数组和对象结合

1.对象的属性是数组类型

 public class Student {
     public String name;
     public String tel;
     public int no;
     
     //三门成绩
     public double[] scores ;
     
     /**
      * 返回平均成绩
      */
     public double getAvg() {
         double sum = 0;
         for (int i = 0; i < scores.length; i++) {
             sum += scores[i];
         }
         return sum / scores.length;
     }   
     public void state(int day) {
         if(day >= 1 && day <= 5) {
             System.out.println("好好上课");
         }else if(day == 6) {
             System.out.println("休息");
         }else if(day == 7) {
             System.out.println("打游戏");
         }else {
             System.out.println("非法日期");
         }
     }
 ​
     
     public String info() {
         return "Student [name=" + name + ", tel=" + tel + ", no=" + no + ", scores=" + Arrays.toString(scores) + "]";
     }       
 }

测试类:

 public class TestStudent {
     public static void main(String[] args) {
         Student s = new Student();
         s.name = "老沈";      
         s.no = 110;
         s.tel = "8888666";
         
         s.scores = new double[] {87,100,69};
         
         double avg = s.getAvg();
         System.out.println(s.info());
         System.out.println("平均分数" + avg);
         s.state(2);
     }
 }

2.数组的元素是对象类型

对象数组: 数组的元素是一个个对象

语法:

 类 []  数组名  =  new 类[大小];

 public class Goods {
     public int no;
     public String name;
     public double price;
     public int counts;  
 }
 ​
 public class TestGoods {
     public static void main(String[] args) {
         //定义一个商品数组
         Goods [] goods = new Goods[3];
         Scanner sc = new Scanner(System.in);
         //动态赋值
         for (int i = 0; i < goods.length; i++) {
             goods[i] = new Goods();
             System.out.println("请输入商品名称");
             goods[i].name = sc.next();
             System.out.println("请输入商品价格");
             goods[i].price = sc.nextDouble();
             System.out.println("请输入商品编号");
             goods[i].no = sc.nextInt();
             System.out.println("请输入商品库存");
             goods[i].counts = sc.nextInt();
         }
         
         //数组遍历
         
         for (Goods g : goods) {
             System.out.println(g.name + "," + g.price);
         }
         
         //获得最高价格的商品
         double max = 0;
         int index = -1;
         for (int i = 0; i < goods.length; i++) {
             if(max < goods[i].price) {
                 max = goods[i].price;
                 index = i;
             }
         }
         System.out.println(goods[index].name);
 ​
         //控制台接收一个水果名,数组查找是否存在 equals()
         int index = -1;
         System.out.println("请输入您需要查找的水果名:");
         
         String n = sc.next();
         for (int i = 0; i < goods.length; i++) {
             if(goods[i].name.equals(n)) {
                 index = i;
                 break;
             }
         }
         if(index == -1) {
             System.out.println("没有该商品");
         }else {
             System.out.println(goods[index].name + "," + goods[index].price);
         }
     }
 }

面向对象编程(全)_第3张图片

 

1.5.8 方法的调用

1.5.8.1 调用方式

  1. 对象调用,类创建出对象后,通过对象调用

 public class Student {
     
     public String name;
     
     public void study() {
         System.out.println(name + "在认真学习");
     }
     public static void main(String[] args) {
         Student s = new Student();
         s.name = "张雨";
         //对象调用方法
         s.study();
     }
 }

2.类中的方法互相调用

 public class Student {
     
     public String name;
     //学习方法
     public void study() {
         //听歌
         music();
         System.out.println(name + "在认真学习");
         
     }
     //听歌    
     public void music() {
         System.out.println(name + "在听音乐");
     }
 }
 ​

注意: 当a方法调用b方法的时候,先执行b,b执行完,再回来执行a。

 public class Test { 
     public void a() {
         b();
         System.out.println("a");
     }   
     public void b() {
         c();
         System.out.println("b");
     }
     public void c() {
         
         System.out.println("c");
     }   
     public static void main(String[] args) {
         new Test().a(); // c b a
     }
 }

设定返回值:

 public void a() {
         b();
         System.out.println("a");
     }   
     public void b() {
         
         System.out.println("b");
         System.out.println("2" + c());
     }
     
     public int c() {        
         System.out.println("c");
         return 2;
     }   // b c 22  a 

  1. 递归调用(了解)

方法自己调用自己,递归调用必须要有一个结束条件,否则会造成死递归,堆栈溢出。

 public class Num {
     
     /**
      * 求阶乘
      * 
      * 1! = 1
      * 2! = 1! * 2
      * 3! = 2! * 3
      * ..
      * n! = (n - 1)! * n
      */
     public int getJc(int n) {
         if(n == 1) {
             return 1;
         }
         return getJc(n - 1) * n;
     }
     
     public static void main(String[] args) {
         Num n = new Num();
         int res = n.getJc(3);
         System.out.println(res);
     }
 }

综合练习:

 public class ScoreCalc{
     public int[] scores ;   
     public double sum() {
         double sum = 0;
         for (int i = 0; i < scores.length; i++) {
             sum += scores[i];
         }
         return sum;
     }
     
     public double avg() {
         return sum() / scores.length;
     }
     
     public void print() {
         System.out.println("平均成绩:" + avg());
     }
 ​
 }
 /**
     测试
 */
 public class TestScore {
     public static void main(String[] args) {
         ScoreCalc c = new ScoreCalc();
         c.scores = new int[] {100,67,74};       
         c.print();
     }
 }
 ​

1.5.8.2 方法参数个数

  1. 方法的重载: 展示方法的多样化(两个以上)

满足条件:

1. 方法名相同
2. 方法的参数一定不同:  个数,类型,顺序
3. 实参自动调用对应形参的方法
 public class Student {
     
     /**
      * 计算两个数的和
      */
     public int sum(int a,int b) {
         return a + b;
     }
     
     /**
      * 计算三个数的和
      */
     public int sum(int a,int b,int c) {
         return a + b + c;
     }
     
     public double sum(double a,double b) {
         return a + b;
     }
     public double sum(double a,int b) {
         return a + b;
     }
     public double sum(int a,double b) {
         return a + b;
     }
     //相同的方法
 //  public int sum(int c,int d) {
 //      
 //  }
     //测试
     sum(1,2,3);
 }

2.可变长参数(jdk5+)

用于设计方法的时候,不限制参数个数

 控制权限  返回值  方法名([参数类型 参数变量 , ] 数据类型...可变长参数变量){  
 ​
     方法体;
     return 值;
 }

注意:

  1. 可变长参数一定放在参数列表的最后

  2. 当定义了可变长参数,传递的实参个数可以不固定

  3. 在方法中,将可变长参数当作数组使用

 public class Student {
     //可变长参数的方法,p参数变量
     public int sum(int ...p) {
         int sum = 0;
         for (int i = 0; i < p.length; i++) {
             sum += p[i];
         }
         return sum;
     }
     
     public static void main(String[] args) {
         Student s2 = new Student();
         //任意个数的实参
         int res = s2.sum(1,2,3,4,5,10);
         System.out.println(res);
     }
 }

1.5.8.3 方法调用参数传递

当调用方法的时候,传递实参,实参赋值给形参

1.基本数据类型 : 传递的是数值

2.引用数据类型 : 传递的是地址(引用)

 public class Param1 {   
     public static void change(int a,int[]b,Person p) {
         a = 10;
         //b = new int[] {2,4,6,8};
         b[0] = 88;      
         p.face = "哭唧唧";
     }   
     public static void main(String[] args) {
         int a = 20;
         int [] b = {1,2,3,4};
         Person p = new Person();
         p.face = "笑嘻嘻";
         change(a,b,p);      
         System.out.println(a);// 20     
         System.out.println(Arrays.toString(b));     //88 2 3 4
         System.out.println(p.face); // 哭唧唧
     }
 }

堆栈图:面向对象编程(全)_第4张图片

 

方法传参案例:

 public class Param2 {
 ​
     public static void change(int x,int y,Birth b,String s) {
         //交换
         int temp = x;
         x = y;
         y = temp;   
         System.out.println(x + "," + y);// 200 100
         b = new Birth();
         b.date = 30;
         s = "abc";
     }
      
     public static void main(String[] args) {
         int x = 100, y = 200;
         Birth b = new Birth();
         b.year = 2002;
         b.month = 5;
         b.date = 9;
         //字符串类型传参比较特殊
         String a = "123";
         change(x,y,b,a);
         System.out.println(x + "," + y);// 100 200
         System.out.println(b.date);//9
         System.out.println(a);//123
     }
 }
 public class Birth {
     public int year;
     public int month;
     public int date;
 }
 ​

1.6 构造方法

又叫做构造器,类中一种特殊的方法。(重点)

作用:

能够在创建对象的时候,给属性直接赋值(属性初始化)。

语法:

控制权限  类名(形参类型 变量, 形参类型 变量2...){
    方法体(给属性赋值)
}

注意:

  1. 没有方法的返回声明

  2. 构造方法的方法名是类名

无参数的构造器:

 public Birth() {
         System.out.println("创建了生日对象");
 }

有参数的构造方法:

 public Birth(int year,int month,int date) {
         this.year = year;
         this.month = month;
         this.date = date;
     }

构造方法的调用者 : JVM 自动调用

构造方法的调用时机: new对象

构造方法调用次数: 1次

构造方法的分类:

  1. 默认构造方法 当不定义构造方法的时候,系统会自动创建一个默认的构造方法

 public 类(){
     
 }
 2. 当手动定义了构造方法,默认的无参构造方法就被覆盖。**因此,当创建构造方法的时候,一定加上无参构造。**
 3. 构造方法可以实现重载: 根据方法的参数不同实现

构造方法和普通方法的区别:

构造方法 普通方法
返回类型 无返回声明 必须加声明 void
调用方式 JVM 对象.方法()
作用 初始化属性 自定义
调用时间点 创建对象的时new 自定义

类中成员: 属性 + 方法+ 构造方法

思考: 类中普通方法是否可以是类名作为方法名? 可以,不推荐。 声明返回值类型

第二章 面向对象三大基本特性

面向对象的三大基本特性: 封装性 , 继承性 ,多态性

1,封装性 信息隐藏,数据包装 ,安全性

2,继承性 代码继承 , 代码重用

3,多态性 一个父类多个子类 , 代码扩充性强


2.1 封装性

2.1.1 什么是封装?

将类中的成员(属性,方法,构造方法)信息隐藏,信息私有化,类之外的所有地方都不能访问。

2.1.2 作用?

1.保证数据的安全性

2.保证数据不被非法使用

2.1.3 如何实现封装?

1.需要封装的成员权限改为 private

控制权限: (限制成员的使用范围)

public 公开的 整个项目都可以使用

private 私有的 当前类

注意:企业开发中,为了保证数据安全,会将所有的属性都私有化。

  1. 封装的属性需要提供一组方法 setXX() 设置属性的值 getXX() 获得属性的值

 public class Emp {
     //私有化属性
     private int eno;
     private String ename;
     private double sal;     
     //构造方法
     public Emp() {
         
     }   
     public Emp(int eno, String ename, double sal) {
         super();
         this.eno = eno;
         this.ename = ename;
         this.sal = sal;
     }
 ​
     /**
      * 获得eno的值
      */
     public int getEno() {
         //可以添加判断
         return eno;
     }
     
     /**
      * 获得薪资的方法
      */
     public double getSal() {
         return sal;
     }
     
     /**
      * 设置薪资的方法
      */
     public void setSal(double sal) {
         if(sal < 0) {
             System.out.println("薪资不合法");
         }else {
             this.sal = sal;
         }   
     }
 }

测试类:

 public class TestEmp {
     public static void main(String[] args) {
         Emp p = new Emp(1,"jack",4000);
         //获取员工编号
         System.out.println(p.getEno());
         //设置薪资
         p.setSal(-9);
         //获取薪资
         //System.out.println(p.getSal());
     }
 }

注意:

setXX() xx属性名 必须有参数

getXX() xx属性名 必须有返回值

2.1.4 封装后会怎样?

1.属性赋值的整个过程:

  1. 默认值

  2. 声明的值

  3. 构造方法(对象创建时第一次值)

  4. setXX() (为了修改对象的属性值)

2.方法的封装(构造方法的封装)

封装方法: 当类中某些方法不希望外部类调用,仅限于类内部使用。

封装构造方法: 类不希望被创建对象(单例模式)

 public void open() {
         //内部调取零件
         startFixes();
         System.out.println("电视打开");
     }
 //封装方法  
 private void startFixes() {
         System.out.println("....零件1");
         System.out.println("....零件2");
         System.out.println("....零件3");
     }

 public class Math{
     //封装构造方法
     private Math(){
     
     }
 }
 ​

单例模式:

 public class Earth {
     private static Earth earth = new Earth();
     
     private Earth() {
         
     }
     
     public static Earth getEarth() {
         return earth;
     }
 }

2.1.5 一个JAVA源文件的构成 Animal.java

包的声明(1次)
导包声明(n次)
类的声明(n个): 属性,方法,构造方法

 package  包;
 import 包;
 public  class  类名{    
 ​
 //属性        
 ​
 //方法   
 ​
 //构造
 ​
 }
 ​
 class  类名{    
 ​
 //属性        
 ​
 //方法   
 ​
 //构造
 ​
 }

包:

在JAVA中相当于文件夹。

作用:

  1. 将逻辑相关的类存放在一起

  2. 限制类的访问

包声明:

 package  根包.子包.子包;
 package com.qf.oop;

注意:

1.包名全部小写

2.包之间用.间隔, 命名 : 网站后缀.公司名.项目名 网站后缀.公司名.项目名.emp

3.包声明一定在源文件的首行有效代码

导入包声明:

 import  根包.子包.*; //导入该包中所有资源
 import  java.util.Arrays;  //导入JAVA中定义的类
 import com.qf.homework.Student; //导入自定义的跨包类

注意:可以导入多个类

JAVA中提供包(API)

java.lang 核心包 System ,String ,Math....

java.util 工具包 集合,日期, Arrays ,Scanner

java.io 文件包 读写文件

java.net 网络

java.awt 图形窗口

注意:只有java.lang不需要手动导入 ;快捷键: ctrl + shift + o

2.2 继承性

2.2.1 类和类之间的关系

1.关联(包含) ”有“ has a

2.继承(泛化) ”是“ is a

3.依赖 ”用“ use a

1.关联(包含关系) A类中包含B类类型的属性 : 1对1 1对多(对象数组,集合) 多对多

 class  A{
     //一对多
     private B[] b;
     
     //一对一
     private  C c;
 }
 ​
 class B{
 ​
 ​
 }
 class C{
 ​
 }

例如: 订单类 : 一个账户类 ,n个商品类

2.继承 A类满足B类,A类继承B的代码

 public class A extends B{
 ​
 ​
 }

例如: 猫类继承动物类

3.依赖 A类的某个行为依赖于B类实现

 public class  Student{
 ​
     public void goToSchool(Bike b){
         
     }
     public void goToSchool(Car c){
         
     }
     public void goToSchool(Bus b){
         
     }
     // ..
 ​
 }

关联关系: A类包含B类,B类作为A类的属性

例子: 动物园 老虎 ; 餐馆 菜品 ; 运动会 体育项目 ; 美女类 衣服类

图书馆,书籍类 ; 美团 商铺 ; 超市 商品....

银行客户 账户;面向对象编程(全)_第5张图片

 

用户类:

 package com.qf.oop.bank;
 ​
 public class User {
     private String name;
     private String card;
     private String tel;
     //包含
     private Account acc;
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     }
     public String getCard() {
         return card;
     }
     public void setCard(String card) {
         this.card = card;
     }
     public String getTel() {
         return tel;
     }
     public void setTel(String tel) {
         this.tel = tel;
     }
     public Account getAcc() {
         return acc;
     }
     public void setAcc(Account acc) {
         this.acc = acc;
     }
     @Override
     public String toString() {
         return "user [name=" + name + ", card=" + card + ", tel=" + tel + ", acc=" + acc + "]";
     }
     public User(String name, String card, String tel) {
         super();
         this.name = name;
         this.card = card;
         this.tel = tel;
     }
     
     public User() {
         
     }
     
 }
 ​

账户类:

 package com.qf.oop.bank;
 ​
 public class Account {
     
     private int accNo;
     private String pass;
     private double balance;
     public Account(int accNo, String pass, double balance) {
         super();
         this.accNo = accNo;
         this.pass = pass;
         this.balance = balance;
     }
     public Account() {
         
     }
     public int getAccNo() {
         return accNo;
     }
     public void setAccNo(int accNo) {
         this.accNo = accNo;
     }
     public String getPass() {
         return pass;
     }
     public void setPass(String pass) {
         this.pass = pass;
     }
     public double getBalance() {
         return balance;
     }
     
     @Override
     public String toString() {
         return "Account [accNo=" + accNo + ", pass=" + pass + ", balance=" + balance + "]";
     }
     
     /**
      * 存钱
      */
     public boolean deposit(double mon) {
         if(mon > 0 && mon % 100 == 0) {
             balance += mon;
             return true;
         }else {
             return false;
         }
         
     }
     /**
      * 取钱
      */
     public boolean withdraw(double mon) {
         if(mon <= balance) {
             balance -= mon;
             return true;
         }else {
             return false;
         }       
     }
 }
 ​

银行类:

 package com.qf.homework;
 ​
 import java.util.Scanner;
 ​
 public class Banking {
     public static void main(String[] args) {
         int[] acc = { 1001, 1002 };
         String[] pass = { "123456", "666666" };
         double[] balance = { 5000, 1000 };      
         Scanner sc = new Scanner(System.in);
         while (true) {
             System.out.println("欢迎使用ATM系统:1.登录 2.退出系统");            
             System.out.println("请输入操作编号:");
             int opp = sc.nextInt();
             if(opp == 1) {
                 System.out.println("请输入您的账户名:");
                 int no = sc.nextInt();
                 // 查找账户
                 int index = -1;
                 for (int i = 0; i < acc.length; i++) {
                     if (acc[i] == no) {
                         index = i;
                         break;
                     }
                 }
                 if (index != -1) {
                     System.out.println("请输入您的密码:");
                     String password = sc.next();
                     if (pass[index].equals(password)) {
                         // 密码正确
                         System.out.println("登录成功");
                         while (true) {
                             System.out.println("1.存钱");
                             System.out.println("2.取钱");
                             System.out.println("3.查看余额");
                             System.out.println("4.转账");
                             System.out.println("5.退出");
 ​
                             System.out.println("请输入操作编号");
                             int opr = sc.nextInt();
                             if (opr == 1) {
                                 System.out.println("请输入存款金额");
                                 // 整百> 0
                                 double money = sc.nextDouble();
                                 if (money % 100 == 0 && money > 0) {
                                     balance[index] += money;
                                 } else {
                                     System.out.println("金额有误");
                                 }
                             } else if (opr == 2) {
                                 System.out.println("请输入取款金额");
                                 // 判断
                                 double money = sc.nextDouble();
                                 if (money > 0 && money <= balance[index]) {
                                     balance[index] -= money;
                                 } else {
                                     System.out.println("余额不足");
                                 }
                             } else if (opr == 3) {
                                 System.out.println("当前余额:" + balance[index]);
                             } else if (opr == 4) {
                                 System.out.println("请输入转账账户");
                                 int no2 = sc.nextInt();
                                 int index2 = -1;
                                 for (int i = 0; i < acc.length; i++) {
                                     if (acc[i] == no2) {
                                         index2 = i;
                                         break;
                                     }
                                 }
                                 if (index2 != -1) {
                                     System.out.println("请输入转账金额");
                                     double m = sc.nextDouble();
                                     if (m <= balance[index]) {
                                         // index2 账户+
                                         balance[index2] += m;
 ​
                                         // index -
                                         balance[index] -= m;
                                         System.out.println("转账成功");
                                     } else {
                                         System.out.println("金额不足");
                                     }
 ​
                                 } else {
                                     System.out.println("无此账户,无法转账");
                                 }
                             } else if (opr == 5) {
                                 break;
                             } else {
                                 System.out.println("操作错误");
                             }
                         }
                     } else {
                         System.out.println("密码错误");
                     }
                 } else {
                     System.out.println("无此账户");
                 }
             }
             else if(opp == 2){
                 System.exit(0);
             }else {
                 System.out.println("操作错误");
             }           
         }
     }
 }
 ​

测试类:

 package com.qf.oop.bank;
 ​
 public class TestBank {
     public static void main(String[] args) {
         new Bank();
     }
 }
 ​

2.2.2 什么是继承?

利用现有的类构建新的类的过程,代码的继承。

现有的类 : 父类 , 根类 , 超类 , 基类

构建新类 : 子类 , 派生类 , 衍生类

“是” , is a 如 : 老虎类 动物类 (子类 满足父类特性,子类相对具体,父类相对抽象); 鞋子类 服装类 ; 小学生类 学生类

2.2.3 继承的作用?

代码重用,避免代码冗余

2.2.4 如何实现继承?

 控制权限   class  子类  extends  父类{
 ​
     
 }

注意:

控制权限: public 或者 不加权限default

子类继承时的父类只能一个

父类:

 public class Emp extends Object{
     private int eNo;
     private String eName;
     private double eSal;
     
     
     public int geteNo() {
         return eNo;
     }
     public void seteNo(int eNo) {
         this.eNo = eNo;
     }
     public String geteName() {
         return eName;
     }
     public void seteName(String eName) {
         this.eName = eName;
     }
     public double geteSal() {
         return eSal;
     }
     public void seteSal(double eSal) {
         this.eSal = eSal;
     }
     public Emp(int eNo, String eName, double eSal) {
         super();
         this.eNo = eNo;
         this.eName = eName;
         this.eSal = eSal;
     }
     
     public Emp() {
         
     }
     
     
     @Override
     public String toString() {
         return "Emp [eNo=" + eNo + ", eName=" + eName + ", eSal=" + eSal + "]";
     }   
 }

子类:

 public class Manager extends Emp{
     //奖金
     private double bonus;
 ​
     public double getBonus() {
         return bonus;
     }
 ​
     public void setBonus(double bonus) {
         this.bonus = bonus;
     }
 ​
     @Override
     public String toString() {
         //super.toString() 父类的
         return super.toString() + "Manager [bonus=" + bonus + "]";
     }   
 }

测试类:

         Manager m = new Manager();
         m.seteNo(2);
         m.seteName("rose");
         m.seteSal(6000);
         m.setBonus(30000);
         System.out.println(m);

2.2.5 可以继承哪些?

可以继承: 非私有的属性和方法

不可以: 私有的,构造方法不可以继承的

因此: 子类中: 父类的成员 + 子类自己成员

2.2.6 继承后的问题

1.JAVA中的继承关系? 类和类之间只存在单继承(一个父类可以有多个子类,每个子类只能一个父类)

2.JAVA中继承关系时多层的,越是上层级越抽象,越是下层级越具体

面向对象编程(全)_第6张图片

 

  1. Object是所有类的祖先类,顶级的,所有的类都直接或间接继承该类。

  2. JAVA中的权限(重点)

public protected 缺省 private
含义 公开的 受保护的 友好的,默认的 私有的
范围 整个项目 同包访问,跨包继承 同包访问 当前类

面向对象编程(全)_第7张图片

 

范围排序: public > protected > 默认 > private

 public class A {
     public int a = 10;
     protected int b = 20;
     int c = 30;
     private int d = 40;
     
 }

使用:

类,接口 : public ,缺省

属性: 四个

方法,构造 : 四个

局部变量 : 没有权限

2.2.7 方法的重载和重写(覆盖)

当多个方法具有相同方法名,如果希望共存,就需要重载或重写。

 方法的重载:(方法的多样化) overload
 ​
 原则:
 ​
 1.方法名相同
 ​
 2.参数必须不同(个数,顺序,类型)
 ​
 3.权限和返回值不影响

 方法的重写:(方法的覆盖,子类将父类继承的方法加以改造)   override
 ​
 原则:
 ​
 1.方法名相同
 ​
 2.参数必须相同
 ​
 3.返回值必须相同
 ​
 4.权限不能降低   public > protected > 默认  > private

 package com.qf.oop;
 ​
 public class Father {
     /**
      * 重载
      * @param t
      */
     public void eat() {
         
         System.out.println("爸爸吃肉");
     }
     public void eat(String t) {
         System.out.println();
     }
     public int eat(String t,double k) {
         return 0;
     }
 }
 ​
 class Son extends Father{
     /**
      * 重写
      */
      public void eat() {
         System.out.println("孩子喝奶");
     }   
 }
 public class TestFather {
     public static void main(String[] args) {
         Father f = new Father();
         //爸爸吃肉
         f.eat();
         
         Son s = new Son();
         //调用重写之后的方法
         //孩子喝奶
         s.eat();
         s.eat("哇哈哈");
     }
 }

总结重载和重写的区别:

重载 重写(覆盖)
overload override
目的 方法多样化 子类覆盖父类
参数 参数必须不同 参数必须相同
权限 不限制 子类不能降低权限
返回值 不限制 必须相同
位置 本类,父子类 父子类
次数 n次 1次
异常 不限制 子类不能抛出更多异常

2.2.8 继承中的构造方法(难点)

  1. 子类不能继承父类的构造方法

  2. 子类需要手动调用父类的构造方法的:

 public 子类(类型  形参变量 ){
     //父类继承的属性
     super(实参1,实参2);
     //自己定义的属性
     this.xx = xx;
 }

子类手动调用父类的构造方法:

 public Manager(int eNo, String eName, double eSal,double bonus) {
         //调用父类
         super(eNo,eName,eSal);
         //自己
         this.bonus = bonus;
     }
 //调用
 public Emp(int eNo, String eName, double eSal) {
         super();
         this.eNo = eNo;
         this.eName = eName;
         this.eSal = eSal;
     }
 ​
 //实例化:
   public class TestEmp {
     public static void main(String[] args) {
         //Emp e = new Emp(1, "jack", 4000);
         
         //System.out.println(e);    
         Manager m = new Manager(2, "rose", 6000, 30000);
 //      m.seteNo(2);
 //      m.seteName("rose");
 //      m.seteSal(6000);
 //      m.setBonus(30000);
         System.out.println(m);          
     }
 } 
 3. 继承中,构造方法执行顺序:  祖先 >  父类  > 子类
 4. 当构造方法的第一行没有super(参数) ,系统默认提供super(); 自动调用父类的默认构造,因此,保证空构造
 public class GrandPa {
     
     public GrandPa() {
         super();
         System.out.println("爷爷来啦");
     }
 }
 ​
 public class Father extends GrandPa{
     public String name;
     
     public Father(String name) {
         //super()
         System.out.println("爸爸来啦");
     }
     
 //  public Father() {
 //      
 //  }
 }
 ​
 public class Son extends Father{
     
     public Son(String name) {
         //super()
         super(name);
         System.out.println("孩子也来啦");
     }
     
 }
 ​
 public class TestSon {
     public static void main(String[] args) {
         Son son = new Son("jack");
         
     }
 }

2.2.9 总结super和this的使用

super的用法:

  1. 在子类中调用父类的被覆盖的属性和方法

 public class Student extends Person{
     public String name = "小王";
 ​
     @Override
     public String toString() {
         return "父亲:" + super.name + ";孩子:" + this.name;
     }   
 }

 public class Student extends Person{
     public String toy;
 ​
     @Override
     public String toString() {
         return super.toString() + "toy=" + toy; 
     }
 }

2.调用父类的构造方法

     public Person(String name) {
         this.name = name;
     }
     public Person() {
         //super(); //默认的
     }

     public Student() {
         //super();//父类的空构造
     }
     public Student(String name) {
         super(name); // 手动调用
     }

注意: super() 调用构造方法,一定放在构造方法的首行。

this的用法:(当前对象,对象本身)

  1. 调用本类的属性和方法(尤其全局变量被局部变量覆盖)

 public void setToy(String toy) {
         this.toy = toy;
     }

2. 调用本类的构造方法

     public Emp(int empno, String ename, double sal, int deptno) {   
         this(empno,deptno); //调用下面的构造方法
         this.ename = ename;
         this.sal = sal;
         
     }
     
     public Emp(int empno, int deptno) {
         super();
         this.empno = empno;
         this.deptno = deptno;
     }

注意:this() 调用构造方法,一定放在构造方法的首行。

2.3 多态性

2.3.1 什么是多态?

一个父类呈现出了多个子类形态,同一个动作展现出不一样的行为。

真正意义上的多态:

 父类  多态对象  =  new  子类(); // 向上转型

父类: Animal

子类: Tiger Rabbit Cat Dog Pig ....

 Animal a = new Animal()
 Tiger t = new Tiger();
 Cat c = new Cat();
 Dog d = new Dog();

灵活的多态:

 Animal a  =  new  Dog();

生活中多态例子: USB : 风扇 , 键盘,鼠标,加湿器

 USB  b = new Mouse();
 USB  b = new  KeyBoard();

2.3.2 多态的好处?

使得代码更加灵活,扩展性强

2.3.3 深入分析多态

 Animal a  =  new  Dog();

角度1:类型转换(编译角度)

当有继承关系:

 父类  对象名  = new  子类();  // 自动转换   向上转型
 子类  对象名  = (子类)new  父类();  // 强制转换   向下转型

角度2: 多态底层的运行

面向对象编程(全)_第8张图片

 

2.3.4 多态对象的访问

只能访问父类的成员,当且仅当子类覆盖父类方法,执行子类的方法。

2.3.5 多态设计的必要条件

 1.继承,一个父类有多个子类
 2.子类必须覆盖父类的方法
 3.对象向上转型

父类:

 public class USB {
     private String name;    
     public USB() {
         
     }
     public USB(String name) {
         super();
         this.name = name;
     }
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     }
     public void use() {
         System.out.println("usb工作....");
     }
 }

子类:

 public class Mouse extends USB{
 ​
     @Override
     public void use() {
         System.out.println(getName() + "usb鼠标工作....");
     }
 ​
     public Mouse() {
         super();
         // TODO Auto-generated constructor stub
     }
 ​
     public Mouse(String name) {
         super(name);
         // TODO Auto-generated constructor stub
     }   
 }
 ​
 public class KeyBoard extends USB{
 ​
     @Override
     public void use() {
         System.out.println(getName() + "usb键盘工作....");
     }
 ​
     public KeyBoard() {
         super();
         // TODO Auto-generated constructor stub
     }
 ​
     public KeyBoard(String name) {
         super(name);
         // TODO Auto-generated constructor stub
     }   
 }

测试类:

 public class TestUSB {
     public static void main(String[] args) {
         //USB u = new Mouse("罗技");
         USB u = new KeyBoard("樱桃");
         u.use();        
     }
 }

2.3.6 多态的实际应用

依赖关系的传参

 public class Developer {
     /**
      * 依赖关系
      * @param u
      */
     public void useTool(USB u) {
         //调用覆盖的方法
         u.use();
     }   
 }

开发人员测试工具:

 public class TestUSB {
     public static void main(String[] args) {
         Developer d = new Developer();
         d.useTool(new KeyBoard("樱桃"));//USB u = new KeyBoard("樱桃");
     }
 }

注意: 构造方法不能重写,可以重载

2.3.7 instanceof 向下转型

用于判断某个对象具体是哪一种类型的:(看new)

 对象   instanceof   类型(类/接口)

1.返回的是布尔类型: true(对象就是类型;对象是类型的子类类型) ; false(不是这个类型的)

2.如果对象和类型没有任何联系,出现编译错误

         Cat c = new Cat();
         Animal a = new Animal();        
         Animal a2 = new Tiger();//向上转型 多态对象
 ​
 ​
         System.out.println(c instanceof Cat);   // true  对象就是猫类型    
         System.out.println(c instanceof Animal); // true  对象就是猫类型 是Animal子类 
         System.out.println(a instanceof Animal); 
         
         //System.out.println(c instanceof Student);
         //System.out.println(c instanceof Tiger);// Tiger Cat没有联系,没有兄弟关系
             
         System.out.println(a instanceof Cat); // false  动物对象不一定是猫
         
         System.out.println(a instanceof Object);//true
         System.out.println(c instanceof Object);//true
         
         System.out.println(a2 instanceof Cat);//判断是否是猫

目的是多态对象向下转型,获取子类中的资源:

 Animal a = new Cat();
 a.eat();
 if(a instanceof Tiger) {
             Tiger t = (Tiger)a;//向下转型
             t.ao();
 }

第三章 面向对象高级特性

3.1 abstract

3.1.1 什么是abstract?

抽象的,难以描述清楚,比较笼统。概念模糊。

3.1.2 abstract可以修饰哪些?

1.类 抽象类(抽象父类)

 public abstract class 类名{
     
 }

2.方法 抽象方法

 控制权限   abstract  返回类型  方法名(形参类型 变量 ,形参类型 变量2 ) ;

3.1.3 抽象类的特征

1.抽象类一般作为父类,抽象类不能实例化

2.抽象父类强制要求必须有子类继承,子类将其描述清楚(必须有子类继承)

3.子类继承抽象父类之后,必须重写里面所有的抽象方法*,否则该类就成为抽象类*

4.抽象类中不一定都是抽象方法,可以有非抽象的; 有抽象方法的类必须是抽象类

5.抽象类是否包含构造方法?

抽象父类:

 public abstract class Fly {
     private String name;
     /**
      * 抽象方法
      */
     public abstract void fly();
     
 //  public abstract void hua();
     
     /**
      * 非抽象
      * @return
      */
     public String getName() {
         return name;
     }
 }

子类继承和覆盖:

 public class Bird extends Fly{
     @Override
     public void fly() {
         System.out.println("鸟飞行");
         
     }
 }
 ​
 public class Plane extends Fly {
     @Override
     public void fly() {
         System.out.println("飞机飞行");
 ​
     }
 }

测试类:

public class TestFly {
	public static void main(String[] args) {
        //抽象类不能实例化对象
		//Fly f = new Fly();
		//向上转型
		Fly f = new Plane();
		f.fly();
	}
}

注意:抽象父类有构造方法,给子类调用的。

3.1.4 抽象方法的特征

1.无法描述的行为,一定不能有方法体,不能加{ }

2.包含抽象方法的类一定是抽象类

public abstract void fly();

3.2 static

3.2.1 什么是static?

静态的,属于类的,不再属于某一个对象。

3.2.2 static可以修饰什么?

属性,方法,内部类

public class Test {
	//静态属性,类属性
	private static int a ;
	
	/**
	 * 静态方法,类方法
	 * @param args
	 */
	public static void test() {
        //局部变量不能static
		int b = 10;
	}
}

3.2.3 静态属性?

加static的属性: 静态属性,类属性,是所有对象共享的资源,不再单独属于某个对象。例如: 共享汽车 私家车 ;网吧电脑,自己电脑;

不加的属性 : 实例属性, 是每个对象独有的资源。

人: 姓名 年龄 科目(灵长目类), 肤色

 public class Person {
     //实例属性
     private String name;
     private int age;
     //静态属性
     private static String type = "灵长目";
     
 }

检测静态属性的特点:

 package com.qf.oop;
 ​
 public class TestStatic {
     public int i = 10;
     public static int j = 20;
     
     public TestStatic() {
         i ++;
         j ++;
     }
     
     public static void main(String[] args) {
         TestStatic t1 = new TestStatic();
         System.out.println(t1.i + "," + t1.j);// 11 21
         
         TestStatic t2 = new TestStatic();
         System.out.println(t2.i + "," + t2.j);// 11 22  
         
     }
 }

堆栈图:

面向对象编程(全)_第9张图片

 

静态属性和实例属性的区别:(记住)

静态属性 实例属性
含义 属于类的,对象共享资源 每个对象独有
个数 一个类一份拷贝 n份
内存分配 静态区
初始化时机 类加载的时候(类使用之前) 创建对象
调用 类.静态属性 / 对象.静态属性 对象.实例属性

调用:

public class TestStatic {
	public int i = 10; //实例属性
	public static int j = 20; //静态属性
	
	public TestStatic() {
		i ++;
		j ++;
	}
	
	public static void main(String[] args) {
		
		TestStatic t = new TestStatic(); // B 错误 其余都对
		// A t.i
		// B TestStatic.i
		// C TestStatic.j
		// D t.j
	}
}

3.2.4 静态方法?

  1. 静态方法只能调用静态的属性和方法,不可以调用非静态属性和方法

  2. 实例方法可以调用静态的方法

  3. 当静态方法就是要调用非静态: 只能创建对象

  4. 类名.静态方法()推荐的 / 对象.静态方法() 可以的

package com.qf.oop;
/**
 * 测试静态方法的调用
 * @author 86136
 *
 */
public class Test2 {	
	int a = 10;
	static int b = 10;
		
	public static void main(String[] args) {
		System.out.println(Math.random());
		
		t1();
		//非静态方法先创建对象才使用
		Test2 ttt = new Test2();
		ttt.t3();
	}
	//静态方法
	public static void t1() {
		System.out.println(b);
		Test2 ttt = new Test2();
		System.out.println(ttt.a);
		t2();
		//t3();
	}

	public static void t2() {
		
	}
	//实例方法
	public  void t3() {
		System.out.println(a);
		System.out.println(b);
		t1();
		t2();
	}
}

3.2.4 静态代码块?

静态代码块用于初始化静态的成员。

//静态代码块
static{
    
   // 初始化静态属性
}
//实例代码块
{
		
}

1.位置 和构造方法同级

2.个数 可以有多个,按照顺序执行

3.时机 类加载时

4.次数 1次

5.顺序 静态 1> 实例 n > 构造 n

public class Test3 {
	
	public static int a ;
	public int b;
	
	static {
		//a = 20;
		System.out.println("静态代码块");
	}
//	static {
//		a = 30;
//	}
	
	{
		System.out.println("实例代码块");
	}
	
	public Test3(int b) {
		System.out.println("构造方法");
		this.b = b;
	}
    
}

3.3 final

3.3.1 什么是final?

最终的,最后的。

3.3.2 final修饰什么?

变量(属性+局部变量) 常量

方法

public final class TestFinal {
	public final String TEACHER = "Miss Yu";
	
	public final void test() {
		final int YEAR = 365;
	}
}

3.3.3 final修饰内容的特点?

  1. final修饰的变量: 常量,一经定义不能改 ; final修饰的属性必须设置初始值,不可以使用默认值

  2. final修饰的方法: 不能被重写

  3. final修饰的类 : 不能有子类(最后的类)

JAVA中哪些类final修饰类: Math ,String,Integer

3.4 修饰符共用

abstract: 类 方法

static : 属性 方法

final: 变量 方法 类

1.不能混合使用

abstract和static

abstract和final

abstract 和 private

2.可以混用

static和final可以一起修饰属性和方法,不限制顺序

public class TestFinal2 {
	
	public final static int AGE = 20;
	public static final double PI = 3.14159265358979323846;
	public static void main(String[] args) {
		
		System.out.println(TestFinal2.AGE);
		System.out.println(TestFinal2.PI);
	}
	
	public static final void test() {
		
	}
}

第四章 接口

4.1 接口的意义

当一个子类继承了父类之后,不能具备其他父类的特性,接口可以使得类具备多种特性。

目的是解决单继承问题。

接口作为引用数据类型,抽象概念,只定义方法声明。 what is ?(定义是什么) How is ?(怎么样不管)

注意:开发中,设计和实现是分离的,接口是设计层面,架构师设计有什么; 类是实现层面,将接口中定义的内容具体实现

4.2 接口的定义

控制权限  interface  接口名{
	
	
}

注意:

1.控制权限 public 缺省

2.关键字 interface

3.接口名 : 同类名 , IWeapon , IVehicles

4.3 接口的实现

控制权限  class  实现类  extends 父类  implements 接口1,接口2...{
	
	
}

注意:

实现类可以同时实现多个接口,具备多种特性

继承只能一个父类 ,实现多个接口 (单继承,多实现)

案例:

 //武器接口
 public interface IWeapon {
 ​
 }
 //交通工具接口
 public interface IVehicles {
 ​
 }
 //钢铁父类
 public abstract class Iron {
 ​
 }
 //实现类
 public class Tank extends Iron implements IWeapon,IVehicles{
 ​
 }
 //抽象类实现
 public abstract class UFO implements IWeapon, IVehicles{
 ​
 }

注意: XXXImpl

4.4 接口中的成员

 属性: 公开的静态常量    public  static  final = 初始值;
 方法: 公开的抽象方法    public  abstract  返回值  方法名(参数) ;

注意:

  1. 接口中属性和方法的修饰符全是默认的定死的,即使省略,必须是该类型

  2. 接口中没有构造方法,肯定不能实例化

public interface IWeapon {
	//静态常量
	public static final int POWER = 100;
	int DEFENCE = 50;
	
	//抽象方法
	public abstract void fire() ;	
	String fix(int hour);
	
	
}

4.5 实现类的实现

1.覆盖接口中所有的抽象方法

public class Gun implements IWeapon{

	@Override
	public void fire() {
		System.out.println("开炮");
		
	}

	@Override
	public String fix(int hour) {
		System.out.println("保养" + hour + "小时");
		return "恢复,准备就绪";
	}
}

2.接口中的常量

接口名.属性,直接使用,不能修改

3.接口中多态

接口类型  多态对象  = new  实现类();

public interface Photograph {
	void shot();
}
class Camera implements Photograph{
	
	@Override
	public void shot() {
		System.out.println("相机拍照");
	}
	
}
class Phone implements Photograph{
	
	@Override
	public void shot() {
		System.out.println("手机拍照");
	}
	
}

public class Photographer {
	private static final String NAME = "义民"; 
	/**
	 * 使用设备拍照
	 */
	public void takePhoto(Photograph p) {
		System.out.println(NAME + "拍照:");
		p.shot();
	}
	
	/**
	 * 测试
	 */
	
	public static void main(String[] args) {
		new Photographer().takePhoto(new Camera());
	}
}

4.6 类和接口的关系

关系 继承角度 关键字
类和类 单继承 一个父类多个子类,每个子类一个父类 extends public class 子类 extends 父类{}
类和接口 多实现 接口多个实现类,每个实现类实现多个接口 implements public class 实现类 implements 接口1,接口2...{}
接口和接口 多继承 父接口可以有多个子接口,每个子接口继承多个父接口 extends public interface 子接口 extends 父接口1,父接口2...{}

public interface A extends B,C{

}

interface B {

}

interface C {

}

4.7 抽象类和接口的区别(重点)

抽象类 接口
定义 abstract class interface
属性 自定义 private public static final
方法 自定义 (抽象+非抽象) public abstract
构造方法
与类关系 单继承 多实现

相似点: 1. 都有抽象的方法存在 2.都不能实例化对象,都不能new

特例: jdk8+

public interface More {
	
	public  abstract  void test();
	
	/**
	 * jdk8+ 非抽象方法
	 */
	public default void test2() {
		
	}
}

第五章 枚举

5.1 枚举的意义

枚举表示一一列举,用于一组固定的离散值,比如:性别固定 男,女 ; 月份 1-12 ; 四季 , 星期, 十二生肖 , 四大名著,人民币面值(100,50,20,10,5,1), 交通灯(红色,绿色,黄色),26字母。

5.2 枚举的作用

  1. 代码的安全更高, 不会非法调用

  2. 降低代码的耦合度

  3. 代码的可读性增强,不会使用int,String代表其含义

5.3 枚举的声明

控制权限  enum  枚举名{
	
	
}

注意:

控制权限 : public 缺省

枚举名 : 首字母大写,合法标识符

5.4 枚举中的成员

控制权限  enum  枚举名{
	枚举常量 , 枚举常量2 ;	
}

5.5 枚举中的成员调用

枚举名.枚举常量

 public enum Light {
     RED,GREEN,YELLOW;
 }
 public class TestLight {
     public static void main(String[] args) {
         System.out.println(Light.RED);
     }
 }

在switch中使用枚举:

 /**
  * 交通
  * @author 86136
  *
  */
 public class Traffic {
     //定义属性,切换完信号灯的颜色
     private Light curr ;
 ​
     public Light getCurr() {
         return curr;
     }
     public void setCurr(Light curr) {
         this.curr = curr;
     }   
     /**
      * 信号切换
      */
     public Light change(Light l) {
         switch (l) {
         case RED:
             curr = Light.GREEN;
             break;
         case YELLOW:
             curr = Light.RED;
             break;
         case GREEN:
             curr = Light.YELLOW;
             break;
         }
         
         return curr;
     }
 }
 /*测试*/
 public class TestTraffic {
     public static void main(String[] args) {
         Traffic t = new Traffic();
         //切换
         System.out.println(t.change(Light.RED));
     }
 }

5.6 工厂模型

23种设计模式: 单例模式,静态工厂模式,代理模式,生产者消费者....

单例模式: 获得对象实例只有一个

 public class  Singleton{
     private static Singleton ins = new Singleton();
     
     /**
     使用方法返回一个实例*/
     
     public static Singleton getSingleton(){
         
         return ins;
     }
     
 }

案例:

 public class Earth {
     private static Earth ins = new Earth();
     
     private Earth() {
         
     }
     
     /**使用方法返回一个实例*/
     
     public static Earth getEarth(){
         
         return ins;
     }
 }
 ​
 public class TestEarth {
     public static void main(String[] args) {
         Earth e1 = Earth.getEarth();
         Earth e2 = Earth.getEarth();
         
         System.out.println(e1 == e2);//单实例
     }
 }

静态工厂模式: 根据类型需要,生产对象。

 public interface IShoe {
     
     public abstract void info();
 }
 public enum ShoesType {
     ADIDAS,NIKE,ANTA;
 }
 public class Nike implements IShoe{
 ​
     @Override
     public void info() {
         System.out.println("耐克鞋轻巧好穿");
     }
 ​
 }
 public class Adidas implements IShoe{
 ​
     @Override
     public void info() {
         System.out.println("阿迪好看,抗造");
     }
 ​
 }
 public class Anta implements IShoe{
 ​
     @Override
     public void info() {
         System.out.println("安踏永不止步");
     }
 ​
 }
 /**
  * 静态工厂
  * @author 86136
  *
  */
 public class ShoesFactory {
     
     private static IShoe shoe;
 ​
     /**
      * 多态属性
      * @param type
      * @return
      */
     public static  IShoe  make (ShoesType type) {
         switch (type) {
         case ADIDAS:
             shoe = new Adidas();
             break;
 ​
         case NIKE:
             shoe = new Nike();
             break;
             
         case ANTA:
             shoe = new Anta();
             break;
         }
         
         return shoe;
     }
         
 }
 public class TestFactory {
     public static void main(String[] args) {
         //多态
         IShoe shoe = ShoesFactory.make(ShoesType.NIKE);
         shoe.info();
     }
 }

第六章 内部类

6.1 什么是内部类?

定义在类里的类,称之为内部类,外部的叫做外部类。

6.2 内部类的分类

① 静态内部类

② 实例内部类

③ 局部内部类

 public class Outer {
     /**
      * 静态内部类
      *
      */
     public static class Inner{
         public int a  = 10;
         public static int b = 20;
     }
     /**
      * 实例内部类
      *
      */
     public class Inner2{
         public int a = 30;
     }
     
     public void test() {
         //局部内部类
         class Inner3{
             
         }
     }
 }

静态内部类:

外部类.静态内部类

public class TestInner1 {
	public static void main(String[] args) {
		Outer.Inner inner = new Outer.Inner();
		System.out.println(inner.a);
		System.out.println(Outer.Inner.b);		
	}
}

实例内部类:

new 外部类().new 实例内部类();

public class TestInner2 {
	public static void main(String[] args) {
		Outer.Inner2 inner2 = new Outer().new Inner2();
		
		System.out.println(inner2.a);
	}
}

局部内部类:看方法,外部类调用方法

public void test() {
		//局部内部类
		class Inner3{
			int a = 50;
			
			public void test2() {
				System.out.println("局部内部类");
			}
		}
		Inner3 inner3 = new Inner3();
		System.out.println(inner3.a);
		inner3.test2();
	}
public class TestInner3 {
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.test();
	}
}

6.3 匿名内部类(重点)

① 该内部类没有名字

② 以上三种内部类都可以是匿名的,主要是局部内部类

抽象父类  变量名  =   new  抽象父类(){
	//抽象父类的子类的类体

}

接口  变量名  =   new  接口(){
	//实现类的类体
}

public interface IAnimal {
	void eat();
}

         IAnimal animal = new IAnimal() {
 ​
             @Override
             public void eat() {
                 System.out.println("小猫吃老鼠");
             }
             
         };
         
         animal.eat();
         
         //lambda JDK8+
         IAnimal animal2 = () -> System.out.println("小鹿吃草");
         
         animal2.eat();

你可能感兴趣的:(java,servlet,开发语言)