Java基础-面向对象进阶-抽象类, 接口, 内部类
抽象类
- 抽象类作用
- 抽取共性时, 无法确定方法体, 就把方法定义为抽象的
- 强制让子类按照某种格式重写
- 抽象方法所在的类, 必须是抽象类
- 抽象类和抽象方法的格式
public abstract 返回值类型 方法名(参数列表);
public abstract class 类名{}
- 继承抽象类注意事项
- 要么重写抽象类中的所有抽象方法
- 要么是抽象类
// demo
public class demo {
public static void main(String[] args) {
// 编写带有抽象类的标准JavaBean类
Frog frog = new Frog("青蛙", 2);
frog.eat();
frog.drink();
}
}
// Animal
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
public void drink(){
System.out.println("喝水");
};
}
// Frog
public class Frog extends Animal{
public Frog() {
}
public Frog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("吃虫子");
}
@Override
public void drink() {
System.out.println("喝水");
}
}
接口
接口的基本使用
// demo
public class demo {
public static void main(String[] args) {
// 编写带有接口和抽象类的标准JavaBean类
Frog f = new Frog("青蛙", 2);
f.eat();
f.swim();
}
}
// Animal
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
}
// Swim
public interface Swim {
void swim();
}
// Frog
public class Frog extends Animal implements Swim{
public Frog() {
}
public Frog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("吃虫子");
}
@Override
public void swim() {
System.out.println("蛙泳");
}
}
接口中成员的特点
- 成员变量
- 只能是常量
- 默认修饰符:
public static final
- 构造方法
- 没有
- 成员方法(JDK7以前)
- 只能是抽象方法
- 默认修饰符:
public abstract
接口和类之间的关系
- 类和类的关系
继承关系,只能单继承,不能多继承,但是可以多层继承 - 类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口 - 接口和接口的关系
继承关系,可以单继承,也可以多继承
综合练习
- demo
public class Demo { public static void main(String[] args) { /** * 我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练 * 为了出国交流,跟乒乓球相关的人员都需要学习英语。 * 请用所有知识分析,在这个案例中,哪些是具体类,哪些是抽象类,哪些是接口? * * 乒乓球运动员:姓名,年龄,学打乒乓球,说英语 * 篮球运动员:姓名,年龄,学打篮球 * 乒乓球教练:姓名,年龄,教打乒乓球,说英语 * 篮球教练:姓名,年龄,教打篮球 */ PingpongAthletes pingpongAthletes = new PingpongAthletes("乒乓球运动员", 30); pingpongAthletes.speakEnglish(); pingpongAthletes.learn(); PingpongInstructor pingpongInstructor = new PingpongInstructor("乒乓球教练", 35); pingpongInstructor.speakEnglish(); pingpongInstructor.teach(); BasketballAthletes basketballAthletes = new BasketballAthletes("篮球远动员", 31); basketballAthletes.learn(); BasketballInstructor basketballInstructor = new BasketballInstructor("篮球教练", 36); basketballInstructor.teach(); } }
- abstract
// Person // 不希望Person类被创建 public abstract class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } } // Athletes public abstract class Athletes extends Person{ public Athletes() { } public Athletes(String name, int age) { super(name, age); } public abstract void learn(); } // Instructor public abstract class Instructor extends Person{ public Instructor() { } public Instructor(String name, int age) { super(name, age); } public abstract void teach(); }
- interface
// SpeakEnglish public interface SpeakEnglish { public abstract void speakEnglish(); }
- impl
// BaskAthletes public class BasketballAthletes extends Athletes{ public BasketballAthletes() { } public BasketballAthletes(String name, int age) { super(name, age); } @Override public void learn() { System.out.println("学打篮球"); } } // PinAthletes public class PingpongAthletes extends Athletes implements SpeakEnglish{ public PingpongAthletes() { } public PingpongAthletes(String name, int age) { super(name, age); } @Override public void learn() { System.out.println("学打乒乓球"); } @Override public void speakEnglish() { System.out.println("说英语"); } } // BaskInstr public class BasketballInstructor extends Instructor{ public BasketballInstructor() { } public BasketballInstructor(String name, int age) { super(name, age); } @Override public void teach() { System.out.println("教打篮球"); } } // PinInstr public class PingpongInstructor extends Instructor implements SpeakEnglish{ public PingpongInstructor() { } public PingpongInstructor(String name, int age) { super(name, age); } @Override public void teach() { System.out.println("教打乒乓球"); } @Override public void speakEnglish() { System.out.println("说英语"); } }
接口的扩展
JDK8开始接口中新增的方法
- Jdk7以前: 接口中只能定义抽象方法
- Jdk8: 接口中可以定义有方法体的方法(默认, 静态)
- Jdk9: 接口中可以定义私有方法
- 普通的私有方法, 服务默认方法
- 静态的私有方法, 服务静态方法
适配器设计模式
- 当一个接口中抽象方法过多, 但是我只要使用其中一部分的时候, 就可以使用适配器设计模式
- 书写步骤
- 编写中间类XXXAdapter, 实现对应的接口
- 对接口中的抽象方法进行空实现
- 让真正的实现类继承中间类, 并重写需要用的方法
- 为了避免其他类创建适配器类的对象, 中间的适配器类用abstract进行修饰
内部类
初识内部类
- 内部类: 类里的类
- 使用场景
- B类表示的事物是A类的一部分, 且B单独存在没有意义
// Demo
public class Demo {
public static void main(String[] args) {
/**
* 需求:写一个Javabean类描述汽车
* 属性:汽车的品牌,车龄,颜色,发动机的品牌,使用年限。
*
* 内部类的访问特点:
* 内部类可以直接访问外部类的成员,包括私有
* 外部类要访问内部类的成员,必须创建对象
*/
}
}
// Car
public class Car {
private String carName;
private int carAge;
private String carColor;
public void show()
{
System.out.println(carName);
Engine e = new Engine();
System.out.println(e.engineName);
}
class Engine{
private String engineName;
private int engineAge;
public void show()
{
System.out.println(engineName);
System.out.println(carName);
}
}
}
成员内部类
- 成员内部类代码书写, 创建成员内部类的对象
成员内部类可以被修饰符修饰 成员内部类里, Jdk16之前不能定义静态变量 获取成员内部类对象的两种方式 1. 外部类编写方法, 对外提供内部类对象(private) 2. 直接创建: Outer.Inner oi = new Outer().new Inner();
// Demo public class Demo { public static void main(String[] args) { Outer o = new Outer(); // Outer.Inner oi = o.getInstance(); // Inner是private, 无法Outer.Inner Object oi = o.getInstance(); } } // Outer public class Outer { private String name; private class Inner{ private String name; } public Inner getInstance(){ return new Inner(); } }
- 内部类获取外部类的成员变量(内部类成员变量和外部类成员变量重名)
public class Outer { private int a = 10; class Inner{ private int a = 20; public void show(){ int a = 30; // Outer.this => 外部类对象的地址值 System.out.println(Outer.this.a); // 10 System.out.println(this.a); // 20 System.out.println(a); // 30 } } }
静态内部类
注意事项:
1. 静态内部类也是成员内部类中的一种
2. 静态内部类只能访问外部类中的静态变量和静态方法,
如果想要访问非静态的需要创建外部类的对象。
创建静态内部类对象的格式:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
调用静态方法的格式:
外部类名.内部类名.方法名();
// Demo
public class Demo {
public static void main(String[] args) {
Outer.Inner oi = new Outer.Inner();
oi.show1();
// 静态方法
Outer.Inner.show2();
}
}
// Outer
public class Outer {
// 静态内部类
static class Inner{
public void show1(){
System.out.println("调用非静态方法");
}
public static void show2(){
System.out.println("调用静态方法");
}
}
}
局部内部类
- 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量.
- 外界是无法直接使用局部内部类,需要在方法内部创建对象并使用。
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
匿名内部类
- 什么是匿名内部类
隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置 - 匿名内部类的格式
new 类名或者接口名(){ 重写方法; };
- 格式的细节
包含了继承或实现,方法重写,创建对象。
整体就是一个类的子类对象或者接口的实现类对象 - 使用场景
当方法的参数是接口或者类时
以接口为例,可以传递这个接口的实现类对象
如果实现类只要使用一次,就可以用匿名内部类简化代码
来源
黑马程序员. 阿玮Java零基础
Gitee地址
https://gitee.com/yu-ba-ba-ba/awJava