DAY07

变量

局部变量
位置: 定义在方法里或者局部代码块中
注意: 必须手动初始化来分配内存.如:int i = 5;或者int i; i = 5;
作用域: 也就是方法里或者局部代码块中,方法运行完内存就释放了

成员变量
位置: 定义在类里方法外
注意: 不用初始化,也会自动被初始化成默认值
作用域: 整个类中,类消失了,变量才会释放

构造代码块与局部代码块

构造代码块的特点

1) 位置: 在类的内部,在方法的外部
2) 作用: 用于抽取构造方法中的共性代码
3) 执行时机: 每次调用构造方法前都会调用构造代码块
4) 注意事项: 构造代码块优先于构造方法加载

局部代码块

1) 位置: 在方法里面的代码块
2) 作用: 通常用于控制变量的作用范围,出了花括号就失效
3) 注意事项: 变量的作用范围越小越好,成员变量会存在线程安全的问题

继承

概念
继承是面向对象最显著的一个特性。
继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展
新的能力。
Java 继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新
的数据戒新的功能,也可以用父类的功能,但不能选择性地继承父类/超类/基类。
这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。
提高复用性:只要继承父类,就能有一样的功能
注意:构造方法不能被继承

特点
1、使用 extends 关键字
2、相当于子类把父类的功能复制了一份
3、java 只支持单继承
4、继承可以传递(爷爷,儿子,孙子的关系)
5、不能继承父类的私有成员
6、继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展
7、像是 is a 的关系

super关键字
1、通过 super 关键字可以使用父类的内容
2、super 代表父类的一个引用对象
3、如果用,必须出现在调用位置的第一行

方法重写Override
1、继承后,子类就拥有了父类的功能
2、那么在子类中,可以添加子类特有的功能也可以修改父类的原有功能
3、子类中方法签名与父类完全一样(包括方法的返回值,方法名和参数列表,完全一致)
时,会发生覆盖/复写操作,相当于修改功能
注意:
1、父类中的私有方法不能被重写
2、子类重写父类方法时,修饰符要大于等于父类修饰符的权限

拓展

this 与 super的区别
1) This代表本类对象的引用
class Father3{ this.XXX } //this — Father3 this = new Father3();
2) super代表父类对象的引用
class Father3{ super.XXX } //this — Father3 super = new Father3();
就相当于创建了一个父类对象
3) this可以在两个变量名相同时,用于区分成员变量和局部变量
4) this 可以在本类的构造方法之间调用,位置必须是第一条语句,注意,不能相互调用,会死循环
5) super是发生了继承关系以后,子类如果想用父类的功能,可以通过super调用
6) 如果发生了重写,还想用父类的功能,需要使用super来调用
7) Super在调用父类构造方法时,必须出现在子类构造方法的第一条语句,而且如果父类中没有提供无参构造,子类可以通过super来调用父类其他的含参构造

重载Overload 与 重写Override的区别

  1. 重载: 是指在一个类中的现象,是指一个类中有很多同名的方法,但是方法的参数列表不同
  2. 重写: 是指发生了继承关系以后(两个类),子类去修改父类原有的功能,子类中有一个方法签名(返回值类型 方法名(参数列表) )和父类的一模一样
  3. 重载的意义: 是为了方便外界对方法进行调用,什么样的参数程序都可以找到对应的方法来执行,体现的是程序的灵活性
  4. 重写的意义:是在不修改源码的前提下,进行功能的修改和拓展

    (OCP原则:面向修改关闭,面向拓展开放)

  5. 重写要求方法的修饰符: 子类权限 >= 父类的权限

    DAY08

    static关键字
    概念:
    是java中的一个关键字
    用于修饰成员(成员变量和成员方法)

静态代码块格式

static {}
静态资源随着类的加载而加载,并且只被加载一次,一般用于项目的初始化
特点: 被static修饰,位置在类里方法外

特点
1) 可以修饰成员变量与成员方法
2) 随着类的加载而加载,优先于对象加载
3) 只加载一次,就会一直存在,不再开辟新空间, 直到类消失才一起消失
4) 静态资源也叫做类资源,全局唯一,被全局所有对象共享
5) 可以直接被类名调用
6) 静态只能调用静态,非静态可以随意调用
7) static不能和this或者super共用,因为有static时可能还没有对象

静态代码块、构造代码块和局部代码块:

//总结:
//1,代码块间的执行顺序:静态代码块,构造代码块,局部代码块
//2,为什么是这样的顺序呢?
//原因:静态代码块优先于对象加载,是随着类的加载而加载到内存中的,只加载一次,并且一直存在,直到类消失,它才会消失。专门用来完成一些需要第一时间加载并且只需要加载一次
//构造代码块是在创建对象时才会触发,专门用来提取构造方法的共性
//局部代码块是方法调用时才会触发,专门用来控制变量的作用范围

多态

概念:

多态指同一个实体同时具有多种形式。
它是面向对象程序设计(OOP)的一个重要特征。
主要是指同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
好处是:可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。
水果有两种形态:水果和苹果,不关心买回来的是苹果还是西瓜,只要是水果就行 DAY07-DAY010复习(3.6-3.11) - 图1特点
1) 多态的前提1:是继承
2) 多态的前提2:要有方法的重写
3) 父类引用指向子类对象,如:Animal a = new Cat();
4) 多态中,编译看左边,运行看右边
06.png
多态入门案例

  1. /**本类用于测试多态*/
  2. public class Test5 {
  3. public static void main(String[] args) {
  4. //5.创建父类对象进行测试\
  5. Animal a = new Animal();
  6. a.eat();//小动物Animal吃啥都行~~~
  7. //a.jump();//父类无法使用子类的特有方法
  8. //6.创建子类对象进行测试
  9. Cat c = new Cat();
  10. c.eat();//小猫Cat爱吃小鱼干!!!--调用的是重写以后的功能
  11. c.jump();
  12. //8.创建多态对象进行测试
  13. /**口诀1:父类引用 指向子类对象*/
  14. /**口诀2:编译(保存)看左边,运行(测试)看右边*/
  15. Animal a2 = new Cat();
  16. Animal a3 = new Dog();
  17. a2.eat();//eat()使用的是父类的声明,但使用的是子类的实现方式
  18. a3.eat();
  19. /**多态的出现是为了统一调用标准,向父类看齐
  20. * 父类提供的功能才能用,子类特有的功能用不了*/
  21. }
  22. }
  23. //1.创建父类
  24. class Animal{
  25. //3.创建父类中的普通方法eat()
  26. public void eat() {
  27. System.out.println("小动物Animal吃啥都行~~~");
  28. }
  29. }
  30. //2.创建子类
  31. class Cat extends Animal{
  32. //4.重写父类中的方法--对父类中的代码功能修改
  33. //重写:方法签名保持一致(返回值类型 方法名(参数列表) )
  34. // & 权限修饰符 >= 父类权限修饰符
  35. public void eat() {
  36. System.out.println("小猫Cat爱吃小鱼干!!!");
  37. }
  38. //7.定义了子类特有的方法
  39. public void jump() {
  40. System.out.println("小猫Cat跳的老高啦");
  41. }
  42. }
  43. class Dog extends Animal{
  44. public void eat() {
  45. System.out.println("小狗爱吃肉骨头!!!");
  46. }
  47. }

多态的好处
1) 多态可以让我们不用关心某个对象到底具体是什么类型,就可以使用该对象的某些方法
2) 提高了程序的可扩展性和可维护性
**

多态的使用**

多态成员变量使用测试

  1. /**本类用于多态中的元素测试*/
  2. public class Test6_DuoTai {
  3. public static void main(String[] args) {
  4. //7.创建子类对象进行测试
  5. Dog2 d = new Dog2();
  6. System.out.println(d.sum);//20
  7. d.eat();//小狗要吃肉骨头
  8. d.play();//小狗爱打滚儿~~~
  9. //10.创建多态对象进行测试
  10. /**口诀1:父类引用指向子类对象*/
  11. /**口诀2:编译(保存)看左边,运行(测试)看右边*/
  12. Animal2 a = new Dog2();
  13. /**2.多态中,成员变量使用的都是父类的*/
  14. System.out.println(a.sum);//10
  15. /**3.多态中,成员方法使用的是父类的声明,子类的实现*/
  16. a.eat();
  17. /**4.多态中,如果父子类都有静态方法,使用的是父类的*/
  18. a.play();//玩啥都行
  19. }
  20. }
  21. //1.创建父类
  22. class Animal2{
  23. //2.创建成员变量
  24. int sum = 10;
  25. //3.创建成员方法
  26. public void eat() {
  27. System.out.println("吃啥都行");
  28. }
  29. //8.父类中定义静态方法play()
  30. public static void play() {
  31. System.out.println("玩啥都行");
  32. }
  33. }
  34. /**1.多态的前提:继承+重写*/
  35. //4.定义子类Dog2
  36. class Dog2 extends Animal2{
  37. //5.定义子类的成员变量
  38. int sum = 20;
  39. //6.重写父类的eat()
  40. /**@Override 这个注解加在方法上,表示这是一个重写的方法*/
  41. @Override //注解--标签
  42. public void eat() {
  43. System.out.println("小狗要吃肉骨头");
  44. }
  45. //9.定义子类的静态方法play()
  46. //@Override --不是重写,不能加这个注解
  47. public static void play() {
  48. System.out.println("小狗爱打滚儿~~~");
  49. }
  50. }

/*注意!!!静态资源属于类,不存在重写现象,只是两个类中有同样声明的方法而已,不属于重写/

拓展

设计汽车综合案例

  1. /**本类用于完成OOP汽车设计综合案例*/
  2. /**
  3. * 1.分析事物,得出它的属性和功能
  4. * 2.提取类中的共同点,向上抽取,形成父类Car
  5. * 3.子类继承父类后,就拥有的父类的功能
  6. * 4.如果对父类的功能不满意,可以重写
  7. * 5.可以封装某些类的属性,如果封装了,就要提供对应的get()/set()
  8. */
  9. public class Test7_ExtendsDesignCar {
  10. //3.创建入口函数main
  11. public static void main(String[] args) {
  12. //4.创建父类对象进行测试
  13. Car c = new Car();
  14. System.out.println(c.getColor());//通过get方法查看封装后的color值
  15. c.start();
  16. c.stop();
  17. //5.创建宝马类对象进行测试
  18. BMW b = new BMW();
  19. System.out.println(b.color);
  20. System.out.println("*********");
  21. b.start();
  22. b.stop();
  23. //6.创建保时捷类对象进行测试
  24. BSJ j = new BSJ();
  25. System.out.println(j.color);
  26. j.start();
  27. j.stop();
  28. }
  29. }
  30. //0.创建一个汽车类
  31. class Car{
  32. //0.1定义Car类的属性
  33. //0.3通过private对Car类的属性进行封装
  34. private String brand;//品牌
  35. private String color;//颜色
  36. //0.4属性封装后,对外提供公共的get()与set()便于外界对属性进行操作
  37. //右键-->Source-->Generate Getters and Setters -->Select All -->Generate
  38. public String getBrand() {
  39. return brand;
  40. }
  41. public void setBrand(String brand) {
  42. this.brand = brand;
  43. }
  44. public String getColor() {
  45. return color;
  46. }
  47. public void setColor(String color) {
  48. this.color = color;
  49. }
  50. //0.2定义Car类的启动与停止方法
  51. public void start() {
  52. System.out.println("我的车车启动啦~~~");
  53. }
  54. public void stop() {
  55. System.out.println("哎呀吗,我的车车熄火了~");
  56. }
  57. }
  58. //1.创建一个宝马类并且继承Car类
  59. class BMW extends Car{
  60. String color = "五彩斑斓的黑";
  61. @Override
  62. public void start() {
  63. super.start();
  64. System.out.println("宝马启动加速度~~~UPUP");
  65. }
  66. }
  67. //2.创建一个保时捷并且继承Car类
  68. class BSJ extends Car{
  69. String color = "黑不溜秋的白";
  70. @Override
  71. public void stop() {
  72. System.out.println("保时捷想停的稳当些~");
  73. }
  74. }

静态变量和实例变量的区别:

在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
**

向上转型和向下转型(了解)

在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。
在应用中就存在着两种转型方式,分别是:向上转型和向下转型。
比如:父类Parent,子类Child
向上转型:父类的引用指向子类对象Parent p=new Child();
说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类的方法就根据这个引用指向调用子类重写方法。
向下转型(较少):子类的引用的指向子类对象,过程中必须要采取到强制转型。
Parent p = new Child();//向上转型,此时,p是Parent类型
Child c = (Child)p;//此时,把Parent类型的p转成小类型Child
//其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的
说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。

DAY09

异常

概述

用来封装错误信息的对象
组成结构:类型 提示 行号
TIPS: Ctrl + Shift + T :在eclipse当中查找你想找到的类
Ctrl + T : 查看类的继承结构
Ctrl + O : 查看类的结构信息(大纲)

异常的继承结构

Throwable:顶级父类
—Error:系统错误,无法修复
—Exception:可修复的错误
—RuntTimeException
—ClassCastException
—ClassNotFoundException

异常处理

当程序中遇到了异常,通常有两种处理方式:捕获或者向上抛出
当一个方法抛出异常,调用位置可以不做处理继续向上抛出,也可以捕获处理异常
1) 捕获方式:
try{
需要捕获的代码
}catch(异常类型 异常名){
处理方案
}
2) 抛出方式:
在会发生异常的方法上添加代码:throws 异常类型
例如:public static void main(String[] args) throws Exception{
练习1:异常测试

  1. import java.util.InputMismatchException;
  2. import java.util.Scanner;
  3. /**本类用于测试异常入门案例*/
  4. /**总结8:如果方法抛出异常,那么谁调用谁需要解决(继续抛出/捕获解决)
  5. * 所以main()调用了method3(),也需要抛出异常
  6. * 注意,我们一般在main()调用之前捕获解决异常,而不是抛给main(),因为没人解决了
  7. * */
  8. public class Test1_ExceptionDemo {
  9. public static void main(String[] args) throws Exception{
  10. //1.创建method(),用来人为的暴露异常
  11. //method();
  12. //2.创建method2(),用来进行异常的捕获
  13. //method2();
  14. //3.创建method3(),用来进行异常的抛出
  15. method3();
  16. }
  17. /**
  18. * 抛出的语法:
  19. * 在可能会抛出异常的方法上加throws 异常类型
  20. * 在抛出时,也可以使用多态,不管会发生什么异常,通通被Exception跑出去
  21. */
  22. //public static void method3() throws ArithmeticException,InputMismatchException,Exception{
  23. public static void method3() throws Exception{
  24. //1.复写刚刚可能会发生异常的代码
  25. System.out.println("请输入两个整数:");
  26. int a = new Scanner(System.in).nextInt();
  27. int b = new Scanner(System.in).nextInt();
  28. System.out.println( a/b );
  29. }
  30. /**
  31. * 捕获的语法:
  32. * try{
  33. * 可能会发生异常的代码
  34. * }catch(异常类型 异常参数名){
  35. * 如果捕获到异常的解决方案
  36. * }
  37. */
  38. public static void method2() {
  39. //1.按照捕获语法编写try-catch结构
  40. /**总结4:try{}里放的是可能会发生异常的代码*/
  41. try {
  42. //2.复写刚刚可能会发生异常的代码
  43. System.out.println("请输入两个整数:");
  44. int a = new Scanner(System.in).nextInt();
  45. int b = new Scanner(System.in).nextInt();
  46. System.out.println( a/b );
  47. /**总结5:如果发生异常被捕获,就被匹配对应的解决方案*/
  48. } catch (ArithmeticException e) {//3.1异常捕获1
  49. System.out.println("除数不能为0!");//3.2异常处理1
  50. /**总结6:由于程序中可能存在多种异常,所以catch可以配合多次使用*/
  51. }catch (InputMismatchException e) {//4.1异常捕获2
  52. System.out.println("输入的类型不正确,请输入正确的整数类型!");//4.2异常处理2
  53. /**总结7:如果还有上述两种异常之外的异常,用Exception匹配捕获
  54. * 这个就是多态最为经典的一种用法,我们不关心子类的类型
  55. * 只要是可解决异常,都是Exception的子类,多态会把这些异常当做父类来看,捕获,通过通用方案进行解决
  56. * */
  57. }catch (Exception e) {
  58. System.out.println("请输入正确的整数!");
  59. }
  60. }
  61. public static void method() {
  62. //1.提示并接收用户输入的两个整数:
  63. System.out.println("请输入两个整数:");
  64. int a = new Scanner(System.in).nextInt();
  65. int b = new Scanner(System.in).nextInt();
  66. //2.输出除法运算的结果
  67. //2.1输入9.9 --java.util.InputMismatchException[输入不匹配异常]
  68. //2.2输入9/0 --java.lang.ArithmeticException: / by zero[算术异常,除0了]
  69. System.out.println( a/b );
  70. /**总结1:不要害怕BUG,真正的勇士敢于直面自己写的BUG*/
  71. /**总结2:学会看报错信息的错误提示,确定自己错误的方向*/
  72. /**总结3:学会看报错信息的行号提示,哪里报错点哪里,注意,源码不会错,看自己写的代码*/
  73. }
  74. }

抽象类

抽象类简述

Java中可以定义被abstract关键字修饰的方法,这种方法只有声明,没有方法体,叫做抽象方法.
Java中可以定义被abstract关键字修饰的类,被abstract关键字修饰的类叫做抽象类
如果一个类含有抽象方法,那么它一定是抽象类
抽象类中的方法实现交给子类来完成

抽象方法格式

权限修饰符 abstract 返回值类型 方法名(参数列表);

特点

1) abstract 可以修饰方法或者类
2) 被abstarct修饰的类叫做抽象类,被abstract修饰的方法叫做抽象方法
3) 抽象类中可以没有抽象方法
4) 如果类中有抽象方法,那么该类必须定义为一个抽象类
5) 子类继承了抽象类以后,要么还是一个抽象类,要么就把所有抽象方法都重写
6) 多用于多态中
7) 抽象类不可以被实例化

练习2:抽象类入门案例

  1. /**本类用于测试抽象类入门案例*/
  2. public class Test2_AbstarctDemo {
  3. public static void main(String[] args) {
  4. //创建多态对象进行测试
  5. Animal2 a = new Dog2();
  6. a.eat();//调用抽象父类的普通方法
  7. a.sleep();//调用抽象父类的抽象方法,具体实现看子类
  8. /**5.抽象类可以被实例化/创建对象吗?---不可以!!!*/
  9. //Animal2 a2 = new Animal2();//Cannot instantiate the type Animal2
  10. }
  11. }
  12. //1.创建父类
  13. /**2.如果一个类中包含抽象方法,那么这个类必须声明成一个抽象类*/
  14. abstract class Animal2{
  15. //3.创建普通方法--抽象类中可以有普通方法
  16. public void eat() {
  17. System.out.println("吃啥都行");
  18. }
  19. public void play() {
  20. System.out.println("玩啥都行");
  21. }
  22. //4.创建抽象方法
  23. /**1.没有方法体的方法叫做抽象方法,被abstract关键字修饰*/
  24. abstract public void sleep();
  25. abstract public void sleep2();
  26. }
  27. //2.创建子类
  28. /**3.1当子类继承了抽象父类后,要么变成一个抽象子类,要么实现父类的所有抽象方法*/
  29. //3.2--abstract class Dog2 extends Animal2{}
  30. class Dog2 extends Animal2{
  31. /**4.1子类继承了抽象父类以后,可以选择重写父类的所有抽象方法*/
  32. /**4.2如果没有重写父类的所有抽象方法,子类仍然需要是一个抽象类*/
  33. @Override //给方法做标记,表示这是一个重写的方法
  34. public void sleep() {
  35. System.out.println("重写父类的抽象方法sleep()");
  36. }
  37. @Override //给方法做标记,表示这是一个重写的方法
  38. public void sleep2() {
  39. System.out.println("重写父类的抽象方法sleep2()");
  40. }
  41. }

练习3:抽象类构造函数测试
抽象类中的构造函数通常在子类对象实例化时使用

  1. /**本类用于测试抽象类的构造函数的用法*/
  2. /**
  3. * 总结:
  4. * 1.抽象类中可以有构造方法
  5. * 2.父类的构造方法要优先于子类执行
  6. * 3.抽象类中构造方法存在的目的,不是为了创建抽象类本身的对象,而是为了创建子类对象时使用
  7. * */
  8. public class Test3_Abstarct2 {
  9. public static void main(String[] args) {
  10. //4.创建多态对象进行测试
  11. Animal3 a = new Dog3();
  12. //5.测试抽象类是否可以创建对象?--不能!!
  13. //Animal3 a2 = new Animal3();
  14. }
  15. }
  16. //1.创建抽象父类
  17. abstract class Animal3{
  18. //3.创建抽象类的构造函数
  19. public Animal3() {//如果此处传参,会覆盖无参构造,子类super就报错了
  20. System.out.println("Animal3...构造方法");
  21. }
  22. }
  23. //2.创建子类
  24. class Dog3 extends Animal3{
  25. //6.创建子类无参构造,无参构造默认存在
  26. public Dog3() {
  27. super();//隐藏着super();//先访问父类的构造方法,再执行自己的功能
  28. System.out.println("Dog3...构造方法");
  29. }
  30. }
  31. 3.6 练习4:抽象类成员测试
  32. 抽象类中的构造函数通常在子类对象实例化时使用
  33. 创建Java工程: DAY09
  34. 创建包: cn.tedu.oop
  35. 创建类: Test4_Abstarct3.java
  36. package cn.tedu.oop;
  37. /**本类用于测试抽象类中的成员*/
  38. public class Test4_Abstarct3 {
  39. public static void main(String[] args) {
  40. //7.创建多态对象进行测试
  41. Fruit f = new Apple();
  42. System.out.println(f.sum);//10
  43. //f.name = "lemon";//常量的值不能被修改The final field Fruit.name cannot be assigned
  44. System.out.println(f.name);
  45. f.clean();
  46. f.eat();//吃啥水果都行
  47. f.eat2();//Apple.eat2...吃啥水果都行
  48. }
  49. }
  50. //1.创建抽象父类--水果类
  51. abstract class Fruit{
  52. /**1.抽象类中可以有成员变量吗?--可以!!!*/
  53. //3.1创建抽象父类成员变量
  54. int sum = 10;
  55. /**2.抽象类中可以有成员常量吗?--可以有,但是值无法修改*/
  56. //3.2创建抽象父类成员常量
  57. final String name = "banana";
  58. /**3.抽象类中可以有普通方法吗?--可以!!
  59. * 抽象类中可以都是普通方法吗?--可以* */
  60. /**4.如果一个类中都是普通方法,这个类为什么还要被声明成抽象类呢?
  61. * 原因:抽象类不可以创建对象,如果不想让外界创建本类的对象,可以把普通类声明成一个抽象类* */
  62. //4.创建抽象父类普通方法
  63. public void eat() {
  64. System.out.println("吃啥水果都行");
  65. }
  66. public void eat2() {
  67. System.out.println("eat2...吃啥水果都行");
  68. }
  69. //5.创建抽象父类抽象方法
  70. /**5.抽象类中可以有抽象方法,一旦类中有抽象方法,这个类就必须被声明成抽象类*/
  71. abstract public void clean();
  72. }
  73. /**6.当一个类继承了父类,父类是一个抽象类时
  74. * 子类需要重写抽象父类中的所有抽象方法,如果不重写,就需要把自己变成一个抽象子类
  75. */
  76. //解决方案一:把自己变成一个抽象子类
  77. //abstract class Apple extends Fruit{
  78. //解决方案二:重写抽象父类的所有抽象方法
  79. //2.创建子类--苹果类
  80. class Apple extends Fruit{
  81. public void eat2() {
  82. System.out.println("Apple.eat2...吃啥水果都行");
  83. }
  84. //6.重写父类的抽象方法clean()
  85. @Override //重写标记,表示子类重写/实现了父类的抽象方法clean
  86. public void clean() {
  87. System.out.println("苹果还是需要好好洗洗再吃的");
  88. }
  89. }

拓展

程序设计:分析老师示例—面向抽象编程
具体事物: 培优班老师 高手班老师
共性: 讲课 备课

  1. /**本类用于设计老师类,面向抽象编程*/
  2. public class Test5_Design {
  3. public static void main(String[] args) {
  4. Teacher ct = new CGBTeacher();
  5. Teacher at = new ACTTeacher();
  6. ct.ready();
  7. ct.teach();
  8. at.ready();
  9. at.teach();
  10. }
  11. }
  12. //生活中的事物 -- 类
  13. //特征 -- 属性 & 行为 -- 方法
  14. //把所有的共性内容向上提取形成父类
  15. /**2.类中含有抽象方法,这个类必须变成抽象类*/
  16. abstract class Teacher{
  17. //备课方法
  18. public void ready() {
  19. System.out.println("正在备课");
  20. }
  21. //讲课方法
  22. /**1.没有方法体的方法叫做抽象方法,用abstract修饰*/
  23. abstract public void teach();
  24. }
  25. //培优班老师--主打电商项目
  26. class CGBTeacher extends Teacher{
  27. @Override
  28. public void teach() {
  29. System.out.println("正在讲课...电商项目");
  30. }
  31. }
  32. //高手班老师--基础加强+框架加强+高新技术
  33. class ACTTeacher extends Teacher{
  34. @Override
  35. public void teach() {
  36. System.out.println("正在讲课...基础加强+框架加强+高新技术");
  37. }
  38. }

DAY10

接口

概念
Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现,Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现
OOP面向对象编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口编程,面向抽象的变成,正确的使用接口/抽象类这些抽象类型作为java结构层次上的顶层.

接口格式
interface 接口名{ 代码… }

接口特点:
1) 接口中都是抽象方法
2) 通过interface关键字来定义接口
3) 通过implements让子类来实现接口
4) 可以理解成,接口是一个特殊的抽象类(接口里的方法都是抽象方法)
5) 接口突破了java单继承的局限性
6) 接口和类之间可以多实现,接口与接口之间可以多继承
7) 接口是对外暴露的规则,是一套开发规范
8) 接口提高了程序的功能拓展,降低了耦合性

练习1-1:创建接口

  1. /**本接口是创建接口测试*/
  2. /**1.通过interface关键字来定义接口*/
  3. public interface Inter {
  4. /**2.接口中可以有普通方法吗?--不可以!!*/
  5. //public void eat() {}
  6. /**3.接口中可以有抽象方法吗?--可以,接口中的方法都是抽象方法!!!*/
  7. public abstract void eat();
  8. public abstract void play();
  9. }

练习1-2:创建接口实现类

  1. /**本类作为Inter接口的实现类*/
  2. /**1.实现类如果想用接口的功能,要和接口建立实现关系,通过关键字implements来实现*/
  3. /**2.1 方案一:如果实现类与接口建立关系以后,可以选择不实现接口中的抽象方法,而是把自己变成一个抽象子类*/
  4. //abstract public class InterImpl implements Inter{
  5. /**2.2 方案二:如果实现类实现了接口以后,可以重写接口中的所有抽象方法*/
  6. public class InterImpl implements Inter{
  7. @Override //作为标记,表示实现了父接口的抽象方法
  8. public void eat() {
  9. System.out.println("吃火锅");
  10. }
  11. @Override//作为标记,表示实现了父接口的抽象方法
  12. public void play() {
  13. System.out.println("玩代码");
  14. }
  15. }

练习1-3:创建接口测试类

  1. /**本类用于测试接口的实现类*/
  2. public class InterTests {
  3. //6.创建入口函数main()
  4. public static void main(String[] args) {
  5. //7.测试接口创建对象
  6. /**接口可以创建对象吗?--不可以!!!*/
  7. //Inter i = new Inter();
  8. //8.创建多态对象进行测试
  9. Inter i = new InterImpl();
  10. //9.通过对象调用方法测试
  11. i.eat();
  12. i.play();
  13. //10.创建子类对象并进行测试
  14. InterImpl i2 = new InterImpl();
  15. i2.eat();
  16. i2.play();
  17. }
  18. }

接口的用法

练习2-1: 接口之构造方法

  1. /**本类用于进一步测试接口的使用*/
  2. public class Test2_UserInter {
  3. //5.创建入口函数main()
  4. public static void main(String[] args) {
  5. //6.创建多态对象进行测试
  6. /**问题:子类创建对象时,默认会调用父类的构造方法
  7. * 目前接口实现类的父级是一个接口,而接口没有构造方法
  8. * 那实现类构造方法中的super()调用的是谁呢?
  9. * 结论:如果一个类没有明确指定父类,那么默认继承顶级父类Object
  10. * 所以super()会自动调用Object类中的无参构造
  11. * */
  12. /**查看类的继承结构:Ctrl+T*/
  13. Inter2 i = new Inter2Impl();
  14. }
  15. }
  16. //1.创建接口
  17. interface Inter2{
  18. /**1.接口中有构造方法吗?--不可以!!!*/
  19. //2.测试接口是否可以有构造方法
  20. // public Inter2() {}
  21. }
  22. //3.创建接口的实现类
  23. //class Inter2Impl extends Object implements Inter2{
  24. class Inter2Impl implements Inter2{
  25. //4.创建实现类的构造函数
  26. public Inter2Impl() {
  27. super();
  28. System.out.println("我是Inter2Impl的无参构造");
  29. }
  30. }
  31. 总结:接口里是没有构造方法的。
  32. 在创建实现类的对象时默认的super(),是调用的默认Object的无参构造。

练习2-2: 接口之成员变量

  1. /**本类用于进一步测试接口的使用*/
  2. public class Test2_UserInter {
  3. //5.创建入口函数main()
  4. public static void main(String[] args) {
  5. //6.创建多态对象进行测试
  6. /**问题:子类创建对象时,默认会调用父类的构造方法
  7. * 目前接口实现类的父级是一个接口,而接口没有构造方法
  8. * 那实现类构造方法中的super()调用的是谁呢?
  9. * 结论1:如果一个类没有明确指定父类,那么默认继承顶级父类Object
  10. * 所以super()会自动调用Object类中的无参构造
  11. * */
  12. /**查看类的继承结构:Ctrl+T*/
  13. Inter2 i = new Inter2Impl();
  14. /**结论2:接口中的变量实际上都是静态常量,可以通过类名直接调用*/
  15. System.out.println(Inter2.age);
  16. /**结论3:接口中的变量实际上都是静态常量,值不可以被修改*/
  17. //Inter2.age = 200;
  18. }
  19. }
  20. //1.创建接口
  21. interface Inter2{
  22. /**1.接口中有构造方法吗?--不可以!!!*/
  23. //2.测试接口是否可以有构造方法
  24. // public Inter2() {}
  25. /**2.接口里可以有成员变量吗?--没有!!!
  26. * 是一个静态常量,实际上的写法是public static final int age = 10;
  27. * 只不过在接口中可以省略不写
  28. * */
  29. int age = 10;
  30. }
  31. //3.创建接口的实现类
  32. //class Inter2Impl extends Object implements Inter2{
  33. class Inter2Impl implements Inter2{
  34. //4.创建实现类的构造函数
  35. public Inter2Impl() {
  36. super();
  37. System.out.println("我是Inter2Impl的无参构造");
  38. }
  39. }
  40. 总结:接口里没有成员变量,都是常量。所以,你定义一个变量没有写修饰符时,默认会加上:public static final

练习2-3: 接口之成员方法

  1. /**本类用于进一步测试接口的使用*/
  2. public class Test2_UserInter {
  3. public static void main(String[] args) {
  4. //3.在main()中创建多态对象进行测试
  5. /**问题:子类创建对象时,会自动调用父类的构造方法,但是现在的父级是个接口
  6. * 接口里没有构造方法,那子类中super()调用的是什么呢?
  7. * 结论1:子类默认继承了顶级父类Obejct,super()会自动调用Object的无参构造
  8. */
  9. Inter2 in = new Inter2Impl();
  10. /**结论2.1:接口中的变量实际上都是静态常量,可以通过类名直接调用*/
  11. System.out.println(Inter2.age);
  12. /**结论2.2:接口中的变量实际上都是静态常量,不能被重新赋值*/
  13. //Inter2.age = 20;
  14. }
  15. }
  16. //1.创建接口
  17. interface Inter2{
  18. /**1.接口里有构造方法吗?--没有!!!,连普通方法都没有*/
  19. //public Inter2() {}
  20. /**2.接口里可以有成员变量吗?--没有!!!*/
  21. int age = 10;//静态常量,实际上:final static int age = 10;
  22. /**3.接口中可以有抽象方法吗?--可以!!!*/
  23. abstract public void eat2();
  24. void eat();//可以简写--会自动拼接public abstarct
  25. }
  26. //2.创建接口的实现类
  27. class Inter2Impl implements Inter2 {
  28. public Inter2Impl() {
  29. super();//默认先调用顶级父类Object的无参构造方法
  30. System.out.println("我是Inter2Impl的无参构造");
  31. }
  32. /**4.如果接口中添加了抽象方法,实现类中需要实现所有未实现的抽象方法*/
  33. @Override
  34. public void eat2() {
  35. }
  36. @Override
  37. public void eat() {
  38. }
  39. }
  40. 总结:接口里的方法,默认就都是抽象的,如果你不写明是abstract的,那会自动补齐。
  41. 例如:public abstract void save

练习3:分析老师示例—面向接口编程

具体事物: 培优班老师 高手班老师
共性: 讲课 备课

  1. /**本类用于改造老师设计案例,采用面向接口编程*/
  2. public class Test3_DesignInter {
  3. public static void main(String[] args) {
  4. CGBTeacher2 ct = new CGBTeacher2();
  5. ct.ready();
  6. ct.teach();
  7. }
  8. }
  9. //1.创建接口Teacher2--抽取共性,形成抽象层-体现接口-定义的是规则
  10. /**1.通过interface关键字定义接口*/
  11. interface Teacher2{
  12. /**2.接口中的方法都是抽象方法,可以简写public abstract*/
  13. //2.定义接口中的抽象方法
  14. //2.1备课方法
  15. void ready();
  16. //2.2上课方法
  17. void teach();
  18. }
  19. /**3.如果实现类想要使用接口的功能,就需要与接口建立实现关系*/
  20. //3.创建接口的实现类并添加所有未实现的方法
  21. class CGBTeacher2 implements Teacher2{
  22. @Override
  23. public void ready() {
  24. System.out.println("正在备课...电商项目");
  25. }
  26. @Override
  27. public void teach() {
  28. System.out.println("正在上课...电商项目");
  29. }
  30. }
  31. //4.创建接口的抽象子类
  32. abstract class SCDTeacher2 implements Teacher2{}
  33. //5.创建接口的抽象子类2
  34. abstract class ACTTeacher2 implements Teacher2{
  35. @Override
  36. public void ready() {
  37. System.out.println("正在备课...基础加强..框架加强..高新技术");
  38. }
  39. public abstract void teach() ;
  40. }

接口的多继承多实现

练习4: 测试接口与类之间的复杂关系

  1. public class Test4 {
  2. //5.创建入口函数
  3. public static void main(String[] args) {
  4. //6.创建实现类对象进行测试
  5. Inter3Impl i3 = new Inter3Impl();
  6. i3.update();
  7. //7.创建多态对象进行测试
  8. Inter3 i4 = new Inter3Impl();
  9. i4.find();
  10. }
  11. }
  12. //1.创建接口1
  13. interface Inter1{
  14. void save();//保存功能
  15. void delete();//删除功能
  16. }
  17. //2.创建接口2
  18. interface Inter2{
  19. void update();//更新功能
  20. void find();//查询功能
  21. }
  22. //3.创建接口3用来测试接口与接口的继承关系
  23. /**1.接口之间可以建立继承关系,而且还可以多继承
  24. * 接口与接口之间用逗号隔开
  25. * */
  26. interface Inter3 extends Inter1,Inter2{
  27. }
  28. //4.创建Inter3接口的实现类并添加未实现的方法
  29. /**2.接口和实现类之间可以建立实现关系,通过implments关键字来完成
  30. * 注意,java类是单继承,而接口不限,写接口时,我们一般先继承再实现
  31. * */
  32. class Inter3Impl implements Inter3{
  33. @Override
  34. public void save() {
  35. System.out.println("稍等...正在保存中...");
  36. }
  37. @Override
  38. public void delete() {
  39. System.out.println("稍等...正在删除中....");
  40. }
  41. @Override
  42. public void update() {
  43. System.out.println("客官,马上就更新好啦~~");
  44. }
  45. @Override
  46. public void find() {
  47. System.out.println("小二正在马不停蹄的查询~~~");
  48. }
  49. }

总结

1.类与类的关系
—继承关系,只支持单继承
—比如,A是子类 B是父类,A具备B所有的功能(除了父类的私有资源和构造方法)
—子类如果要修改原有功能,需要重写(方法签名与父类一致 + 权限修饰符>=父类修饰符)

2.类和接口的关系
—实现关系.可以单实现,也可以多实现
—class A implements B,C{}
—其中A是实现类,B和C是接口,A拥有BC接口的所有功能,只是需要进行方法的重写,否则A就是抽象类

3.接口与接口的关系
—是继承关系,可以单继承,也可以多继承
—interface A extends B,C{}
—其中ABC都是接口,A是子接口,具有BC接口的所有功能(抽象方法)
—class X implements A{}
—X实现类需要重写ABC接口的所有方法,否则就是抽象类
—class A extends B implements C,D{}
—其中A是实现类,也是B的子类,同时拥有CD接口的所有功能
—这时A需要重写CD接口里的所有抽象方法
4.抽象类与接口的区别
—抽象类是一个特殊的类,特殊在,抽象类中可以包含没有方法体的方法(抽象方法)
—接口可以理解成一个特殊的抽象类,特殊在,接口里的都是抽象方法,没有普通方法
—接口会为方法自动拼接public abstract,还会为变量自动拼接public final static
—抽象类可以有构造方法—用来给子类创建对象,接口中没有构造方法
—抽象类和接口都不能实例化(创建对象)
—抽象类可以有普通方法,接口都是抽象方法

拓展

引用

image001.jpg

OOP综合练习

练习-1:士兵类

  1. import java.util.Random;
  2. /**本类用于封装士兵相关的属性数据和逻辑运算方法
  3. * 封装成一个士兵"类"组件
  4. * */
  5. public class Soldier {
  6. //定义成员变量--属性
  7. int id;//成员变量可以不初始化,int的默认值是0
  8. int blood = 100;//血量
  9. AK47 a;//默认值是null
  10. //定义成员方法
  11. public void go() {
  12. //this是一个特殊的引用,引用的就是"当前对象"的地址,谁引用,就是谁,可以省略
  13. System.out.println(this.id+"士兵在前进");
  14. }
  15. public void attack() {
  16. if(blood == 0 ) {
  17. System.out.println("这是"+id+"号士兵的尸体!");
  18. return;//方法结束
  19. }
  20. System.out.println(id+"士兵在攻击");
  21. //模拟进攻掉血
  22. int d = new Random().nextInt(10);
  23. blood = blood - d;//可以简写blood -= d;
  24. if(blood < 0) {//不允许出现负数血量
  25. blood = 0;
  26. }
  27. System.out.println("当前血量:"+blood);
  28. if(blood==0) {
  29. System.out.println(id+"号士兵阵亡!");
  30. }
  31. }
  32. }

练习-2:士兵类测试类

  1. /**本类用于进行士兵类的测试*/
  2. public class Test1 {
  3. public static void main(String[] args) {
  4. //创建士兵类对象
  5. Soldier s1 = new Soldier();//s1引用的是第一个士兵对象
  6. Soldier s2 = new Soldier();//s1引用的是第二个士兵对象
  7. //为id属性赋值
  8. s1.id=9588;
  9. s2.id=9589;
  10. //通过s1 s2引用变量找到第一个士兵对象,让士兵对象执行go()
  11. s1.go();
  12. s2.go();
  13. // //通过s1 s2引用变量找到第一个士兵对象,让士兵对象执行attack()
  14. // s1.attack();
  15. // s2.attack();
  16. // s2.attack();
  17. //新建AK47对象,保存到s1.a
  18. s1.a=new AK47();
  19. s2.a=new AK47();
  20. s2.attack();
  21. s2.attack();
  22. s2.attack();
  23. s2.attack();
  24. }
  25. }

练习-3:AK47类

  1. import java.util.Random;
  2. /**本类用于AK47的封装*/
  3. public class AK47 {
  4. int bullets = 100;
  5. public void fire() {
  6. if(bullets == 0) {
  7. System.out.println("没有子弹!");
  8. return;
  9. }
  10. //随机产生发射子弹的数量
  11. int r = new Random().nextInt(10);
  12. //要发射的数量,比现有的子弹多
  13. if(r>bullets) {
  14. r=bullets;//剩多少发多少
  15. }
  16. bullets -= r;
  17. for (int i = 0; i < r; i++) {
  18. System.out.print("突");
  19. }
  20. System.out.println("~");
  21. if(bullets == 0) {
  22. System.out.println("弹夹空了!");
  23. }
  24. }
  25. public void load() {
  26. bullets = 100;
  27. System.out.println("弹夹已装满");
  28. }
  29. }

练习-4:循环射击测试类

  1. import java.util.Scanner;
  2. /**本类用于循环测试射击类*/
  3. public class Test2 {
  4. public static void main(String[] args) {
  5. AK47 a = new AK47();
  6. System.out.println("按回车射击,输入load装载子弹");
  7. while(true) {
  8. String s = new Scanner(System.in).nextLine();
  9. if(s.equals("load")) {
  10. a.load();
  11. }
  12. a.fire();
  13. }
  14. }
  15. }

abstract注意事项
抽象方法要求子类继承后必须重写。
那么,abstract关键字不可以和哪些关键字一起使用呢?以下关键字,在抽象类中。用是可以用的,只是没有意义了。
1) private:被私有化后,子类无法重写,与abstract相违背。
2) static:静态优先于对象存在。而abstract是对象间的关系,存在加载顺序问题。
3) final:被final修饰后,无法重写,与abstract相违背。

接口和抽象类的区别
1) 抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2) 抽象类要被子类继承,接口要被子类实现。
3) 接口只能做方法声明,抽象类中可以做方法声明,也可以做方法实现
4) 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5) 抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
6) 抽象方法只能声明,不能实现,接口是设计的结果 ,抽象类是重构的结果
7) 抽象类里可以没有抽象方法
8) 如果一个类里有抽象方法,那么这个类只能是抽象类
9) 抽象方法要被实现,所以不能是静态的,也不能是私有的。
10) 接口可继承接口,并可多继承接口,但类只能单继承。

了解软件设计的开闭原则OCP
开放功能扩展,关闭源码修改。等
开闭原则的英文全称是Open Close Principle,缩写是OCP,它是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的、灵活的系统。
开闭原则的定义是:软件中的对象(类、模块、函数等)应该对于扩展是开放的,但是对于修改是封闭的。
开闭原则,是一种设计模式,随着面向对象程序设计的思想,应运而生。
开,指的是可以在源代码的基础上进行扩展,比如继承,接口,抽象类等。在JAVA中,之所以用继承,是在可以直接调用类库的前提下,对其功能进行扩展。不需要应用者去了解封装类的内部逻辑就可以做开发。
闭:指不允许对原有的代码进行修改。以免影响其他现有功能,造成功能瘫痪。