其它的笔记统计在了JAVA学习记录总贴 中,欢迎大家点评
接口
一个简单例子
public class Interface01 {
public static void main(String[] args) {
Camera camera = new Camera();
Phone phone = new Phone();
Computer computer = new Computer();
computer.work(camera);
computer.work(phone);
}
}
public interface UsbInterface {
public void start();
public void stop();
}
public class Phone implements UsbInterface {
@Override
public void start() {
System.out.println("手机开始工作...");
}
@Override
public void stop() {
System.out.println("手机停止工作...");
}
}
public class Camera implements UsbInterface {
@Override
public void start() {
System.out.println("相机开始工作...");
}
@Override
public void stop() {
System.out.println("相机停止工作...");
}
}
public class Computer {
public void work(UsbInterface usbInterface){
usbInterface.start();
usbInterface.stop();
}
}
基础语法
interface 接口名{
//属性
//方法
}
class 类名 implements 接口名{
自己属性;
自己方法;
必须实现的抽象方法;
}
ps:
-
jdk7.0之前,接口内的所有方法都是抽象方法,即没有方法体。
-
jdk8.0后,接口可以有静态方法、普通方法,也就是说接口中可以有方法的具体实现,但写方法需要使用default关键字
public interface AInterface {
public int n1 = 10;
public void hi();
// 普通方法要写default关键字
public default void ok(){
System.out.println("ok()方法被调用");
}
public static void cry(){
System.out.println("cry()方法被调用");
}
}
接口应用场景
我们思考一个场景:假设一位产品经理和三位程序员一起工作,需要编写三个类,分别实现对 MySQL、Oracle、DB2 数据库的连接与关闭操作。
如果不使用接口,三位程序员很可能会按照各自的标准来写,结果开发出三个方法命名各异、实现方式也不同的类。产品经理拿到这些类后,甚至可能发现连方法名都无法统一,自然也难以进行统一调用。
但如果产品经理提前设计好接口,在接口中定义好需要被实现的方法,三位程序员只需按照这个接口去开发即可。这样最终得到的类不仅方法命名统一,而且因为它们都实现了同一个接口,产品经理还可以利用多态特性,轻松实现统一调用。
因此接口的好处是
-
规范统一
-
多台调用
public class Interface2 {
public static void main(String[] args) {
Interface2.useDatabase(new MySql());
Interface2.useDatabase(new Oracle());
Interface2.useDatabase(new DB2());
}
public static void useDatabase(DateBase dateBase){
dateBase.connect();
dateBase.close();
}
}
interface DateBase {
public void connect();
public void close();
}
class MySql implements DateBase {
@Override
public void connect() {
System.out.println("连接MySql数据库");
}
@Override
public void close() {
System.out.println("关闭MySql数据库");
}
}
class Oracle implements DateBase {
@Override
public void connect() {
System.out.println("连接Oracle数据库");
}
@Override
public void close() {
System.out.println("关闭Oracle数据库");
}
}
class DB2 implements DateBase {
@Override
public void connect() {
System.out.println("连接DB2数据库");
}
@Override
public void close() {
System.out.println("关闭DB2数据库");
}
}
接口使用细节
-
接口本身是不能实例化的。
-
接口中写抽象方法可以省略abstract关键字,接口中的所有方法默认是public
-
一个普通类实现接口,就必须将该接口的所有方法都实现
-
抽象类实现接口,可以不用实现接口的方法
-
一个类可以同时实现多个接口
-
接口中的属性默认且只能是
public static final的,比如int a = 1;其实就是public static final int a = 1;(你可以修改一下值,就能证明是fianl的;写private int a = 1;会报错,也能证明它是public的) -
接口中属性的访问方式:接口名.属性名(因为本质是静态的嘛)
-
一个接口不能继承其他的类,但是可以继承别的多个接口,比如
interface A extends B, C{}接口之间的关系是继承,接口和类之间的关系是实现
-
接口的修饰符合类一样,只能是默认或者public
小练习
interface A{
int a = 23;
}
// 实现接口的类
class B implements A{
}
// main方法所在的测试类(补充完整可运行结构)
public class Test {
public static void main(String[] args) {
B b = new B();
System.out.println(b.a);
System.out.println(A.a);
System.out.println(B.a);
}
}
请判断上述代码语法是否可以通过
答案如下
全都可以通过。
int a=23相当于public static final int a=23,没问题
A里面没有抽象方法,所以B不需要实现
三种a的调用方法,由于a本身是静态的,因此无论是用A(接口)B(实现接口的类)b(实现接口的类的对象),都可以完成调用,不过第三种形式不推荐。
接口 VS 继承
java中的实现机制,可以看作是对继承机制的一种补充。
-
接口和继承解决的问题不同
-
继承价值在于:解决代码的复用性和可维护性
-
接口价值在于:设计好各种规范方法,让其他类去实现
-
-
接口比继承更加灵活
-
继承是 is-a的关系
-
接口是 can do的关系
-
-
接口在一定程度上实现了代码解耦【依赖于接口规范性+动态绑定机制】
// 继承:is-a 关系
class Animal {}
class Dog extends Animal {} // Dog is an Animal
// 接口:can do 关系
interface Swimmable {
void swim();
}
interface Flyable {
void fly();
}
// 一个类可以同时具备多种能力
class Duck extends Animal implements Swimmable, Flyable {
@Override
public void swim() { System.out.println("鸭子游泳"); }
@Override
public void fly() { System.out.println("鸭子飞"); }
}
接口的多态特性
是的,接口也可以实现多态,代码示例如下:
public class Interface2 {
public static void main(String[] args) {
useDatabase(new MySql());
useDatabase(new Oracle());
useDatabase(new DB2());
}
static void useDatabase(DateBase dateBase){
dateBase.connect();
dateBase.close();
}
}
interface DateBase {
public void connect();
public void close();
}
class MySql implements DateBase {
@Override
public void connect() {
System.out.println("连接MySql数据库");
}
@Override
public void close() {
System.out.println("关闭MySql数据库");
}
}
class Oracle implements DateBase {
@Override
public void connect() {
System.out.println("连接Oracle数据库");
}
@Override
public void close() {
System.out.println("关闭Oracle数据库");
}
}
class DB2 implements DateBase {
@Override
public void connect() {
System.out.println("连接DB2数据库");
}
@Override
public void close() {
System.out.println("关闭DB2数据库");
}
}
可以看到useDatabase(DateBase dateBase)接收一个DataBase接口类型的参数,但是实际上可以传入实现该接口的类的实例,并且根据每个类不同的实现来调用
此外,还可以这么做
DateBase db = new DB2(); //接口的向上转型
DB2 db1 = (DB2)db; //接口的向下转型
当然也可以写接口数组,来实现多态特性
DateBase[] databases = new DateBase[3];
databases[0] = new MySql();
databases[1] = new Oracle();
databases[2] = new DB2();
for (DateBase database : databases) {
database.connect();
database.close();
}
此外,接口的多态特性也是可以传递的,如下代码
public class Interface3 {
public static void main(String[] args) {
IH ih = new T();
IG ig = new T();
}
}
interface IG{}
interface IH extends IG{}
class T implements IH{}
小练习2
下面这段代码是否有错,如果有该如何修改呢?
interface A{
int x = 0;
}
class B{
int x = 1;
}
class C extends B implements A {
public void pX(){
System.out.println(x);
}
public static void main(String[] args) {
new C().pX();
}
}
答案:
有错,类C同时继承了B的x和接口A的x,无法确定x是哪个,修改方法是
if你想访问接口的x then A.x
if你想访问父类B的x then super.x
2 个帖子 - 2 位参与者