文章目录
前言
这篇文章主要记录对抽象类和接口的理解。
一、抽象类是什么?
1.使用abstract修饰的方法叫做抽象方法,包含抽象方法的类叫做抽象类;
2.继承抽象类的类需要重写抽象类中的所有抽象方法,否则编译器会报错;
3.抽象类继承抽象类可以暂时不重写抽象方法;
4.抽象类的访问权限不能用private并且不能使用static、final修饰。
1.示例
代码如下(示例):
//抽象类
abstract class USB {
public abstract void use();
}
class Mouse extends USB {
//继承抽象类的类需要重写抽象类中的所有抽象方法
@Override
public void use() {
System.out.println("Mouse");
}
}
二、接口(interface)
1、接口中的成员变量默认都是public static final修饰;
2、接口中的方法默认是抽象方法,用public abstract修饰;
3、接口中的普通成员方法是不能有具体实现的除非加default;
4、接口不能被实例化,接口中不能有静态、实例代码块、构造方法;
5、类和接口的关联是通过implement进行实现的。
1.实例
代码如下(示例):
//接口
interface Shape {
public static final int count = 3;//接口中的成员变量默认是public static final修饰
void draw();//接口中的方法默认是抽象方法,使用public abstract修饰
}
//类与接口用implement实现关联
class Rect implements Shape {
//实现接口的类需要重写接口中的所有抽象方法
@Override
public void draw() {
System.out.println("□");
}
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("○");
}
}
class Flower implements Shape {
@Override
public void draw() {
System.out.println("❀");
}
}
public class TestDemo2 {
public static void drawShape(Shape shape){
shape.draw();
}
public static void main(String[] args) {
drawShape(new Rect());
drawShape(new Circle());
drawShape(new Flower());
}
}
2.实现多个接口
一个类先继承后实现,只能继承一个类可以实现多个接口。
代码如下(示例):
class Animal {
String name;//成员变量
int age;
//构造方法
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
}
//接口
interface IEating {
void eat();
}
interface IFlying {
void fly();
}
interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
//一个类只能继承一个类,但是可以实现多个接口
class Dog extends Animal implements IEating,IRunning,ISwimming {
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(name+" "+age+"岁,正在吃~");
}
@Override
public void run() {
System.out.println(name+" "+age+"岁,正在跑~");
}
@Override
public void swim() {
System.out.println(name+" "+age+"岁,正在游泳~");
}
}
class Bird extends Animal implements IEating,IFlying,IRunning {
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(name+" "+age+"岁,正在吃~");
}
@Override
public void fly() {
System.out.println(name+" "+age+"岁,正在飞~");
}
@Override
public void run() {
System.out.println(name+" "+age+"岁,正在跑~");
}
}
public class TestDemo3 {
public static void eat(IEating iEating) {
iEating.eat();
}
public static void fly(IFlying iFlying) {
iFlying.fly();
}
public static void run(IRunning iRunning) {
iRunning.run();
}
public static void swim(ISwimming iSwimming) {
iSwimming.swim();
}
public static void main(String[] args) {
eat(new Dog("小白",1));
run(new Dog("小白",1));
swim(new Dog("小白",1));
System.out.println("===================");
eat(new Bird("小鸟",2));
fly(new Bird("小鸟",2));
run(new Bird("小鸟",2));
}
}
三、自定义类型如何比较大小?
基本数据类型可以直接比较他们的大小,可是自定义的类型,例如:学生,如何去对学生这个类进行大小比较,如下介绍两种方法:
1.Comparable
代码如下(示例):
//Comparable接口
class Student implements Comparable<Student> {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写compareTo方法
@Override
public int compareTo(Student o) {
return this.age-o.age;
}
}
public class TestDemo4 {
public static void main(String[] args) {
Student[] arr = {new Student("李三",20),new Student("张思",19)};
System.out.println("排序前"+Arrays.toString(arr));
Arrays.sort(arr);
System.out.println("排序后"+Arrays.toString(arr));
}
}
2.Comparator
代码如下(示例):
//第二种方法:比较器 Comparator接口
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
class NameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o2.name.compareTo(o1.name);
}
}
public class TestDemo4 {
//模拟的sort排序
public static void sort(Comparable[] array) {
for (int i = 0; i < array.length-1; i++) {
for (int j = 0; j < array.length-i-1; j++) {
if(array[j].compareTo(array[j+1])>0) {
Comparable tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
}
}
}
}
public static void main(String[] args) {
Student[] students = {new Student("李三",20),new Student("张思",19),new Student("阿伟",23)};
System.out.println("排序前"+Arrays.toString(students));
Arrays.sort(students,new AgeComparator());
System.out.println("排序后"+Arrays.toString(students));
Arrays.sort(students,new NameComparator());
System.out.println("排序后"+Arrays.toString(students));
}
四、Clone实现深拷贝与浅拷贝
1.浅拷贝
改变一个会影响另一个
代码如下(示例):
//浅拷贝:改变一个会影响另一个
class Money {
public double money = 11.1;
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestDemo5 {
public static void main(String[] args) throws CloneNotSupportedException{
Person person = new Person();
Person person1 = (Person) person.clone();//浅拷贝
System.out.println("person:"+person.money.money);
System.out.println("person:"+person1.money.money);
person.money.money = 12.12;
System.out.println("person:"+person.money.money);
System.out.println("person:"+person1.money.money);
}
}
2.深拷贝
改变一个不会影响另一个
代码如下(示例):
class Money implements Cloneable{
public double money = 11.1;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
//实现深拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person) super.clone();
tmp.money = (Money) this.money.clone();
return tmp;
}
}
五、抽象类、接口的区别和联系
1.区别:
(1)抽象类中有普通类和抽象方法,接口中只有抽象方法和public static final修饰的全局常量;
(2)抽象类与类之间使用extends关键字继承,接口与类之间使用implements关键字实现;
(3)一个类只能继承一个抽象类,但是一个类可以实现多个接口;
(4)一个抽象类可以实现若干接口,但是接口不能继承抽象类,只能继承多个父类接口。
2.联系:
抽象类和接口都不可以实例化。