继承:
-
概念:
- 子类继承父类的方法和属性,在里面可以写重复的代码
-
语法格式:
-
Class A 父类 Class B extends A A是父类 B是子类,用来继承A父类
-
-
作用:
- 提高代码的复用性,提高运行效率
-
特点:
- 解决了共性和特性的问题
- 子类不能继承父类的私有的属性和方法,但是可以通过get和set方法间接继承
- 子类继承父类的构造方法
- 单继承,一个子类只有一个父类
- 多重继承(多层):一个子类可以有孙类,曾孙类
- 每一个类都有一个直接父类,如果没有看到显示的继承代码,那么就隐式继承Object
- 在继承当中,构造方法是被子类使用super进行调用
方法覆写(重写/Override):
- 概念:
- 为了满足子类的特性,注意同名同参
- 作用:
- 保证业务逻辑的合理性
- 重写的语法:
- 直接将父类的方法拿来重新写一次进行,同名同参
- 子类的方法的访问权限大于等于父类的访问权限
- 子类方法的返回值类型可以是父类方法的返回值类型的子类或者相等
- static/private修饰的不能被重写
- 注意事项:
- 不是每一个方法都要继承
- 并不是每一个子类都要重写的父类继承过来的方法
- super:
- 意义:
- 在子类的构造方法中,需要去调用父类被覆盖的方法,此时就要用到super关键字
- 他就表示父类对象的意思
- 也可以去调用父类的方法 super().eat
- 意义:
abstract:
-
成员:
- 成员变量
- 基本方法
- 构造方法
- 但是构造方法是被调用,在继承里面,构造方法都是被调用
- 抽象方法:
- 没有方法体
- 用abstract修饰的方法
-
语法:
- 修饰符 abstract 返回值类型 方法名();
-
作用:
- 保证业务的逻辑合理性,强制子类根据自己的需求写自己的逻辑,重写方法
-
使用场景:
-
一般作为业务父类(基类,模板类),且业务父类中,有的方法需要所有子类强制重写。
例如,模板方法模式。
-
Object类(及方法覆写的应用):
-
概念:
-
类
Object
是类层次结构的根类,每个类都使用Object
作为超类。所有对象(包括数组)都可以调用到Object中的方法; -
boolean equals(Object obj) 根据实际业务,判断两个对象成员变量的值是不是“相等”
-
String toString() 返回对象的字符串表示形式。如果需要打印对象的制定格式,则需要重写当前对象所对应类的toString方法即可 。
-
-
toString;
-
引入:
- 直接打印对象的话是地址值,那么通过这个方法我们可以打印出自己自定义的格式
-
怎么用:
- 只要将User类的toString方法重写,只可以打印指定的格式
-
equals:
- 概念:
- 两个对象是否相等
- 为什么会用?
- 因为在引用数据类型当中,我们不能使用==去比较,只有使用equals去比较才行
- 特性:
- 比较引用数据类型 而== 是比较基本数据类型
- 我们在使用的时候,要注意重写equals,才能在里面写自己想要的比较逻辑
equals和==的区别:
-
== :
-
比较基本数据类型: 比较的就是值是否相等。
-
比较引用数据类型: 比较的是对象的地址是否相等。
-
-
equals:
- equals 只能用于引用类型
interface:
-
概念:
- 是一种约定的规范,仅仅只是说明了一些功能,并不能去实现
-
成员:
- 属性:在接口里面属性是全局常量
- 名称大写
- 默认会用public static final修饰 属性的值不会发生变化
- 普通方法:
- 可以有但是必须加上static 或者default修饰
- 构造方法:
- 不能用,以为只是一个模板,不会创建对象
- 抽象方法:一定有
- 接口本来就是用来定义抽象方法的默认会被 public abstract修饰
- 属性:在接口里面属性是全局常量
-
意义:
- 体现了低耦合的思想
- 低耦合:就是说各个模块分开写,一个模块损坏不会影响其他模块运行
- 体现了低耦合的思想
-
格式:
-
public interface 接口名{ 抽象方法1 抽象方法2 抽象方法3 }
-
-
注意:
-
类可以继承类,但是都是单继承,但是接口可以继承多个接口
-
public interface IAmphibiable extends IWalkable,ISwimable{ 格式 }
-
-
接口实现类:implements
-
概念:
- 接口中的方法只是一个模板和方法,并不能实现逻辑,因此我们需要用接口实现类去实现里面的代码的程重写,然后在里面写自己的逻辑
-
格式:
-
public class 类名 implements 接口名 1,接口名 2{ 覆盖接口中抽象方法 }
-
-
接口和接口实现类的说明:
-
接口:
- 只是定义了一些规范,并没有进行逻辑的实现
-
接口实现类:
- 去实现重写接口类中的方法,里面写具体的逻辑代码的实现
-
-
接口中方法和变量的调用:
- default修饰的方法
- 实现类对象名.方法名()
- static修饰的方法
- 接口名.方法名()
- 抽象方法:
- 实现类接口名.方法名()
- 访问全局变量:
- 接口名.变量名
- 这里注意,因为是全局常量,所以他需要用变量去接收或者直接输出,不然会报错
- default修饰的方法
多态(polymorphic):
-
概念:
- 将子类对象装到父类的变量中保存(向上造型/向上转型),当父类变量调用方法的时候,如果子类重写了该方法,会直接执行子类重写之后的方法。(父类变量可以装任意类型的子类对象)
-
语法格式:
- 父类类型 父类变量 = new 子类类型(); 父类变量.方法() 子类若重写,则会执行子类重写后的方法
-
多态的使用:
-
向上转型:
- 正常语法使用,会调用子类重写父类过后的方法
-
向下转型:
-
就是为了调用子类特有方法
-
需要用到强制转换,并且进行对象的比较
-
类型判断的方式:
-
if(父类变量 instanceof 子类类型1){ //强制类型转换 子类类型1 子类变量 = (子类类型1)父类变量; //现在就可以调用子类特有方法 子类变量.子类特有方法(...); }else if(父类变量 instanceof 子类类型2){ //强制类型转换 子类类型2 子类变量 = (子类类型2)父类变量; 子类变量.子类特有方法(...);
-
-
-
-
-
多态的注意事项:
- 子类没有多态
- 不能调用子类特有的方法,如果需要调用子类特有的方法,必须进行强制类型转换(向下造型/向 下转型),向下造型需要进行子类类型判断
- 父类变量能点(调用)出哪些成员(成员变量和方法),是由当前类和其父类决定,优先从当前类 开始查找,直到找到Object了为止,如果Object中有没有,就不能调用
作用;
-
可以屏蔽子类差异性,提高代码的扩展性
-
人类Person有开车方法:drive(Car car) { * 调用车的run方法 * car.run(); * // 类型判断 * car向下造型,然后调用子类车独有方法 * } * 车Car类:有抽象run()方法 * 子类: * 货车Truck的run()方法 跑80km/小时,并且有独有运输货物方法 * 牛车BullCar的run()方法跑10km/小时,并且有独有吃草的方法 * 军车的run()方法跑150km/小时,并且有独有fire方法 * 测试类中: * 人类分别开3种车,并且调用每一个车的特有方法 * 创建一个人类对象,但是创建3个子类车对象,人类的调用开车方法,分别开3类车 * 判断子类类型,用车类自己调用独有方法
-
car类: public abstract class Car { abstract void run(); } TruckCar类: public class TruckCar extends Car { @Override void run() { System.out.println("火车跑80KM/小时"); } public void transport(){ System.out.println("货车独有的运输方式"); } } BullCar类: public class BullCar extends Car{ @Override void run() { System.out.println("牛车速度 10KM/小时"); } public void eatCao(){ System.out.println("牛车吃草独有的方法"); } } Military类: public class Military extends Car{ @Override void run() { System.out.println("军车速度150KM/小时"); } public void fire(){ System.out.println("军车独有的灭火的方法"); } } 测试类: public class Test { public static void main(String[] args) { Person person = new Person(); person.drive(new BullCar()); System.out.println("================="); person.drive(new Military()); System.out.println("================="); person.drive(new TruckCar()); } }
-
多态的总结:
-
多态的三个条件:
- 继承的存在;(继承是多态的基础,没有继承就没有多态)
- 子类重写父类的方法。(多态下会调用子类重写后的方法)。
- 父类的引用变量指向子类的对象。(涉及子类到父类的类型转换)
-
多态的特点:编译看父类,运行看子类
-
在编译时期,看父类是否有调用的方法,如果有则编译通过,没有则编译失败。
-
在运行时期,看子类是否有调用的方法。如果有则运行子类的重写的方法,否则运行父类的方法
-
非静态成员方法在多态调用时,编译看左边,运行看右边。而静态成员变量和静态成员方法,无论是编译还是运行都是看左边(父类)
-
-
总结:
- 当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量
- 当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量
- 当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法
- 当父类和子类具有相同的静态方法,多态下访问的是父类的静态方法。因为静态方法不能被重写
-
最终解释!!!!:
- 除了非静态的方法(没有static修饰的方法)编译看左边,运行看右边以外,不管编译和运行都是看父类
- 要看父类有没有这个方法,如果没有就要进行向下转型
static修饰符:
-
可以修饰的:
-
普通方法
-
成员变量
-
内部类
-
-
不可修饰的:
- 构造方法
- 外部类
- 局部变量
-
访问方式:
- 类名.成员名(方法)
-
被static修饰后的特点:
- 被static修饰过后的,会从元空间放到静态区当中去,并且,放到静态区过后,main方法会优先从静态区里面去找对应的东西,再按照代码的执行逻辑进行运行
- 虽然被static加载的优先加载,但是只执行一次。
- 被static修饰的成员,被这个类的所有对象共享
- 当有对象修改了这个字段的值,用到的就是修改后的值
-
作用:
- 可以避免对象被多次创建
- 需要几个对象有共享数据
- 一般情况下,修饰成员变量的时候,是配合 public static final 一起使用,被修饰的叫做:全局常量,一般 用全大写+下划线的命名方式,例如: MAX_VALUE
- 修饰方法,只是为了方便调用,比如说,Arrays里面的工具类,都是使用static修饰,方便类进行直接调用
-
变量的分类:
- 类变量:static修饰的变量,没有static修饰, 生命周期是类加载的时候开始,类被卸载的时候结束
- 实例变量:常用的变量,无static修饰 , 生命周期是创建对象的时候开始,对象失去引用的时候结束
- 局部变量:方法,或者代码块中,生命周期是方法被调用的时候开始,方法调用完毕结束
匿名内部类:
-
概念:
- 就是为了解决对象只需要调用一次的情况
-
用法:
- 可以使用父类构造器或者接口来完成使用
- 针对接口,定义匿名内部类来实现接口(使用较多)
-
语法格式:注意格式的末尾要有 ; 进行结尾
-
new 接口名称(){ //匿名内部类的类体部分 } board.plugin(new IUSB() { public void swapData() { System.out.println("打印...打印..."); } });
-
Final:
- 概念:
- 关键字,表示最终的,修饰的成员变量不可被修改
- 作用:
- 修饰外部类:
- 不可以被继承
- 实例变量:
- 必须在声明的时候或者在构造方法中进行赋值
- 类变量:
- 必须在声明的时候赋值
- public static final
- 必须在声明的时候赋值
- 实例方法:
- 不能被子类重写
- 类方法:
- 不能被子类重写
- 修饰外部类:
代码块:
-
概念:
- 作用域的问题
-
静态代码块:
-
语法:
-
直接声明在类中,前面有static修饰
-
格式:
-
static { //一般用来初始化数据,在类加载的时候就初始化完成 }
-
直接写在类中,有static修饰
-
在类加载的时候执行,和创建对象没有关系,并且只会执行一次
-
优先于主方法执行,并且,在执行完过后,JVM才会去找主方法执行
-
可以在类加载的时候做一些初始化操作,例如:JDBC驱动的加载配置
-
-
-
-
在有继承中代码块的执行顺序:
- 从最高父类的静态代码块开始加载,然后逐级向下加载,直到加载到当前类的静态代码块结束。
- 再从最高父类的构造代码块开始执行,然后是构造方法,然后逐级向下执行,直到执行到当前类的构造代码块、构造方法结束。
枚举:
-
概念:
- 一些固定不变的值放入在此类中,直接用类名调用,枚举类解决了一些取值比较固定的场景,简化了类中的常量字段。
-
语法:这里要注意,在枚举类中,我们要注意,在里面的实例变量,要进行private修饰,并且在声明了一些固定不变的字段以后,我们的实例变量要放在字段的下方
public enum 枚举类名字{ 字段 实例变量 实例方法 类方法 构造方法 - 枚举中的构造方法默认都是private修饰,不能够是public,protected修饰 构造方法作用:只能在当前枚举类中使用,就是给当前枚举类对象初始化实例变量的 } 语法: public enum Gender {//表示性别类 // MAN,//相当于一个常量public static final Gender = new Gender(); MAN(),//MAN这里也可以这样写,这里就是在调用当前枚举类的无参构造 WOMEN("女"),//这里就是在调用当前枚举类的String类型有参构造 UNKNOWN, 其他;//也可以写中文,但是不建议,建议写法:WOMEN(""); private String name;//实例变量,属于每一个枚举对象,如:MAN,WOMEN.. /** * 无参构造 */ Gender() {//默认有一个隐式的private修饰 } /** * 有参构造 */ Gender(String name) {//默认有一个隐式的private修饰 this.name = name; } @Override//实例方法 public String toString() { if (this == MAN) { return "男"; }else if (this == WOMEN) { return "女"; }else{ return "未知"; } }
-
枚举类编译完毕也同样生成字节码文件
-
每一个自定义的枚举类型都(隐式的)继承于 Enum抽象类,因此我们的枚举对象可以调用到Enum中的方法的(看API )。但是不能显示的写出继承关系。
枚举的注意事项:
- 字段之间要用逗号,最后一个字段用 ; 结束
- 可以写中文字段,但是一般建议和英文搭配使用
- eg:CQ(“重庆”)
- 枚举类都会隐式继承了Enum类(所有枚举类的基类),不能显示写出来
- 构造方法必须是要用private修饰的