一,封装
生活中的封装体:包装盒、机箱
代码中的封装体:包、类、方法
好处:
- 提高了代码的复用性
- 隐藏了实现细节
- 提高了代码的安全性
属性的封装:
遇到的问题:在对属性进行赋值时,只要赋的值是符合该类型的任何值都可以完成赋值动作,但是赋的值可能是不合理的数据。
原因:
- 只要有对象就可以随意调用属性进行赋值
- 对属性进行赋值时没有对数据进行合理性的判断
解决办法:
使用关键字
private
将属性私有化注:范围修饰符的大小范围:
public > protected > [default] > private
,被private
修饰的成员只能在本类中访问。对外提供这个私有属性的访问方法
// 赋值 public void setAge(int age){ this.age = age; } // 获取 public int getAge(){ return age; }
注:如果属性的布尔类型的,set/get应该换成set/is
一个标准的javabean必须包含的3部分:无参构造函数、私有化的属性、私有属性的set/get方法
二,继承
2.1 继承的概念
生活中的继承:子女拥有父母的东西
代码块中继承:类与类之间产生了关系,子类可以直接访问父类中的成员
父类是子类共性内容向上抽取形成的,子类中除了有父类的共性内容之外还可以特有内容
父类:superclass,超类、基类
子类:subclass,派生类、衍生类
注:
- 一般来说,父类的范围更大,属性和方法较少;子类的范围更小,属性和方法更多
- java中有一个类
Object
,它是所有类的父类(任何一个类都直接或者间接的继承了Object)- 一个子类就是一个父类
好处:
- 提高了代码的复用性
- 为多态提供了前提
2.2 父类和子类的定义
关键字:
extends
格式:
public class 父类{ } public class 子类 extends 父类{ }
注:
- 一个子类只能有一个父类
- 一个父类可以有多个子类
- 继承具有传递性
- 不能循环继承
2.3 子父类中成员的同名成员的问题
2.3.1 同名变量
子父类中存在同名的成员变量时,子类对象优先访问子类中的。
就近原则
如果要访问父类中的同名成员变量,需要在子类中通过关键字
super
进行访问
2.3.2 同名方法
子父类中存在同名的成员方法时,子类对象优先访问子类中的。
就近原则
如果要访问父类中的同名成员方法,需要在子类中通过关键字
super
进行访问
方法的重写:在继承关系中,子类方法与父类方法的方法名、参数列表都相同
重写的作用:扩展父类功能
注:
注解
@Override
可以用于校验是否是重写子类重写父类方法的范围修饰符必须大于等于父类范围修饰符
范围修饰符的大小范围:
public > protected > [default] > private
父类私有方法不能被重写 (子类看不到这个私有的方法)
- 静态方法只能被继承,无法被重写,因为其同main方法一同在最初被加载了。
子类重写父类方法的返回类型必须是父类方法的返回类型或者该类的子类
2.4 父类属性私有化的问题
子类的共性属性抽取到父类中,父类属性私有化了,子类不能直接访问,可以通过父类对外提供的这些私有属性的
set/get
方法进行访问。如何使用构造函数的重载,在创建子类对象时,对子类的属性进行初始化
步骤:
- 重载父类构造函数
- 在子类的重载构造函数中调用父类的重载构造函数
public class Employee { private String name; private int age; private double salary; private String sex; public Employee() { } public Employee(String name, int age, double salary, String sex) { this.name = name; this.age = age; this.salary = salary; this.sex = sex; } // set/get方法 }
public class Programmer extends Employee { public Programmer() { } public Programmer(String name,int age,double salary ,String sex){ super(name, age, salary, sex); } }
子类中有特有属性的情况:
public class Employee { private String name; private int age; private double salary; private String sex; public Employee() { } public Employee(String name, int age, double salary, String sex) { this.name = name; this.age = age; this.salary = salary; this.sex = sex; } // set/get方法 }
public class Manager extends Employee{ private double bonus; public Manager() { } public Manager(String name, int age, double salary, String sex){ super(name, age, salary, sex); } public Manager(String name, int age, double salary, String sex,double bonus){ super(name, age, salary, sex); this.bonus = bonus; } // set/get方法 }
2.5 关键字 this 和 super
this
:表示本类对象,调用方法时,表示当前方法的调用者作用:
调用本类的成员变量
调用本类的成员方法
调用本类的其他构造函数
public class Stu { String name; int age; double score; String address; String sex; double height; double weight; public Stu() { } public Stu(String name, int age,String sex) { this.name = name; this.age = age; this.sex = sex; } public Stu(String name, int age,double score,String address,String sex ,double height,double weight) { this(name, age, sex); this.address = address; this.height = height; this.weight = weight; this.score = score; } }
注:本类构造函数的调用必须是构造函数的第一条语句,this只能在非静态方法中使用,不可在静态方法和静态代码块中出现this关键字
super
:表示父类的引用作用:
调用父类的成员变量
调用父类的成员方法
调用父类的构造函数
注:
- 任何一个类的每一个构造函数中的第一行都默认调用了父类的无参构造函数
- 如果手动调用了父类的重载构造函数,那么就不再默认调用的父类无参构造函数了
- 父类构造函数的调用必须是子类构造函数中的第一条语句
- 构造函数中不能同时调用父类的构造函数和本类的构造函数;如果没有调用本类的构造函数,就在第一行默认调用父类的无参构造函数,如果调用了本类的构造函数,那么就不再默认调用父类的构造函数了
注意
:this和super关键字在调用构造函数的时候必须在调用方法的第一条语句,不可同时出现,否则报错.
三,抽象类
3.1 概念
抽象方法:子类的共性方法抽取到父类中,而父类无法描述每个子类的具体实现,这样的方法就是抽象方法
抽象方法的定义:
- 使用关键字
abstract
修改方法- 抽象方法没有方法体,直接以
;
结尾抽象方法所在的类必须是抽象类
3.2 抽象类的使用
抽象类不能创建对象
抽象类必须要有子类,除非子类重写父类中的所有抽象方法,否则子类也是一个抽象类
步骤:
- 定义抽象类的子类
- 重写所有抽象方法
- 创建子类对象进行调用
3.3 注意事项
- 抽象类不能创建对象
- 抽象类可以有构造函数
- 抽象方法必须在抽象类中
- 抽象类中也可以有非抽象方法
3.4 关键字 final
可以修饰:
变量:不能被修改
注:成员变量被
final
修饰时,必须手动初始化方法:不能被重写
类:不能被继承
注:被final修饰的类和方法是最终的,无法被继承,实现和重写
final与abstract不能共存 :
final修饰最终类和方法 而abstract必须要有子类,否则无意义 所以这两个关键字无法修饰同一个类和方法
static与abstract不能共存
3.5 匿名对象
创建对象时,不指定对象的引用变量名
好处:使用方便
弊端:
- 只能使用一次
- 可读性差
3.6 匿名内部类
作用:匿名创建子类对象
格式:
new 类名(){ // 重写方法 };
四,接口
4.1 概念
接口是一种特殊的数据类型,它在编译后生成也是
.class
文件,接口是功能的集合好处:
- 对外提供了规则
- 接口扩展了功能
4.2 接口的定义
关键字:
interface
格式:
public interface 接口名{ }
4.3 接口中成员的特点
接口中的成员变量:默认被
public static final
修饰接口中的成员方法:默认被
public abstract
修饰
4.4 接口的使用
关键字:实现
implements
,实现类实现接口步骤:
- 创建实现类实现接口
- 重写接口中的所有抽象方法
- 创建实现类对象调用方法
接口也可以使用匿名内部类的方式创建实现类对象
格式:
new 接口名(){ // 重写方法 };
4.5 类、接口之间的关系
类与类的关系:是继承,子类继承父类
public class 子类 extends 父类{ }
注:类与类之间只存在单继承
(
如果可以多继承,那么多个父类中的同名具体方法,子类无法分辨,接口中都是抽象方法,必须重写,则避免了这种问题的发生
)
类与接口的关系:是实现,实现类实现接口
public class 实现类 implements 接口A,接口B,接口C,...{ }
注:
一个类可以实现多个接口
实现类必须实现所有接口中的所有抽象方法
多个接口中有同名方法,实现类只需要实现一次
接口与接口的关系:是继承,子接口继承父接口
public class 子接口 extends 父接口A,父接口B,父接口C,...{ }
注:
- 接口与接口之间存在多继承
- 子接口继承的多个接口中如果存在同名同参的方法,那么这两个方法的返回类型必须是相同的或者是存在继承关系的
- 子接口继承的多个接口中,一个接口的普通方法与另一个接口的抽象方法同名同参时,子接口可以定义同名的抽象方法或者定义同名的普通方法
子类继承父类的同时实现接口
public class 子类 extends 父类 implements 接口A,接口B,接口C,...{ }
当类和接口中都定义了普通方法 , 根据就近原则执行继承或实现中离本类最近的接口或父类的同名方法
如果要调用接口里的普通方法,在实现类方法中:
接口.super.同名方法
package Demo1; public class D extends A implements C{ public void showC(){ C.super.show(); } }
4.6 接口的新特性
从Java8开始,接口中允许定义普通方法
格式:
public default 返回类型 方法名(参数列表){ }
注:
实现类可以对接口中的普通方法进行重写,重写时不能再写
default
父类中的方法与接口中的普通方法同名时,子类不需要重写该方法,子类对象优先调用父类中的
实现类中调用接口中普通方法:
接口名.super.方法名(参数);
实现类实现的多个接口中存在同名的普通方法,实现类必须重写该方法
实现类实现的一个接口中的普通方法和实现的另一个接口中的抽象方法同名,实现类必须重写该方法
从Java8开始,接口中允许定义静态方法
格式:
public static 返回类型 方法名(参数列表){ }
注:接口中的静态方法只能由定义它的接口名调用
从Java9开始,接口中允许定义私有方法
格式:
private 返回类型 方法名(参数列表){ }
意义:为接口中的其他普通方法提供支持,但不需要对外提供的
4.7 抽象类和接口的异同
同:
- 都不能创建对象
- 都可以有抽象方法
- 都需要子类(实现类)继承(实现)
异:
- 接口中的方法都是抽象方法,抽象类中可以有非抽象方法
- 抽象类中的成员变量与普通类中的成员变量没有区别,但是接口中的成员变量都是静态常量
- 抽象类是类class,接口是接口interface,抽象类与子类的关系是继承extends,接口与实现类的关系是实现implements
- 一个类只能继承一个抽象类,一个类可以实现多个接口
- 类与类之间只能单继承,接口与接口之间可以多继承
- 抽象类有构造函数,接口没有构造函数
- 抽象类是描述一类事物的属性和方法的集合,接口是功能的集合
抽象类和接口的选用:优先选用接口,接口避免了单继承的局限性