Java中一个接口是一个引用类型,类似于类,可以通过使用Interface关键字声明。
接口可以仅包含常量,方法签名,默认方法,静态方法和嵌套类型。
方法体仅存在默认方法和静态方法。
与抽象类一样,无法实例化接口 - 它们只能由类实现或者由其他接口扩展。
该接口是实现Java中的完整抽象的常用方式
Java如何实现多个接口
Java类可以实现多个接口。
public interface NoiseMaker { String noise = "Making Noise"; //interface variables are public static final by default String makeNoise(); //interface methods are public abstract by default } public interface FoodEater { void eat(Food food); } public class Cat implements NoiseMaker, FoodEater { @Override public String makeNoise() { return "meow"; } @Override public void eat(Food food) { System.out.println("meows appreciatively"); } }
请注意CAT类必须如何在接口中实现继承的抽象方法。
此外,请注意,A类如何实际上可以根据需要(由于JVM限制导致65,535的限制)。
NoiseMaker noiseMaker = new Cat(); //Valid FoodEater foodEater = new Cat(); //Valid Cat cat = new Cat(); //valid Cat invalid1 = new NoiseMaker(); //Invalid Cat invalid2 = new FoodEater(); //Invalid
说明:
- 接口中声明的所有变量都是公共静态最终
- 在接口方法中声明的所有方法都是公共摘要(此语句仅通过Java有效
- 从Java 8,我们可以在接口中拥有方法,这不需要抽象;此类方法称为默认方法)
- 接口不能被声明为最终
- 如果多个接口声明了具有相同签名的方法,那么有效地将其视为一种方法,并且我们无法区分实施接口方法
- 编译时,将为每个接口生成相应的interfaceName.class文件
声明和实现接口
使用接口关键字声明接口关键字:
public interface Animal { String getSound(); //Interface methods are public by default }
覆盖注释
@Override public String getSound() { //Code goes here… }
这会强制编译器检查我们正在覆盖并阻止程序定义新方法或者搞定方法签名。
接口使用实现关键字实现。
public class Cat implements Animal { @Override public String getSound() { return "meow"; } } public class Dog implements Animal { @Override public String getSound() { return "woof"; } }
在该示例中,类CAT和Dog必须定义Getsound()方法,因为接口的方法是固有的抽象的(默认方法除外)。
使用接口
Animal cat = new Cat(); Animal dog = new Dog(); System.out.println(cat.getSound()); //prints "meow" System.out.println(dog.getSound()); //prints "woof"
扩展接口
接口可以通过扩展关键字扩展另一个接口。
public interface BasicResourceService { Resource getResource(); } public interface ExtendedResourceService extends BasicResourceService { void updateResource(Resource resource); }
现在,实现ExecineResureService的类需要实现GetResource()和
updateDateSource()。
扩展多个接口
与类不同,扩展关键字可用于扩展多个接口(由逗号分隔),允许接口组合到新的接口中
public interface BasicResourceService { Resource getResource(); } public interface AlternateResourceService { Resource getAlternateResource(); } public interface ExtendedResourceService extends BasicResourceService, AlternateResourceService { Resource updateResource(Resource resource); }
在这种情况下,实现ExtendedResourceService的类将需要实现GetResource(),getAlternaterSource()和endateresource()。
接口的有用性
在许多情况下,接口可能非常有用。
例如,假设我们有一个动物列表,我们希望循环通过列表,每次打印它们所做的声音。
{cat, dog, bird}
这样做的一种方法是使用接口。
这将允许在所有类上调用相同的方法
public interface Animal { public String getSound(); }
实现动物的任何类也必须其中有一个getsound()方法,但它们都可以具有不同的实现
public class Dog implements Animal { public String getSound() { return "Woof"; } } public class Cat implements Animal { public String getSound() { return "Meow"; } } public class Bird implements Animal{ public String getSound() { return "Chirp"; } }
我们现在有三个不同的类,每个类都有一个getsound()方法。
因为所有这些类都实现了声明getsound()方法的动物接口,所以动物的任何实例都可以拥有
getsound()调用它
Animal dog = new Dog(); Animal cat = new Cat(); Animal bird = new Bird(); dog.getSound(); //"Woof" cat.getSound(); //"Meow" bird.getSound(); //"Chirp"
因为这些是一种动物,我们甚至可以将动物放在一个列表中,循环穿过它们,并打印出他们的声音
Animal[] animals = { new Dog(), new Cat(), new Bird() }; for (Animal animal : animals) { System.out.println(animal.getSound()); }
因为数组的顺序是狗,cat ,然后是鸟,“woof meow chirp”将被打印到控制台。
接口也可以用作函数的返回值。
例如,如果输入是“狗”,则返回狗,cat 如果输入是“cat ”,并且如果它是“鸟”,那么打印那个动物的声音可以使用
public Animal getAnimalByName(String name) { switch(name.toLowerCase()) { case "dog": return new Dog(); case "cat": return new Cat(); case "bird": return new Bird(); default: return null; } } public String getAnimalSoundByName(String name){ Animal animal = getAnimalByName(name); if (animal == null) { return null; } else { return animal.getSound(); } } String dogSound = getAnimalSoundByName("dog"); //"Woof" String catSound = getAnimalSoundByName("cat"); //"Meow" String birdSound = getAnimalSoundByName("bird"); //"Chirp" String lightbulbSound = getAnimalSoundByName("lightbulb"); //null
接口对于可扩展性也是有用的,因为如果要添加新类型的动物,则无需使用我们在它们上执行的操作更改任何操作。