当一个类中,没有足够的信息去描述一件具体的事物(对象)时,那么这个类就要定义成抽象类。
使用 abstract 关键字来定义抽象类,语法如下:
访问修饰符 abstract class 类名{ }●抽象类中可以有构造方法,但是不能创建(new)对象
● 普通类中定义的属性和方法,都可以在抽象类中定义
●抽象类中,可以存在抽象方法
●抽象方法,定义语法: 访问修饰符 abstract 返回值类型 方法名(参数列表);
● 抽象方法没有方法体,只有方法的声明
● 抽象类中的抽象方法,必须由子类来实现;如果子类没有实现,则子类也要定义成 抽象类,由子类的子类来实现,以此类推。
● 抽象类中,可以没有抽象方法,但是如果一个类中有一个方法是抽象的,那么这个 类就一定是抽象类。
package com.bdit; /* 抽象类 */ public class Test3 { public static void main(String[] args) { ChangShape cs = new ChangShape(10, 20); cs.area(); cs.zhouChang(); } } //定义抽象类 abstract class Shape { int height; int width; public Shape(int height, int width) { this.height = height; this.width = width; } public void display() { System.out.println("抽象类中的普通方法"); } public static void t1() { System.out.println("抽象类中的静态方法"); } //面积 public abstract void area(); //周长 public abstract void zhouChang(); } //子类 class ChangShape extends Shape{ public ChangShape(int h, int w) { super(h, w); } public void area() { System.out.println("长方形的面积:" + (super.height * super.width)); } public void zhouChang() { System.out.println("长方形的周长:" + (super.height + super.width) * 2); } }接口,是 Java 语言中一种引用类型,是方法的集合,也是一种标准。如果说类的内部封装了 成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK7 之前)、默认方法和静态方法(JDK8),私有方法(JDK9)。
【接口,就是用来否则定义公共的方法或者说标准的】
接口的定义,它与定义类方式类似,但是使用 interface 关键字,它也会被编译成 class 文件,但一定要明确它并不是类,而是另外一种引用数据类型。
接口的使用,它不能创建对象,但是可以被实现(implements),类似于被继承。一个实现接 口的类(可以看作是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以 调用方法了,否则它必须是一个抽象类。
●接口中不能有构造方法,也不能创建接口的对象
●接口中可以有抽象方法,只有方法的声明,没有方法体
●接口中所有的抽象方法,只能使用 public 来修饰,就算不加访问修饰符,默认也是 public
●接口中定义的变量,都是静态的常量,而且完整的修饰语法: public static final 数据类型 常量名=常量值; 接口中可以简写,直接写 数据类型 常量名=常量值;
●接口需要由类来实现,而且一个类可以实现多个接口,接口之间用逗号分隔
●接口可以弥补 java 中的单一继承,也就是说接口可以实现多继承
语法格式:
public interface 接口名称{ //常量 //抽象方法 //默认方法 //静态方法 //私有方法 }接口命名也是采用大驼峰命名法
抽象方法:使用 abstract 关键字修饰,但是也可以省略,没有方法体,该方法供子类来实现。
package com.bdit; //定义抽象方法的接口 public interface InterfaceDemo1 { public abstract void method1(); public void method2(); void method3(); }默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写 静态方法:使用 static 修饰,供接口直接调用
package com.bdit; //默认方法和静态方法 public interface InterfaceDemo2 { public default void d1(){ System.out.println("接口中的默认方法"); } public static void s1(){ System.out.println("接口中的静态方法"); } }私有方法:使用 private 修饰,供接口中的默认方法或者静态方法调用
package com.bdit; // 私有方法 public interface InterfaceDemo3 { private void p1() { System.out.println("接口中的私有方法"); } private static void p2() { System.out.println("接口中的私有静态方法"); } }实现的概述
类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口 的子类,实现类类似继承,格式类似,只是关键字不同,实现接口使用 implements 关键字。 ●判断继承关系是否成立,可以通过 “is-a”的方式 ●判断实现类和接口的关系,可以通过“like-a”的方式 ●实现接口也是一种特殊的继承关系
非抽象子类实现接口: ●必须重写接口中所有抽象方法 ●继承了接口的默认方法,即可以直接调用,也可以重写
实现格式:
访问修饰符 class 类名 implements 接口名{ }实现类必须全部实现
package com.bdit; public class Impl01 implements InterfaceDemo1 { public static void main(String[] args) { Impl01 impl01 = new Impl01(); impl01.method1(); impl01.method2(); impl01.method3(); } @Override public void method1() { System.out.println("方法 1"); } @Override public void method2() { System.out.println("方法 2"); } @Override public void method3() { System.out.println("方法 3"); } }可以继承,可以重写,二选一,但是只能通过实现类的对象来调用
1.继承默认方法,代码如下:
package com.bdit; public class Impl02 implements InterfaceDemo2 { public static void main(String[] args) { Impl02 impl02 = new Impl02(); impl02.d1(); InterfaceDemo2.s1(); } }2.重写默认方法
package com.bdit; public class Impl02 implements InterfaceDemo2 { public static void main(String[] args) { Impl02 impl02 = new Impl02(); impl02.d1(); InterfaceDemo2.s1(); } public void d1() { System.out.println("这是对接口默认方法的重写"); } }静态与类中静态方法使用一样,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用。
package com.bdit; public class Impl03 implements InterfaceDemo2{ public static void main(String[] args) { InterfaceDemo2.s1(); } }●私有方法:只有默认方法可以调用 ●私有静态方法,默认方法和静态方法均可调用
如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私 有方法中,供默认方法调用。从设计的角度讲,私有的方法时对默认方法和静态方法的辅助。
package com.bdit; // 私有方法 public interface InterfaceDemo3 { private void p1() { p2(); System.out.println("接口中的私有方法"); } private static void p2() { System.out.println("接口中的私有静态方法"); } public default void d2() { p1(); } }在继承中,一个类只能继承一个父类。对接口而言,一个类可以实现多个接口,这叫接口的 多实现。并且一个类能继承一个父类,还可以同时实现多个接口。
语法格式:
访问修饰符 class 类名 [extends 父类] implements 接口 1,接口 2,接口 3,…{ }[]:表示可选操作
接口中,有多个抽象方法时,实现类必须重写所有的抽象方法,如果抽象方法有重名,只需要重写一次。
package com.bdit; public class Impl04 implements InterfaceDemo4, InterfaceDemo5 { public static void main(String[] args) { Impl04 impl04 = new Impl04(); impl04.t1(); impl04.t2(); } @Override public void t1() { System.out.println("t1"); } @Override public void t2() { System.out.println("t2"); } }接口中,有多个默认方法时,实现类都可以继承使用,如果默认方法有重名,必须要重写一次。
package com.bdit; public interface InterfaceDemo4 { public void t1(); public void t2(); public default void display() { System.out.println("demo4 中的默认方法"); } } package com.bdit; public interface InterfaceDemo5 { public void t1(); public void t2(); public default void display() { System.out.println("demo5 中的默认方法"); } } package com.bdit; public class Impl04 implements InterfaceDemo4, InterfaceDemo5 { public static void main(String[] args) { Impl04 impl04 = new Impl04(); impl04.t1(); impl04.t2(); } @Override public void t1() { System.out.println("t1"); } @Override public void t2() { System.out.println("t2"); } @Override public void display() { System.out.println("实现默认方法"); } }接口中,存在同名的静态方法并不会冲突,原因是只能通过各自的接口名访问静态方法。
当一个类,即继承了一个父类,又实现了若干个接口时,父类中的成员方法与接口中的默认 方法重名,子类就近选择执行父类的成员方法。
一个接口能继承多个接口,接口的继承也是使用 extends 关键字,而且多个接口之间使用逗 号隔开即可。子接口继承了父接口的方法,如果某个类实现了子接口,就要实现子接口以及 父接口中所有的抽象方法。【如果父接口中的默认方法有重名的,那么子接口需要重写一次】。
package com.bdit; public class Test1 { public static void main(String[] args) { } } //接口 interface InterfaceDemo6 { int NUM = 100;//public static final public void t1(); public void t2(); public default void d1() { System.out.println("默认方法 1"); } } //接口 interface InterfaceDemo7 { String name = "张三"; public void t3(); public default void d1() { System.out.println("默认方法 2"); } } //子接口 interface SInterfaceDemo1 extends InterfaceDemo6, InterfaceDemo7 { @Override default void d1() { } } class MyImpl01 implements SInterfaceDemo1 { @Override public void t1() { System.out.println(InterfaceDemo7.name); System.out.println(InterfaceDemo6.NUM); } @Override public void t2() { } @Override public void t3() { } }