继承
继承是指子类继承父类的特征(属性)和行为(方法),实现如下:
public class Animal{
private String name;
private Long id;
public Animal(String name, Long id) {
this.name = name;
this.id = id;
}
public void eat(String foodName) {
System.out.println(id + "号动物" + name + "正在吃:" + foodName);
}
}
public class Cat extends Animal{
public Cat(String name, Long id) {
super(name, id);
}
}
public class Dog extends Animal{
public Dog(String name, Long id) {
super(name, id);
}
}
public static void main(String[] args) {
Cat cat = new Cat("小猫",1L);
cat.eat("鱼");
Dog dog = new Dog("小狗",2L);
dog.eat("骨头");
}
// 输出
// 1号动物小猫正在吃:鱼
// 2号动物小狗正在吃:骨头
继承的特点:
- Java支持单继承,不支持多继承,即一个类仅支持继承一个父类。作为父类,一个类可以被多个类同时继承
- Java支持多重继承。多个类可以依次继承,A->B->C
- 子类可以继承父类的非私有属性和方法(示例中,super关键字提供了子类访问父类成员的能力)
- 子类可以独立拥有自己的属性和方法
- 继承增加了代码的耦合性(缺点)
public class Animal {
// 在移除了构建方法的情况下,子类无法访问父类属性
// 示例中通过提供公开的GET、SET方法访问
private String name;
private Long id;
private Integer sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
private Integer getSex() {
return sex;
}
private void setSex(Integer sex) {
this.sex = sex;
}
// public Animal(String name, Long id) {
// this.name = name;
// this.id = id;
// }
public void eat(String foodName) {
System.out.println(id + "号动物" + name + "正在吃:" + foodName);
}
}
public static void main(String[] args) {
// Cat cat = new Cat("小猫",1L);
// cat.eat("鱼");
// Dog dog = new Dog("小狗",2L);
// dog.eat("骨头");
Dog dog = new Dog();
dog.setName("小狗");
dog.setId(3L);
dog.eat("骨头");
}
重写和重载
重写(Override):是指子类对父类允许访问方法的重新实现,但要保持形参、返回值保持不变。即不改框架,改实现
public class Animal {
public void eat(String foodName) {
System.out.println("动物" + "正在吃:" + foodName);
}
}
public class Cat extends Animal{
@Override
public void eat(String foodName) {
System.out.println("小猫正在吃:" + foodName);
}
}
public static void main(String[] args) {
Animal animal = new Animal();
animal.eat("饭");
Cat cat = new Cat();
cat.eat("鱼");
}
// 示例中,子类Cat继承了父类Animal,重写了父类的eat方法,最终实现效果验证重写成功
// 动物正在吃:饭
// 小猫正在吃:鱼
重写规定:
- 构造方法不可以被重写
- 访问权限不能降低,如父类public,子类private
- final修饰的方法不可被重写
- static修饰的方法不可被重写,但可以重新声明
- 子类和父类在同一包中,子类可以重写父类除了声明为private和final的方法
- 子类和父类不在用一包中,子类只能重写父类声明为public和protected的非final方法
- 重写方法可以抛出任何非强制性异常,但不能抛出新的或者比被被重写方法更广泛的强制性异常
重载(Overload):是指同一个类中,存在多个同名但不同参数的方法。返回类型可以相同,也可以不相同
重载规定:
- 重载方法必须改变参数列表
- 重载方法可以改变修饰符
- 重载方法可以声明新的或者更广泛的异常
@Data
public class Dog {
private Long id;
private String name;
public Dog(){
}
public Dog (Long id){
this.id = id;
}
public Dog (String name){
this.name = name;
}
public Long create(Long id){
return id;
}
public String create(String name){
return name;
}
public String create(Long id, String name) throws Exception {
if(id == null){
throw new Exception("id is null");
}
return id.toString() + name;
}
}
public static void main(String[] args) throws Exception {
Dog dogA = new Dog(3L);
System.out.println(dogA.getId());
Dog dogB = new Dog("dogB");
System.out.println(dogB.getName());
Dog dog = new Dog();
dog.setId(1L);
System.out.println(dog.getId());
System.out.println(dog.create(2L));
System.out.println(dog.create("dog"));
System.out.println(dog.create(null, "nullDog"));
}
// 3
// dogB
// 1
// 2
// dog
// Exception in thread "main" java.lang.Exception: id is null
// at com.demo.controller.Dog.create(Dog.java:34)
// at com.demo.controller.Test.main(Test.java:60)
封装
封装可以简单理解为信息(细节)隐蔽,将一系列的信息、方法密封在一个个体内部
public class Animal {
private String name;
private Long id;
public String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
}
// 将一个动物类的信息name、id封装在Animal实体内部
// 提供公共get方法支持外部获取信息。不支持改变内部信息,所以set方法为private私有
多态
多态是指同一个事物或者行为拥有不同的表现形式,比如同属于动物的猫与狗,拥有不同的叫声、不同的食物
public class Animal {
public void eat( ) {
}
}
public class Cat extends Animal{
@Override
public void eat( ) {
System.out.println("小猫正在吃鱼");
}
}
public class Dog extends Animal{
@Override
public void eat( ) {
System.out.println("小狗正在吃骨头");
}
}
public static void main(String[] args) throws Exception {
Animal cat = new Cat();
cat.eat();
Animal dog = new Dog();
dog.eat();
}
// 同属于动物的猫、狗,再同一种“吃”的行为上具有不同的表现形式
抽象类
一个类具体自己的描述属性、方法,但当一个类没有足够的信息描述的时候,可以将该类作为一个抽象类,在Java中,抽象类用abstract class 来修饰。抽象类与普通类相比,类的功能依然存在,但抽象类不能被实例,需要通过继承抽象类来获取其属性和方法
抽象方法
需要定义一个方法,具体地实现有多种形式的情况下,可以考虑声明一个抽象方法,该方法在父类中仅存在方法的声明(类似接口),不存在方法体。而它的子类必须重写父类的抽象方法
public abstract class Animal{
private String name;
private Long id;
public abstract String eat();
}
public class Cat{
private String color;
@Override
public String eat(){
rerurn 'true';
}
}
特点
- 抽象类不能被实例化,通过其子类创建对象
- 抽象类中不一定含有抽象方法,但有抽象方法的类一定是抽象类
- 抽象类中声明的抽象方法,只有声明,没有方法体
- 构造方法、用static修饰的方法不能声明为抽象方法
- 抽象类的子类在不是抽象类的情况下,必须写出继承的抽象方法的具体实现
接口
特点
- 接口是一系列抽象方法的集合体,由interface声明,接口并不是class
- 接口由类去实现,实现类必须包含接口中声明的所有方法
- 接口中的方法都是隐式抽象,不必使用关键字声明
- 接口中的方法都是公有方法
类与接口的对比
- 接口不能实例化,类可以
- 接口没有构造方法,类可以有构造方法
- 接口中的方法必须是抽象方法。或也可以由default修饰的方法(JDK1.8)
- 接口由类实现
- 接口支持多继承
抽象类与接口的对比
- 一个类只可以继承一个抽象类,但一个类可以实现多个接口
- 接口的成员变量必须由 ‘public static final’修饰,并且赋值
- 接口没有构造方法,抽象类可以有构造方法
- 接口和抽象类都是抽离出来的概念
- 接口和抽象类都可以有具体的实现。JDK1.8允许给接口添加非抽象方法的实现,但必须使用default修饰