1. 实现多个接口
在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。
通过类来表示一组动物:
class Animal { protected String name; public Animal(String name) { this.name = name; } }
另外我们再提供一组接口,分别表示“会飞的”,“会跑的”,“会游泳的”:
interface IFlying { void fly(); } interface IRunning { void run(); } interface ISwimming { void swim(); }
接下来我们创建几个具体的动物:
猫,是会跑的
class Cat extends Animal implements IRunning { public Cat(String name) { super(name); } @Override public void run() { System.out.println(this.name + "正在用四条腿跑"); } }
鱼,是会游的
class Fish extends Animal implements ISwimming { public Fish(String name) { super(name); } @Override public void swim() { System.out.println(this.name + "正在用尾巴游泳"); } }
青蛙,既能跑,又能游
class Frog extends Animal implements IRunning, ISwimming { public Frog(String name) { super(name); } @Override public void run() { System.out.println(this.name + "正在往前跳"); } @Override public void swim() { System.out.println(this.name + "正在蹬腿游泳"); } } class Frog extends Animal implements IRunning, ISwimming { public Frog(String name) { super(name); } @Override public void run() { System.out.println(this.name + "正在往前跳"); } @Override public void swim() { System.out.println(this.name + "正在蹬腿游泳"); } }
13
当一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。
例如:鸭子,会游、会飞、会跑
class Duck extends Animal implements IRunning, ISwimming, IFlying { public Duck(String name) { super(name); } @Override public void fly() { System.out.println(this.name + "正在用翅膀飞"); } @Override public void run() { System.out.println(this.name + "正在用两条腿跑"); } @Override public void swim() { System.out.println(this.name + "正在漂在水上"); } }
对上述代码的实现:
public class test { public static void main(String[] args) { Cat cat=new Cat("小花"); cat.run(); Fish fish=new Fish("jiujiu"); fish.swim(); Frog frog=new Frog("青蛙王子"); frog.run(); frog.swim(); Duck duck=new Duck("可达鸭"); duck.run(); duck.fly(); duck.swim(); } }
🍤 运行结果:
上面的代码展示了 Java 面向对象编程中最常见的用法:一个类继承一个父类,同时实现多种接口。
🍩继承表达的含义是 is - a 语义,而接口表达的含义是具有 xxx 特性
🍩有了接口之后,类的使用者就不必关注具体类型,而只关注某个类是否具备某种能力
例如,现在实现一个方法,叫“散步”
public static void walk(IRunning running) { System.out.println("我带着伙伴去散步"); running.run(); }
在这个 walk 方法内部,我们并不关注到底是哪种动物,只要参数是会跑的就行。
2. 接口间的继承
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。
接口可以继承一个接口,达到复用的效果。使用 extends 关键字。
interface IRunning { void run(); } interface ISwimming { void swim(); } // 两栖的动物, 既能跑, 也能游 interface IAmphibious extends IRunning, ISwimming { } class Frog implements IAmphibious { ... }
通过接口继承创建一个新的接口 IAmphibious 表示“两栖的”,此时实现接口创建的 Frog 类,就继续要实现 run 方法,也需要实现 swim 方法。
🍩接口间的继承相当于把多个接口合并在一起
3. Clonable接口和深拷贝
Java 中内置了一些很有用的接口,Clonable 就是其中之一。
Object 类中存在一个 clone 方法,调用这个方法可以创建一个对象的“拷贝”。但是要想合法调用 clone 方法,必须要先实现 Clonable 接口,否则就会抛出CloneNotSupportedException 异常。
class Animals implements Cloneable { private String name; @Override public Animals clone() { Animals o = null; try { o = (Animals)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return o; } } public class Test1 { public static void main(String[] args) { Animals animal = new Animals(); Animals animal2 = animal.clone(); System.out.println(animal == animal2); } }
🍤 运行结果:
Cloneable 拷贝出的对象是一份“浅拷贝”
class Money { public double m = 99.99; } class Person implements Cloneable{ public Money money = new Money(); @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Test1 { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person(); Person person2 = (Person) person1.clone(); System.out.println("通过person2修改前的结果"); System.out.println(person1.money.m); System.out.println(person2.money.m); person2.money.m = 13.6; System.out.println("通过person2修改后的结果"); System.out.println(person1.money.m); System.out.println(person2.money.m); } }
🍤 运行结果:
如上代码,我们可以看到,通过clone,我们只是拷贝了Person对象。但是Person对象中的Money对象,并没有拷贝。通过person2这个引用修改了m的值后,person1这个引用访问m的时候,值也发生了改变。这里就是发生了浅拷贝。