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的区别
- 重载: 是指在一个类中的现象,是指一个类中有很多同名的方法,但是方法的参数列表不同
- 重写: 是指发生了继承关系以后(两个类),子类去修改父类原有的功能,子类中有一个方法签名(返回值类型 方法名(参数列表) )和父类的一模一样
- 重载的意义: 是为了方便外界对方法进行调用,什么样的参数程序都可以找到对应的方法来执行,体现的是程序的灵活性
重写的意义:是在不修改源码的前提下,进行功能的修改和拓展
(OCP原则:面向修改关闭,面向拓展开放)
-
DAY08
static关键字
概念:
是java中的一个关键字
用于修饰成员(成员变量和成员方法)
静态代码块格式
static {}
静态资源随着类的加载而加载,并且只被加载一次,一般用于项目的初始化
特点: 被static修饰,位置在类里方法外
特点
1) 可以修饰成员变量与成员方法
2) 随着类的加载而加载,优先于对象加载
3) 只加载一次,就会一直存在,不再开辟新空间, 直到类消失才一起消失
4) 静态资源也叫做类资源,全局唯一,被全局所有对象共享
5) 可以直接被类名调用
6) 静态只能调用静态,非静态可以随意调用
7) static不能和this或者super共用,因为有static时可能还没有对象
静态代码块、构造代码块和局部代码块:
//总结:
//1,代码块间的执行顺序:静态代码块,构造代码块,局部代码块
//2,为什么是这样的顺序呢?
//原因:静态代码块优先于对象加载,是随着类的加载而加载到内存中的,只加载一次,并且一直存在,直到类消失,它才会消失。专门用来完成一些需要第一时间加载并且只需要加载一次
//构造代码块是在创建对象时才会触发,专门用来提取构造方法的共性
//局部代码块是方法调用时才会触发,专门用来控制变量的作用范围
多态
概念:
多态指同一个实体同时具有多种形式。
它是面向对象程序设计(OOP)的一个重要特征。
主要是指同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
好处是:可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。
水果有两种形态:水果和苹果,不关心买回来的是苹果还是西瓜,只要是水果就行
特点
1) 多态的前提1:是继承
2) 多态的前提2:要有方法的重写
3) 父类引用指向子类对象,如:Animal a = new Cat();
4) 多态中,编译看左边,运行看右边
多态入门案例
/**本类用于测试多态*/public class Test5 {public static void main(String[] args) {//5.创建父类对象进行测试\Animal a = new Animal();a.eat();//小动物Animal吃啥都行~~~//a.jump();//父类无法使用子类的特有方法//6.创建子类对象进行测试Cat c = new Cat();c.eat();//小猫Cat爱吃小鱼干!!!--调用的是重写以后的功能c.jump();//8.创建多态对象进行测试/**口诀1:父类引用 指向子类对象*//**口诀2:编译(保存)看左边,运行(测试)看右边*/Animal a2 = new Cat();Animal a3 = new Dog();a2.eat();//eat()使用的是父类的声明,但使用的是子类的实现方式a3.eat();/**多态的出现是为了统一调用标准,向父类看齐* 父类提供的功能才能用,子类特有的功能用不了*/}}//1.创建父类class Animal{//3.创建父类中的普通方法eat()public void eat() {System.out.println("小动物Animal吃啥都行~~~");}}//2.创建子类class Cat extends Animal{//4.重写父类中的方法--对父类中的代码功能修改//重写:方法签名保持一致(返回值类型 方法名(参数列表) )// & 权限修饰符 >= 父类权限修饰符public void eat() {System.out.println("小猫Cat爱吃小鱼干!!!");}//7.定义了子类特有的方法public void jump() {System.out.println("小猫Cat跳的老高啦");}}class Dog extends Animal{public void eat() {System.out.println("小狗爱吃肉骨头!!!");}}
多态的好处
1) 多态可以让我们不用关心某个对象到底具体是什么类型,就可以使用该对象的某些方法
2) 提高了程序的可扩展性和可维护性
**
多态的使用**
多态成员变量使用测试
/**本类用于多态中的元素测试*/public class Test6_DuoTai {public static void main(String[] args) {//7.创建子类对象进行测试Dog2 d = new Dog2();System.out.println(d.sum);//20d.eat();//小狗要吃肉骨头d.play();//小狗爱打滚儿~~~//10.创建多态对象进行测试/**口诀1:父类引用指向子类对象*//**口诀2:编译(保存)看左边,运行(测试)看右边*/Animal2 a = new Dog2();/**2.多态中,成员变量使用的都是父类的*/System.out.println(a.sum);//10/**3.多态中,成员方法使用的是父类的声明,子类的实现*/a.eat();/**4.多态中,如果父子类都有静态方法,使用的是父类的*/a.play();//玩啥都行}}//1.创建父类class Animal2{//2.创建成员变量int sum = 10;//3.创建成员方法public void eat() {System.out.println("吃啥都行");}//8.父类中定义静态方法play()public static void play() {System.out.println("玩啥都行");}}/**1.多态的前提:继承+重写*///4.定义子类Dog2class Dog2 extends Animal2{//5.定义子类的成员变量int sum = 20;//6.重写父类的eat()/**@Override 这个注解加在方法上,表示这是一个重写的方法*/@Override //注解--标签public void eat() {System.out.println("小狗要吃肉骨头");}//9.定义子类的静态方法play()//@Override --不是重写,不能加这个注解public static void play() {System.out.println("小狗爱打滚儿~~~");}}
/*注意!!!静态资源属于类,不存在重写现象,只是两个类中有同样声明的方法而已,不属于重写/
拓展
设计汽车综合案例
/**本类用于完成OOP汽车设计综合案例*//*** 1.分析事物,得出它的属性和功能* 2.提取类中的共同点,向上抽取,形成父类Car* 3.子类继承父类后,就拥有的父类的功能* 4.如果对父类的功能不满意,可以重写* 5.可以封装某些类的属性,如果封装了,就要提供对应的get()/set()*/public class Test7_ExtendsDesignCar {//3.创建入口函数mainpublic static void main(String[] args) {//4.创建父类对象进行测试Car c = new Car();System.out.println(c.getColor());//通过get方法查看封装后的color值c.start();c.stop();//5.创建宝马类对象进行测试BMW b = new BMW();System.out.println(b.color);System.out.println("*********");b.start();b.stop();//6.创建保时捷类对象进行测试BSJ j = new BSJ();System.out.println(j.color);j.start();j.stop();}}//0.创建一个汽车类class Car{//0.1定义Car类的属性//0.3通过private对Car类的属性进行封装private String brand;//品牌private String color;//颜色//0.4属性封装后,对外提供公共的get()与set()便于外界对属性进行操作//右键-->Source-->Generate Getters and Setters -->Select All -->Generatepublic String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}//0.2定义Car类的启动与停止方法public void start() {System.out.println("我的车车启动啦~~~");}public void stop() {System.out.println("哎呀吗,我的车车熄火了~");}}//1.创建一个宝马类并且继承Car类class BMW extends Car{String color = "五彩斑斓的黑";@Overridepublic void start() {super.start();System.out.println("宝马启动加速度~~~UPUP");}}//2.创建一个保时捷并且继承Car类class BSJ extends Car{String color = "黑不溜秋的白";@Overridepublic void stop() {System.out.println("保时捷想停的稳当些~");}}
静态变量和实例变量的区别:
在语法定义上的区别:静态变量前要加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:异常测试
import java.util.InputMismatchException;import java.util.Scanner;/**本类用于测试异常入门案例*//**总结8:如果方法抛出异常,那么谁调用谁需要解决(继续抛出/捕获解决)* 所以main()调用了method3(),也需要抛出异常* 注意,我们一般在main()调用之前捕获解决异常,而不是抛给main(),因为没人解决了* */public class Test1_ExceptionDemo {public static void main(String[] args) throws Exception{//1.创建method(),用来人为的暴露异常//method();//2.创建method2(),用来进行异常的捕获//method2();//3.创建method3(),用来进行异常的抛出method3();}/*** 抛出的语法:* 在可能会抛出异常的方法上加throws 异常类型* 在抛出时,也可以使用多态,不管会发生什么异常,通通被Exception跑出去*///public static void method3() throws ArithmeticException,InputMismatchException,Exception{public static void method3() throws Exception{//1.复写刚刚可能会发生异常的代码System.out.println("请输入两个整数:");int a = new Scanner(System.in).nextInt();int b = new Scanner(System.in).nextInt();System.out.println( a/b );}/*** 捕获的语法:* try{* 可能会发生异常的代码* }catch(异常类型 异常参数名){* 如果捕获到异常的解决方案* }*/public static void method2() {//1.按照捕获语法编写try-catch结构/**总结4:try{}里放的是可能会发生异常的代码*/try {//2.复写刚刚可能会发生异常的代码System.out.println("请输入两个整数:");int a = new Scanner(System.in).nextInt();int b = new Scanner(System.in).nextInt();System.out.println( a/b );/**总结5:如果发生异常被捕获,就被匹配对应的解决方案*/} catch (ArithmeticException e) {//3.1异常捕获1System.out.println("除数不能为0!");//3.2异常处理1/**总结6:由于程序中可能存在多种异常,所以catch可以配合多次使用*/}catch (InputMismatchException e) {//4.1异常捕获2System.out.println("输入的类型不正确,请输入正确的整数类型!");//4.2异常处理2/**总结7:如果还有上述两种异常之外的异常,用Exception匹配捕获* 这个就是多态最为经典的一种用法,我们不关心子类的类型* 只要是可解决异常,都是Exception的子类,多态会把这些异常当做父类来看,捕获,通过通用方案进行解决* */}catch (Exception e) {System.out.println("请输入正确的整数!");}}public static void method() {//1.提示并接收用户输入的两个整数:System.out.println("请输入两个整数:");int a = new Scanner(System.in).nextInt();int b = new Scanner(System.in).nextInt();//2.输出除法运算的结果//2.1输入9.9 --java.util.InputMismatchException[输入不匹配异常]//2.2输入9/0 --java.lang.ArithmeticException: / by zero[算术异常,除0了]System.out.println( a/b );/**总结1:不要害怕BUG,真正的勇士敢于直面自己写的BUG*//**总结2:学会看报错信息的错误提示,确定自己错误的方向*//**总结3:学会看报错信息的行号提示,哪里报错点哪里,注意,源码不会错,看自己写的代码*/}}
抽象类
抽象类简述
Java中可以定义被abstract关键字修饰的方法,这种方法只有声明,没有方法体,叫做抽象方法.
Java中可以定义被abstract关键字修饰的类,被abstract关键字修饰的类叫做抽象类
如果一个类含有抽象方法,那么它一定是抽象类
抽象类中的方法实现交给子类来完成
抽象方法格式
权限修饰符 abstract 返回值类型 方法名(参数列表);
特点
1) abstract 可以修饰方法或者类
2) 被abstarct修饰的类叫做抽象类,被abstract修饰的方法叫做抽象方法
3) 抽象类中可以没有抽象方法
4) 如果类中有抽象方法,那么该类必须定义为一个抽象类
5) 子类继承了抽象类以后,要么还是一个抽象类,要么就把所有抽象方法都重写
6) 多用于多态中
7) 抽象类不可以被实例化
练习2:抽象类入门案例
/**本类用于测试抽象类入门案例*/public class Test2_AbstarctDemo {public static void main(String[] args) {//创建多态对象进行测试Animal2 a = new Dog2();a.eat();//调用抽象父类的普通方法a.sleep();//调用抽象父类的抽象方法,具体实现看子类/**5.抽象类可以被实例化/创建对象吗?---不可以!!!*///Animal2 a2 = new Animal2();//Cannot instantiate the type Animal2}}//1.创建父类/**2.如果一个类中包含抽象方法,那么这个类必须声明成一个抽象类*/abstract class Animal2{//3.创建普通方法--抽象类中可以有普通方法public void eat() {System.out.println("吃啥都行");}public void play() {System.out.println("玩啥都行");}//4.创建抽象方法/**1.没有方法体的方法叫做抽象方法,被abstract关键字修饰*/abstract public void sleep();abstract public void sleep2();}//2.创建子类/**3.1当子类继承了抽象父类后,要么变成一个抽象子类,要么实现父类的所有抽象方法*///3.2--abstract class Dog2 extends Animal2{}class Dog2 extends Animal2{/**4.1子类继承了抽象父类以后,可以选择重写父类的所有抽象方法*//**4.2如果没有重写父类的所有抽象方法,子类仍然需要是一个抽象类*/@Override //给方法做标记,表示这是一个重写的方法public void sleep() {System.out.println("重写父类的抽象方法sleep()");}@Override //给方法做标记,表示这是一个重写的方法public void sleep2() {System.out.println("重写父类的抽象方法sleep2()");}}
练习3:抽象类构造函数测试
抽象类中的构造函数通常在子类对象实例化时使用
/**本类用于测试抽象类的构造函数的用法*//*** 总结:* 1.抽象类中可以有构造方法* 2.父类的构造方法要优先于子类执行* 3.抽象类中构造方法存在的目的,不是为了创建抽象类本身的对象,而是为了创建子类对象时使用* */public class Test3_Abstarct2 {public static void main(String[] args) {//4.创建多态对象进行测试Animal3 a = new Dog3();//5.测试抽象类是否可以创建对象?--不能!!//Animal3 a2 = new Animal3();}}//1.创建抽象父类abstract class Animal3{//3.创建抽象类的构造函数public Animal3() {//如果此处传参,会覆盖无参构造,子类super就报错了System.out.println("Animal3...构造方法");}}//2.创建子类class Dog3 extends Animal3{//6.创建子类无参构造,无参构造默认存在public Dog3() {super();//隐藏着super();//先访问父类的构造方法,再执行自己的功能System.out.println("Dog3...构造方法");}}3.6 练习4:抽象类成员测试抽象类中的构造函数通常在子类对象实例化时使用创建Java工程: DAY09创建包: cn.tedu.oop创建类: Test4_Abstarct3.javapackage cn.tedu.oop;/**本类用于测试抽象类中的成员*/public class Test4_Abstarct3 {public static void main(String[] args) {//7.创建多态对象进行测试Fruit f = new Apple();System.out.println(f.sum);//10//f.name = "lemon";//常量的值不能被修改The final field Fruit.name cannot be assignedSystem.out.println(f.name);f.clean();f.eat();//吃啥水果都行f.eat2();//Apple.eat2...吃啥水果都行}}//1.创建抽象父类--水果类abstract class Fruit{/**1.抽象类中可以有成员变量吗?--可以!!!*///3.1创建抽象父类成员变量int sum = 10;/**2.抽象类中可以有成员常量吗?--可以有,但是值无法修改*///3.2创建抽象父类成员常量final String name = "banana";/**3.抽象类中可以有普通方法吗?--可以!!* 抽象类中可以都是普通方法吗?--可以* *//**4.如果一个类中都是普通方法,这个类为什么还要被声明成抽象类呢?* 原因:抽象类不可以创建对象,如果不想让外界创建本类的对象,可以把普通类声明成一个抽象类* *///4.创建抽象父类普通方法public void eat() {System.out.println("吃啥水果都行");}public void eat2() {System.out.println("eat2...吃啥水果都行");}//5.创建抽象父类抽象方法/**5.抽象类中可以有抽象方法,一旦类中有抽象方法,这个类就必须被声明成抽象类*/abstract public void clean();}/**6.当一个类继承了父类,父类是一个抽象类时* 子类需要重写抽象父类中的所有抽象方法,如果不重写,就需要把自己变成一个抽象子类*///解决方案一:把自己变成一个抽象子类//abstract class Apple extends Fruit{//解决方案二:重写抽象父类的所有抽象方法//2.创建子类--苹果类class Apple extends Fruit{public void eat2() {System.out.println("Apple.eat2...吃啥水果都行");}//6.重写父类的抽象方法clean()@Override //重写标记,表示子类重写/实现了父类的抽象方法cleanpublic void clean() {System.out.println("苹果还是需要好好洗洗再吃的");}}
拓展
程序设计:分析老师示例—面向抽象编程
具体事物: 培优班老师 高手班老师
共性: 讲课 备课
/**本类用于设计老师类,面向抽象编程*/public class Test5_Design {public static void main(String[] args) {Teacher ct = new CGBTeacher();Teacher at = new ACTTeacher();ct.ready();ct.teach();at.ready();at.teach();}}//生活中的事物 -- 类//特征 -- 属性 & 行为 -- 方法//把所有的共性内容向上提取形成父类/**2.类中含有抽象方法,这个类必须变成抽象类*/abstract class Teacher{//备课方法public void ready() {System.out.println("正在备课");}//讲课方法/**1.没有方法体的方法叫做抽象方法,用abstract修饰*/abstract public void teach();}//培优班老师--主打电商项目class CGBTeacher extends Teacher{@Overridepublic void teach() {System.out.println("正在讲课...电商项目");}}//高手班老师--基础加强+框架加强+高新技术class ACTTeacher extends Teacher{@Overridepublic void teach() {System.out.println("正在讲课...基础加强+框架加强+高新技术");}}
DAY10
接口
概念
Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现,Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现
OOP面向对象编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口编程,面向抽象的变成,正确的使用接口/抽象类这些抽象类型作为java结构层次上的顶层.
接口格式
interface 接口名{ 代码… }
接口特点:
1) 接口中都是抽象方法
2) 通过interface关键字来定义接口
3) 通过implements让子类来实现接口
4) 可以理解成,接口是一个特殊的抽象类(接口里的方法都是抽象方法)
5) 接口突破了java单继承的局限性
6) 接口和类之间可以多实现,接口与接口之间可以多继承
7) 接口是对外暴露的规则,是一套开发规范
8) 接口提高了程序的功能拓展,降低了耦合性
/**本接口是创建接口测试*//**1.通过interface关键字来定义接口*/public interface Inter {/**2.接口中可以有普通方法吗?--不可以!!*///public void eat() {}/**3.接口中可以有抽象方法吗?--可以,接口中的方法都是抽象方法!!!*/public abstract void eat();public abstract void play();}
/**本类作为Inter接口的实现类*//**1.实现类如果想用接口的功能,要和接口建立实现关系,通过关键字implements来实现*//**2.1 方案一:如果实现类与接口建立关系以后,可以选择不实现接口中的抽象方法,而是把自己变成一个抽象子类*///abstract public class InterImpl implements Inter{/**2.2 方案二:如果实现类实现了接口以后,可以重写接口中的所有抽象方法*/public class InterImpl implements Inter{@Override //作为标记,表示实现了父接口的抽象方法public void eat() {System.out.println("吃火锅");}@Override//作为标记,表示实现了父接口的抽象方法public void play() {System.out.println("玩代码");}}
练习1-3:创建接口测试类
/**本类用于测试接口的实现类*/public class InterTests {//6.创建入口函数main()public static void main(String[] args) {//7.测试接口创建对象/**接口可以创建对象吗?--不可以!!!*///Inter i = new Inter();//8.创建多态对象进行测试Inter i = new InterImpl();//9.通过对象调用方法测试i.eat();i.play();//10.创建子类对象并进行测试InterImpl i2 = new InterImpl();i2.eat();i2.play();}}
接口的用法
/**本类用于进一步测试接口的使用*/public class Test2_UserInter {//5.创建入口函数main()public static void main(String[] args) {//6.创建多态对象进行测试/**问题:子类创建对象时,默认会调用父类的构造方法* 目前接口实现类的父级是一个接口,而接口没有构造方法* 那实现类构造方法中的super()调用的是谁呢?* 结论:如果一个类没有明确指定父类,那么默认继承顶级父类Object* 所以super()会自动调用Object类中的无参构造* *//**查看类的继承结构:Ctrl+T*/Inter2 i = new Inter2Impl();}}//1.创建接口interface Inter2{/**1.接口中有构造方法吗?--不可以!!!*///2.测试接口是否可以有构造方法// public Inter2() {}}//3.创建接口的实现类//class Inter2Impl extends Object implements Inter2{class Inter2Impl implements Inter2{//4.创建实现类的构造函数public Inter2Impl() {super();System.out.println("我是Inter2Impl的无参构造");}}总结:接口里是没有构造方法的。在创建实现类的对象时默认的super(),是调用的默认Object的无参构造。
练习2-2: 接口之成员变量
/**本类用于进一步测试接口的使用*/public class Test2_UserInter {//5.创建入口函数main()public static void main(String[] args) {//6.创建多态对象进行测试/**问题:子类创建对象时,默认会调用父类的构造方法* 目前接口实现类的父级是一个接口,而接口没有构造方法* 那实现类构造方法中的super()调用的是谁呢?* 结论1:如果一个类没有明确指定父类,那么默认继承顶级父类Object* 所以super()会自动调用Object类中的无参构造* *//**查看类的继承结构:Ctrl+T*/Inter2 i = new Inter2Impl();/**结论2:接口中的变量实际上都是静态常量,可以通过类名直接调用*/System.out.println(Inter2.age);/**结论3:接口中的变量实际上都是静态常量,值不可以被修改*///Inter2.age = 200;}}//1.创建接口interface Inter2{/**1.接口中有构造方法吗?--不可以!!!*///2.测试接口是否可以有构造方法// public Inter2() {}/**2.接口里可以有成员变量吗?--没有!!!* 是一个静态常量,实际上的写法是public static final int age = 10;* 只不过在接口中可以省略不写* */int age = 10;}//3.创建接口的实现类//class Inter2Impl extends Object implements Inter2{class Inter2Impl implements Inter2{//4.创建实现类的构造函数public Inter2Impl() {super();System.out.println("我是Inter2Impl的无参构造");}}总结:接口里没有成员变量,都是常量。所以,你定义一个变量没有写修饰符时,默认会加上:public static final
练习2-3: 接口之成员方法
/**本类用于进一步测试接口的使用*/public class Test2_UserInter {public static void main(String[] args) {//3.在main()中创建多态对象进行测试/**问题:子类创建对象时,会自动调用父类的构造方法,但是现在的父级是个接口* 接口里没有构造方法,那子类中super()调用的是什么呢?* 结论1:子类默认继承了顶级父类Obejct,super()会自动调用Object的无参构造*/Inter2 in = new Inter2Impl();/**结论2.1:接口中的变量实际上都是静态常量,可以通过类名直接调用*/System.out.println(Inter2.age);/**结论2.2:接口中的变量实际上都是静态常量,不能被重新赋值*///Inter2.age = 20;}}//1.创建接口interface Inter2{/**1.接口里有构造方法吗?--没有!!!,连普通方法都没有*///public Inter2() {}/**2.接口里可以有成员变量吗?--没有!!!*/int age = 10;//静态常量,实际上:final static int age = 10;/**3.接口中可以有抽象方法吗?--可以!!!*/abstract public void eat2();void eat();//可以简写--会自动拼接public abstarct}//2.创建接口的实现类class Inter2Impl implements Inter2 {public Inter2Impl() {super();//默认先调用顶级父类Object的无参构造方法System.out.println("我是Inter2Impl的无参构造");}/**4.如果接口中添加了抽象方法,实现类中需要实现所有未实现的抽象方法*/@Overridepublic void eat2() {}@Overridepublic void eat() {}}总结:接口里的方法,默认就都是抽象的,如果你不写明是abstract的,那会自动补齐。例如:public abstract void save
练习3:分析老师示例—面向接口编程
具体事物: 培优班老师 高手班老师
共性: 讲课 备课
/**本类用于改造老师设计案例,采用面向接口编程*/public class Test3_DesignInter {public static void main(String[] args) {CGBTeacher2 ct = new CGBTeacher2();ct.ready();ct.teach();}}//1.创建接口Teacher2--抽取共性,形成抽象层-体现接口-定义的是规则/**1.通过interface关键字定义接口*/interface Teacher2{/**2.接口中的方法都是抽象方法,可以简写public abstract*///2.定义接口中的抽象方法//2.1备课方法void ready();//2.2上课方法void teach();}/**3.如果实现类想要使用接口的功能,就需要与接口建立实现关系*///3.创建接口的实现类并添加所有未实现的方法class CGBTeacher2 implements Teacher2{@Overridepublic void ready() {System.out.println("正在备课...电商项目");}@Overridepublic void teach() {System.out.println("正在上课...电商项目");}}//4.创建接口的抽象子类abstract class SCDTeacher2 implements Teacher2{}//5.创建接口的抽象子类2abstract class ACTTeacher2 implements Teacher2{@Overridepublic void ready() {System.out.println("正在备课...基础加强..框架加强..高新技术");}public abstract void teach() ;}
接口的多继承多实现
public class Test4 {//5.创建入口函数public static void main(String[] args) {//6.创建实现类对象进行测试Inter3Impl i3 = new Inter3Impl();i3.update();//7.创建多态对象进行测试Inter3 i4 = new Inter3Impl();i4.find();}}//1.创建接口1interface Inter1{void save();//保存功能void delete();//删除功能}//2.创建接口2interface Inter2{void update();//更新功能void find();//查询功能}//3.创建接口3用来测试接口与接口的继承关系/**1.接口之间可以建立继承关系,而且还可以多继承* 接口与接口之间用逗号隔开* */interface Inter3 extends Inter1,Inter2{}//4.创建Inter3接口的实现类并添加未实现的方法/**2.接口和实现类之间可以建立实现关系,通过implments关键字来完成* 注意,java类是单继承,而接口不限,写接口时,我们一般先继承再实现* */class Inter3Impl implements Inter3{@Overridepublic void save() {System.out.println("稍等...正在保存中...");}@Overridepublic void delete() {System.out.println("稍等...正在删除中....");}@Overridepublic void update() {System.out.println("客官,马上就更新好啦~~");}@Overridepublic void find() {System.out.println("小二正在马不停蹄的查询~~~");}}
总结
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
—抽象类可以有构造方法—用来给子类创建对象,接口中没有构造方法
—抽象类和接口都不能实例化(创建对象)
—抽象类可以有普通方法,接口都是抽象方法
拓展
引用

OOP综合练习
练习-1:士兵类
import java.util.Random;/**本类用于封装士兵相关的属性数据和逻辑运算方法* 封装成一个士兵"类"组件* */public class Soldier {//定义成员变量--属性int id;//成员变量可以不初始化,int的默认值是0int blood = 100;//血量AK47 a;//默认值是null//定义成员方法public void go() {//this是一个特殊的引用,引用的就是"当前对象"的地址,谁引用,就是谁,可以省略System.out.println(this.id+"士兵在前进");}public void attack() {if(blood == 0 ) {System.out.println("这是"+id+"号士兵的尸体!");return;//方法结束}System.out.println(id+"士兵在攻击");//模拟进攻掉血int d = new Random().nextInt(10);blood = blood - d;//可以简写blood -= d;if(blood < 0) {//不允许出现负数血量blood = 0;}System.out.println("当前血量:"+blood);if(blood==0) {System.out.println(id+"号士兵阵亡!");}}}
练习-2:士兵类测试类
/**本类用于进行士兵类的测试*/public class Test1 {public static void main(String[] args) {//创建士兵类对象Soldier s1 = new Soldier();//s1引用的是第一个士兵对象Soldier s2 = new Soldier();//s1引用的是第二个士兵对象//为id属性赋值s1.id=9588;s2.id=9589;//通过s1 s2引用变量找到第一个士兵对象,让士兵对象执行go()s1.go();s2.go();// //通过s1 s2引用变量找到第一个士兵对象,让士兵对象执行attack()// s1.attack();// s2.attack();// s2.attack();//新建AK47对象,保存到s1.as1.a=new AK47();s2.a=new AK47();s2.attack();s2.attack();s2.attack();s2.attack();}}
练习-3:AK47类
import java.util.Random;/**本类用于AK47的封装*/public class AK47 {int bullets = 100;public void fire() {if(bullets == 0) {System.out.println("没有子弹!");return;}//随机产生发射子弹的数量int r = new Random().nextInt(10);//要发射的数量,比现有的子弹多if(r>bullets) {r=bullets;//剩多少发多少}bullets -= r;for (int i = 0; i < r; i++) {System.out.print("突");}System.out.println("~");if(bullets == 0) {System.out.println("弹夹空了!");}}public void load() {bullets = 100;System.out.println("弹夹已装满");}}
练习-4:循环射击测试类
import java.util.Scanner;/**本类用于循环测试射击类*/public class Test2 {public static void main(String[] args) {AK47 a = new AK47();System.out.println("按回车射击,输入load装载子弹");while(true) {String s = new Scanner(System.in).nextLine();if(s.equals("load")) {a.load();}a.fire();}}}
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中,之所以用继承,是在可以直接调用类库的前提下,对其功能进行扩展。不需要应用者去了解封装类的内部逻辑就可以做开发。
闭:指不允许对原有的代码进行修改。以免影响其他现有功能,造成功能瘫痪。
