JAVA
学习(十)之接口和抽象类
目录
抽象类
抽象类的小结如下:
1、抽象类和抽象方法都必须用abstract修饰符来修饰,抽象方法不能有方法体
2、抽象类有构造器,但不能直接被实例化,要创建对象涉及向上转型,主要是用于被其子类调用
3、抽象类中可以没有抽象方法,但是有抽象方法的类必定是抽象类
4、抽象类中可以包含静态方法
5、抽象类不能用final修饰
6、抽象类不能用private修饰
7、抽象类也是类,一样是用来继承的,接口与类才是实现关系
8、外部抽象类不能用Static修饰,但内部的抽象类可以使用static声明
9、 抽象类可以继承抽象类,抽象派生类可以覆盖基类的抽象方法,也可以不覆盖。如果不覆盖,则其具体非抽象派生类必须覆盖它们
10、 抽象类可以实现接口,可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法
抽象类组成分析
概述抽象类之前我觉得很有必要先来从普通类下手。普通类可以包含构造方法、普通方法、static方法、常量和变量等内容。而抽象类也是类,而且是一个特别的类,抽象类是指在普通类的结构里面选择性的增加抽象方法并以abstract关键字将该类修饰,是的,每个抽象类不管有没有抽象方法在其类结构中,abstract关键字非加不可。
package com.gx.abstractdemo;
/**
* Animal 动物抽象类 抽象类不能创建实例,只能当成父类来被继承。
* 1、抽象类必须使用abstract修饰符来修饰,
* 抽象方法也必须使用abstract修饰符来修饰,
* 抽象方法不能有方法体。
* 2、抽象类不能被实例化,
* 无法使用new关键字来调用抽象类的构造器创建抽象类的实例。
* 3、抽象类可以包含成员变量、
* 方法(普通方法和抽象方法都可以)、
* 构造器、初始化块、
* 内部类(接 口、枚举)5种成分。
* 4、抽象类的构造器不能用于创建实例,主要是用于被其子类调用。
* 5、抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类
* 6、abstract static不能同时修饰一个方法 (abstract方法没有方法体不能直接调用,static方法可以直接调用,冲突)
*/
public abstract class Animal {
// 成员变量
protected int weight = 0;
static {
System.out.println("static初始化块");
}
{
System.out.println("初始化块");
}
// 构造器
public Animal() {
System.out.println("Animal 的无参构造器");
}
public Animal(int weight) {
this.weight = weight;
System.out.println("Animal 的有参构造器");
}
// 定义一个普通方法 休息
public void sleep() {
System.out.println("休息");
}
//抽象方法没有方法体
public abstract void running();
public abstract String say(String str);
}
抽象类中不能共存的关键字
不能与抽象类(abstract)共存的关键字主要有三个,分别是final、private、static
1、final
final:抽象类不能用final修饰。因为抽象类一定要被abstract修饰,而且抽象类一定要被继承否则该抽象类无意义。而被final修饰的类不能被继承,也就是说不能有子类,所以二者冲突不能同时使用!
2、private
private: 抽象类不能用private修饰,只能用public或protected。首先要明确一点:被abstract修饰的类是为了让非抽象子类看到并强制重写。如果抽象类中有私有的抽象方法,那么该抽象方法不被子类所知,就无法被复写。 而抽象方法出现的就是需要被复写。
3、static
关于static我觉得还是很有必要说下
static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。众所周知,抽象方法是没有方法体的,可见运行也就没意义了。但是有种情况还是值得谈一谈,可能面试的时候会特别加分!那就是虽然外部抽象类不能用Static修饰,但内部的抽象类却可以使用static声明,如下
//定义一个抽象类A
abstract class A{
//定义一个内部抽象类B
static abstract class B{
//static定义的内部类属于外部类
public abstract void saoMethod();
}
}
class C extends A.B{
public void saoMethod(){
System.out.println("======saoMethod方法执行了======");
}
}
public class StaticDemo {
public static void main(String[] args) {
A.B ab = new C();//向上转型
ab.saoMethod();
}
}
运行结果: ======saoMethod方法执行了======
有的童鞋就懵逼了, C extends A.B
是啥骚操作啊,还能这样玩?是的,当使用static
声明的内部抽象类相当于一个外部抽象类,继承的时候使用“外部类.内部类
”的形式表示类名称。这种骚操作属实是稳中带皮。
并且当修饰属性时候我们在外面调用时除去方法的特性外,还具有一点就是我们的公用的是一个值
看个例子便与理解
package sort.text;
public class text01 {
public static int str;
}
package sort.text;
public class main {
public static int text01(){
return text01.str;
}
public static void main(String[] args) {
text01.str = 12;
System.out.println(12);
System.out.println(text01());
}
}
12
12
说白了抽象类的功能就是一个类定义模板的功能。
接口类
java
中接口定义
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。只关心是否具有做某件事的能力(只有方法名),而不关心具体如何去做(没有方法体)
是一种约定,是一种能力。
接口只定义实现类要用到的方法,但是方法的具体实现完全取决于实现类。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
在软件工程中,许多情况是,不同的程序员群体必须同意一份"合同",说明他们的软件是如何相互作用的。每个组应该能够编写代码,而不知道其他组的代码是如何编写的。一般来说,接口就是这样的合同。
例如,想象一个未来社会,计算机控制的机器人汽车在没有人工操作的情况下将乘客运送到城市街道。汽车制造商编写软件(Java,当然),操作汽车停止,启动,加速,左转,等等。另一个工业集团,电子制导仪器制造商,制造接收GPS(全球定位系统)定位数据和交通状况无线传输的计算机系统,并利用这些信息驾驶汽车。
汽车制造商必须发布行业标准界面,详细说明可以调用哪些方法来移动汽车(任何汽车,从任何制造商)。然后,指导制造商可以编写软件,调用界面中描述的方法来命令汽车。两个工业集团都不需要知道其他组的软件是如何实现的。事实上,每个组都认为其软件具有高度专有性,并保留随时修改它的权利,只要它继续遵守已发布的界面。
java
的使用说明
接口和类
接口与类相似点
- 一个接口可以有多个方法。
- 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
- 接口的字节码文件保存在 .class 结尾的文件中。
- 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口与类的区别
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。单继承,多实现。
抽象类和接口的区别
- \1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- \2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- \3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- \4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
interface
特性
- 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
- 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
- 接口中的方法都是公有的。
- 接口中的方法默认使用 public abstract 修饰。
- 接口中的属性默认使用的 public static final 修饰。
- 接口中没有构造方法。
- 一个类只能继承一个父类,但是可以实现多个接口。
- 一个类在实现接口时,必须实现接口中所有的抽象方法;除非该类为抽象类。
- 接口可以继承接口,类在实现该接口时必须实现其父接口中所有的抽象方法。
- 一个类可同时继承类和实现接口。
interface
的实现
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
实现一个接口的语法,可以使用这个公式:
...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...
java
的声明
接口的声明语法格式如下:
[可见度] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
Interface关键字用来声明一个接口。下面是接口声明的一个简单例子。
/* 文件名 : NameOfInterface.java */
import java.lang.*;
//引入包
public interface NameOfInterface
{
//任何类型 final, static 字段
//抽象方法
}
java
的接口使用
public interface TextInterface {
int turn(int direction,
double radius,
double startSpeed,
double endSpeed);
int changeLanes(int direction,
double startSpeed,
double endSpeed);
int signalTurn(int direction,
boolean signalOn);
int getRadarFront(double distanceToCar,
double speedOfCar);
int getRadarRear(double distanceToCar,
double speedOfCar);
}
那我们的interface
如何使用呢
请注意,方法签名没有支架,并且用分号终止。
要使用界面,请编写一个实现界面的类。当可执行类实现接口时,它为界面中声明的每种方法提供了一个方法主体。例如
public class InterfaceTextClass implements TextInterface{
@Override
public int turn(int direction, double radius, double startSpeed, double endSpeed) {
return 0;
}
@Override
public int changeLanes(int direction, double startSpeed, double endSpeed) {
return 0;
}
@Override
public int signalTurn(int direction, boolean signalOn) {
return 0;
}
@Override
public int getRadarFront(double distanceToCar, double speedOfCar) {
return 0;
}
@Override
public int getRadarRear(double distanceToCar, double speedOfCar) {
return 0;
}
}
在上面的机器人汽车示例中,将实现接口的是汽车制造商。当然,雪佛兰的实施将与丰田大不相同,但两家制造商将坚持相同的界面。指导制造商,谁是界面的客户,将建立系统,使用GPS数据的汽车的位置,数字街道地图和交通数据来驾驶汽车。这样,制导系统将调用接口方法:转弯、换车道、刹车、加速等。
如果我们不进行实现的话就后报错,报错信息如下
Class 'InterfaceTextClass' must either be declared abstract or implement abstract method 'getRadarRear(double, double)' in 'TextInterface'
机器人汽车示例显示一个界面被用作行业标准*应用程序编程接口 (API)。*API 在商业软件产品中也很常见。通常,公司销售包含其他公司希望在其软件产品中使用的复杂方法的软件包。例如,一套数字图像处理方法将出售给制作最终用户图形程序的公司。图像处理公司编写其类以实现界面,该界面向客户公开。然后,图形公司使用界面中定义的签名和返回类型调用图像处理方法。虽然图像处理公司的 API 已公开(对客户),但其 API 的实施实际上仍作为严密保密的秘密进行,只要它继续实施其客户所依赖的原始界面,它以后可能会修改实施。
重写时的注意事项
重写接口中声明的方法时,需要注意以下规则:
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
在实现接口的时候,也要注意一些规则:
- 一个类可以同时实现多个接口。
- 一个类只能继承一个类,但是能实现多个接口。
- 一个接口能继承另一个接口,这和类之间的继承比较相似。
interface
的extends
一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。
下面的Sports接口被Hockey和Football接口继承:
// 文件名: Sports.java
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
// 文件名: Football.java
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}
// 文件名: Hockey.java
public interface Hockey extends Sports
{
public void homeGoalScored();
public void visitingGoalScored();
public void endOfPeriod(int period);
public void overtimePeriod(int ot);
}
Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。
相似的,实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。
interface
的多继承
在Java中,类的多继承是不合法,但接口允许多继承。
在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示:
public interface Hockey extends Sports, Event
以上的程序片段是合法定义的子接口,与类不同的是,接口允许多继承,而 Sports及 Event 可以定义或是继承相同的方法
我们可以再来看一个例子,源代码如下
//TextInterface02.java
public interface TextInterface02{
int text();
}
//TextInterface.java
public interface TextInterface {
int turn(int direction,
double radius,
double startSpeed,
double endSpeed);
int changeLanes(int direction,
double startSpeed,
double endSpeed);
int signalTurn(int direction,
boolean signalOn);
int getRadarFront(double distanceToCar,
double speedOfCar);
int getRadarRear(double distanceToCar,
double speedOfCar);
}
//InterfaceTextClass.java
public class InterfaceTextClass implements TextInterface02,TextInterface{
@Override
public int turn(int direction, double radius, double startSpeed, double endSpeed) {
return 0;
}
@Override
public int changeLanes(int direction, double startSpeed, double endSpeed) {
return 0;
}
@Override
public int signalTurn(int direction, boolean signalOn) {
return 0;
}
@Override
public int getRadarFront(double distanceToCar, double speedOfCar) {
return 0;
}
@Override
public int getRadarRear(double distanceToCar, double speedOfCar) {
return 0;
}
@Override
public int text() {
return 0;
}
}
interface
标记
最常用的继承接口是没有包含任何方法的接口。
标记接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。
标记接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。
例如:
public interface TextInterface {
//todo something
}
其中interface
极为标记符
没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:
-
建立一个公共的父接口:
正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。
-
向一个类添加数据类型:
这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。
interface
和extends
区别
下面比较一下两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的可以有非抽象方法,比如deaflut方法
4.抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然 eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5.抽象类中可以包含静态方法,接口中不能包含静态方法
6.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
7.一个类可以实现多个接口,但只能继承一个抽象类。
有抽象方法一定是抽象类吗?抽象类一定有抽象方法吗?
有抽象方法不一定是抽象类,也可能是接口。抽象类不一定有抽象方法,可以有非抽象的普通方法。