Java基础——抽象类与接口
前言:
在Java面向对象编程中,抽象类,接口,内部类以及Object类是构建灵活,可拓展代码的核心工具。理解它们的区别与联系,掌握使用场景,是每一位Java开发者进阶的必经之路。
本文将结合通俗易懂的案例,带你彻底搞懂:
抽象类的概念,语法和特性
接口的定义,多实现与继承
Object类的常用方法(toString,equals)
各种内部类的使用(静态内部类,实例内部类,局部内部类,匿名内部类)
抽象类与接口的核心区别
目录
一.抽象类
1.1为什么需要抽象类
在面向对象的世界里,所有对象都是通过类来描述的。但有些类并不具体,无法描述一个真实对象。比如:
Shape(图形)——它只是一个概念,无法画出具体的形状
Animal(动物)——它只是一个统称,无法让动物发出具体的叫声
这些类缺少足够的信息来描述对象,因此应该被设计为抽象类
抽象类就像一张设计图纸,不能直接拿来住人,但是可以知道建造具体的房子。
1.2抽象类语法
使用abstract关键字修饰列和方法:
public abstract class Shape{
//抽象方法;没有方法体,必须由子类实现
public abstract void draw();
//抽象类可以有自己的属性和普通方法
private double area;
public double getArea(){
return area;
}
}
1.3抽象类特性
1.不能实例化:
Shape shape =new Shape(); //编译错误
2.抽象方法不能是private ,fianl,static
abstract private void test(); // 错误
abstract final void test2(); // 错误
abstract static void test3(); // 错误
3.子类必须重新给所有抽象方法,否则子类也必须声明为抽象类
public class Cricle extends Shape{
@Override
public void draw (){
System.out.println("画一个圈");
}
}
4.抽象类可以有构造方法,供子类调用初始化父类成员
5.抽象类不一定包含抽象方法,但抽象方法的类一定是抽象类
1.4抽象类的作用
抽象类存在的最大意义:多一层编译器的校验。
如果某个方法不应该由父类实现,而必须由子类实现,那么将其声明为抽象方法,父类声明为抽象类。这样一旦由人误用父类实例化,编译器立即就会报错,避免逻辑错误。
二.接口
2.1接口的概念
接口是一种公共的行为规范。只要符合规范,不同设备都可以通用。再Java中,接口是一种引用数据类型,是多个类的公共规范
2.2接口语法
public interface USB{
//接口中的变量默认是 public static final
double VERSION =3.0
//方法默认是public abstract
void openDevice();
}
2.3接口的实现
使用implements关键字,一个类可以实现多个接口。
public class Mouse implements USB {
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
@Override
public void closeDevice() {
System.out.println("关闭鼠标");
}
}
2.4接口特性
1.不能直接实例化
2.所有方法默认public abstract(Java 8后可以有default和static方法)
3.变量默认public static final
4.没有构造方法
5.一个类可以实现多个接口,弥补了单继承的不足
2.5实现多个接口
class Frog extends Animal implements IRunning, ISwimming {
@Override
public void run() {
System.out.println(name + "正在跳");
}
@Override
public void swim() {
System.out.println(name + "正在游泳");
}
}
2.6接口间的继承
接口可以多继承,使用extends:
interface IAmphibious extends IRunning, ISwimming {
}
这样IAmphibious就合并了IRunning和ISwimming两个接口的方法。
2.7接口使用实例:对象比较
方式一:实现Comparable接口
class Student implements Comparable<Student>{
private String name;
private int score;
@Override
public int compareTo(Student o){
return this.score-o.score;
}
}
方式二:Comparator接口
class ScoreComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.score - o2.score;
}
}
2.8Cloneable接口与深拷贝
Cloneable是一个标记接口(没有任何方法),用于告诉JVM该类可以安全地克隆
class Person implements Cloneable {
public Money money = new Money();
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 浅拷贝
}
}
浅拷贝:只拷贝对象本身,内部引用类型成员仍然指向同一个对象。
深拷贝:需要手动实现,拷贝递归所有类型成员
三.抽象类VS接口
| 对比项 | 抽象类 | 接口 |
| 关键字 | abstract class | interface |
| 实例化 | 不能 | 不能 |
| 构造方法 | 可以有 | 不能有 |
| 不同方法 | 可以有 |
Java8前不能,之后可以有 default/static方法 |
| 成员变量 | 各种访问权限 | 默认private static final |
| 继承/实现 | 单继承 | 多实现 |
| 使用场景 | 表示“是什么” | 表示“能做什么” |
核心区别:抽象类可以包含普通方法和成员变量,子类可以直接复用;接口只定义规范,子类必须全部实现。
四.Object类
所有类都直接或间接继承Object,它是类层次结构的根
4.1toString()——获取对象信息
System.out.println(obj); // 默认调用 obj.toString()
默认实现:类名@哈希码的十六进制。通常需要重写以返回有意义的描述。
4.2equals()——对象比较
默认比较地址(和==一样)。若要比较内容,必须重写:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
五.内部类
内部类是指定义在另一个内部的类。它也是一种封装形式。
5.1静态内部类
被static修饰,只能访问外部类的静态成员。
public class OutClass {
static class InnerClass {
public void method() {
// 只能访问外部类的静态成员
}
}
}
// 创建
OutClass.InnerClass inner = new OutClass.InnerClass();
5.2实例内部类(非静态)
可以访问外部类的任何成员。创建时需要先有外部类实例。
public class OutClass {
class InnerClass {
public void method() {
// 可以直接访问外部类成员
}
}
}
// 创建
OutClass out = new OutClass();
OutClass.InnerClass inner = out.new InnerClass();
5.3局部内部类
定义在方法内部,只能再方法内使用,不能使用访问修饰符。
public void method() {
class LocalClass {
// ...
}
LocalClass lc = new LocalClass();
}
5.4匿名内部类
没有名字,在创建的同时之间实现接口或继承类。常用于一次性使用的场景。
Greeting greeting = new Greeting() {
@Override
public void greet() {
System.out.println("Hello!");
}
};
greeting.greet();
匿名内部类可以访问外部类的成员,以及所在方法的final或effectively final的局部变量。
六,总结
抽象类:用来表示“一种类型”,可以有部分实现,子类通过继承复用代码。
接口:用来表示“能力/规范”,强调“能做什么”,实现类需要全部实现
Object类:所有类的父类,牢记toSring,equals的重写规则。
内部类:根据位置和修饰符分为四种,匿名内部类在GUI编程,事件监听中极为常用。
更多推荐



所有评论(0)