抽象类

  在面向对象的概念中,所有的对象都是通过类来表述的,但并不是所有的类都能够完整的描绘对象,如果一个类中没有包含足够的信息来描绘一类具体的对象,这样的类就是抽象类.抽象类往往用来表征对问题领域进行分析,设计中的出的抽象概念.  是对一系列看上去不同,但本质上相同的具体概念的抽象.例如:定义一个平面图形Shape . 任何平面图形都有周长和面积,在Shape类中定义两个方法用于计算图形的面积和周长

  

public class Shape{
//计算圆的面积
public void callArea(){}
//计算圆的周长
public void callPerimeter(){}
}

  通过分析,可以发现平面图形领域存在着园,三角形,长方形等这样一些具体的图形,计算它们的面积和周长是不同的,因此在Shape类中无法统一定义callArea()和callPerimeter()方法 , 但是它们都属于平面领域,都需要这两个方法.

  有事定义类的"骨架",对其共同行为提供规范,但并不实现,具体的实现将放在它的子类来完成.这种骨架类在java中叫做 抽象类,通过abstract关键字来描述

[访问符] abstract class 类名{
[访问符] abstract <返回类型> 方法名([参数列表]);
}

  定义抽象类需要注意一下几点:

  1、abstract放在class前面,指明该类是抽象类;

  2、abstract放在方法声明中,则该方法是抽象方法,抽象方法没有方法体,即未实现;

  3、一个抽象类可以含有多个抽象方法,也可以含有已经实现的方法;

  例子:抽象类的定义与使用

package 抽象类;
//定义图形抽象类
public abstract class Shape {
double dim;
public Shape(double dim) {
this.dim = dim;
}
//抽象方法,获得面积
public abstract double callArea();
//抽象方法,获得周长
public abstract double callPerimeter();
}

  上面的例子是定义了一个抽象类Shape,并且声明了两个抽象方法callArea()和callPerimeter(),这两个抽象方法没有方法体.在这里需要注意,抽象方法是没有方法体,它和空方法是两个不同的概念

    public abstract void callAreas(); //抽象方法,没有 {}括起来的方法体
public void callArea() {}; //空方法,有{}括起来的方法体,但方法体中没有任何语句

  抽象类还可以包含具体数据和具体方法,也可以包括构造方法,定义抽象类的目的是提供可由其子类共享的一般形式,子类可以根据自身需要扩展抽象类

  例子:定义Shape抽象类的一个子类Circle来演示抽象类的使用

package 抽象类;

public class Circle extends Shape{
public Circle(double dim) {
super(dim);
}
//实现抽象方法callArea();
public double callArea() {
//返回圆的面积
return 3.14 * dim * dim;
}
public double callPerimeter() {
//返回圆的周长
return 2 * 3.14 * dim;
}
public static void main(String args[]) {
//声明一个Shape对象,指向实现它的子类对象
Shape shape = new Circle(10);
//调用callArea()求出圆的面积并输出
System.out.println("圆的面积为:" + shape.callArea());
//调用callPerimeter()求出圆的周长并输出
System.out.println("圆的周长为:" + shape.callPerimeter());
}
}

  执行结果:

圆的面积为:314.0
圆的周长为:62.800000000000004

  从执行的结果来看,当调用Shape类型的变量shape时,实际上是调用了Circle类型对象的方法,即通过基类调用派生类的方法,这也是一种多态的体现  

  一个类在继承抽象类时,如果没有实现所有抽象类方法,那么该类也必须声明为抽象类:

  例子:

  

package 抽象类;

public abstract class Square extends Shape{
public Square(double dim) {
super(dim);
}
//实现抽象方法callArea()
public double callArea() {
return dim * dim;
}
//没有实现抽象方法callPerimeter(),Square类中仍然包含抽象方法,所以Square依然是抽象类
}

  注意:1、抽象类不能实例化,既不能直接new一个抽象类,但可以指向一个实现它的子类对象

     2、抽象方法没有方法体,抽象类提供了子类的规范模板,抽象方法必须在子类中给出具体实现。

     3、abstract不能与final同时修饰一个类,abstract不能和static、private、final或者native并列修饰同一方法。

接口

  java只支持单一继承,不支持多重继承,即一个类只能继承另一个类,不能继承两个或两个以上的类。单一继承限制了类的多重体现,为了弥补这一缺陷,模仿C++中的多重继承,java语言的设计者提出了一种折中的解决办法,即使用接口:一个类可以实现多个接口。接口的引入,使java拥有了强大的面向对象编程能力,为面向接口编程提供了广泛的扩展空间 。

定义接口

<访问符> interface 接口名{
[访问符] <返回类型> 方法名([参数列表])
......
}

  1、interface是定义接口的关键字;

  2、接口是一种特殊的抽象类型,是对抽象类的进一步强化,是方法声明和常量的定义集合,因此接口中的方法都没有方法体,即接口中的方法都是未实现的方法,且不需要abstract关键字进行指明

  例子:演示接口的定义和使用

package 接口;

public interface MyInterface {
public void add(int x, int y);
public void volume(int x, int y, int z);
}

  上述代码定义了一个接口MyInterface,在接口 中声明了两个方法,但这两个方法都没有实现,与抽象类中的抽象方法类似,接口中的方法没有方法体,当然也可以定义既包含常量也包含方法的接口

package 接口;

public interface MultiInterface {
//在接口中定义一个静态常量PI
public static final double PI = 3.1415926;
public void callArea();
}

  在定义接口的时候,接口中的所有方法和常量自动定义为public,可以省略public关键字.

实现接口

   实现接口的语法格式如下:

<访问符> class 类名 implements 接口名[接口列表]{
}

  1、implement关键字可以实现多个接口,接口之间用逗号隔开。

  2、一个类实现接口时,必须实现接口中定义的所有方法,除非将该类定义为抽象类。

  例子:定义一个类Myclass实现MyInterface接口,演示接口的实现过程

package 接口;

public class MyClass implements MyInterface{
//实现接口中的add()方法
public void add(int x, int y) {
System.out.println("x + y = " +(x+y));
}
//实现接口中的volume()方法
public void volume(int x, int y, int z) {
System.out.println("X * y * z = " + (x*y*z));
} public static void main(String args[]) {
//声明一个MyInterface对象,指向MyClass类的对象
MyInterface mi = new MyClass();
//调用add方法,传递两个参数
mi.add(1, 2);
//调用volume()方法,传递三个参数
mi.volume(1, 2, 3);
}
}

  执行结果为:

x + y = 3
X * y * z = 6

  上面代码中Myclass类实现MyInterface接口 ,并实现该接口中定义的add()和volume()方法.在main()方法中,先声明一个MyInterface接口类型的变量mi  ,  new一个实现该接口的Myclass类的对象,并将其引用赋值给mi  ,最后通过mi调用方法.

  与抽象类一样,接口是一种更加虚拟的类结构,因此不能对接口实例化

  接口与抽象类有很多相似之处,但要注意这几点区别:

  1、抽象类中可以有已经实现的方法,而接口不能有

  2、接口中定义的变量默认为public static final 型,且必须赋初值,其实现类中不能重新定义,也不能改变其值,即接口中定义的变量都是最终的静态常量;而抽象类中定义的变量 和普通类一样,默认是friendly,其实现类合一重新定义,也可以根据需要改变其值

  3、接口中定义的方法默认都是public修饰,也只能是public,而抽象类则是缺省的friendly

instanceof运算符

  java的多态性机制导致了引用变量的声明类型和其实际类型引用的类型可能不一致,在结合动态方法调度到机制可以得出以下结论:声明为同种类型的两个引用变量调用同一个方法时也有可能会有不同的行为.为了更准确的鉴别一个对象的真正类型,java语言引入了instanceof操作符.其实使用的格式如下:

<引用类型变量> instanceof <引用类型>

   该表达式为boolean类型的表达式,当instanceof左侧的引用类型变量所引用对象的实际类型是其右侧给出的类型或其子类类型时,整个表达式的结果为true,否则为false

  举例:演示instanceof的用法

package instanceof运算符;

//定义IBase接口
public interface IBase {
public void print();
}
package instanceof运算符;

//定义类Derive类实现IBase接口
public class Derive implements IBase{
int b;
public Derive (int b) {
this.b = b;
}
public void print() {
System.out.println("In Derive!");
}
}
package instanceof运算符;

//定义Derive的子类Derive1
public class Derive1 extends Derive{
int c;
public Derive1(int b, int c) {
super(b);
this.c = c;
}
public void print() {
System.out.println("In Derive1!");
}
}
package instanceof运算符;

public class InstanceofDemo {
//判断对象类型
public static void typeof(Object obj) {
if(obj instanceof Derive) {
Derive derive = (Derive) obj;
derive.print();
}else if(obj instanceof Derive1) {
Derive1 derive1 = (Derive1) obj;
derive1.print();
}
}
public static void main(String[] args) {
IBase b1 = new Derive(4);
IBase b2 = new Derive1(4,5);
System.out.print("b1 is:");
//调用typeof()判断b1
typeof(b1);
System.out.print("b2 is:");
//调用typeof()判断b2
typeof(b2);
}
}

  执行结果:

b1 is:In Derive!
b2 is:In Derive1!

  上述代码中定义了一个IBase接口,Derive类实现IBase接口,Derive1是Derive的子类.在InstanceofDemo类中定义了一个静态方法typeof(),该方法使用instanceof来判断对象的类型,并调用其相应的方法,main()方法中定义了两个Base类型的对象分别是b1和b2所引用的实际对象类型.

  从结果不难看出,instanceof运算符能够鉴别出实际对象类型,并实现相应方法的调用,此种方法模拟了方法的动态调用机制.但这种做法被认为没有很好的利用面向对象中的多态性而是采用了结构化编程模式

  注意:在大多数情况下不推荐使用此用算符,应当利用累的多态.

对象转换

  在基本数据类型之间进行相互转换的过程中,有些转换可以自行完成,而有些转换必须通过强制转换,对于引用类型,也从在相互转换机制,也分为自动转换和强制转换

    自动转换:子类转换成为父类,或者实现类转换接口,转换自动完成

    强制转换:父类转换成为子类,或者接口转换成实现类,必须使用强制转换.

Person p = new Teacher(); //创建一个Teacher对象,把引用赋予Person类型变量p
Teacher t = (Teacher) p; //把变量p强制转换成Teacher类型变量

  注意:无论自动转换还是强制转换,都只能用在有继承关系的对象之间.并不是任意类型都可以转换,只有多态的情况下,原本就是子类类型的对象被声明为父类的类型,才可以通过造型恢复其"真实面目",否则将编译失败.

java抽象类,接口(接口定义,实现接口,instanceof运算符,对象转换)的更多相关文章

  1. IEnumerator<TItem>和IEnumerator Java 抽象类和普通类、接口的区别——看完你就顿悟了

    IEnumerable 其原型至少可以说有15年历史,或者更长,它是通过 IEnumerator 来定义的,而后者中使用装箱的 object 方式来定义,也就是弱类型的.弱类型不但会有性能问题,最主要 ...

  2. java中接口的定义和接口的实现

    1.接口的定义 使用interface来定义一个接口.接口定义同类的定义类似,也是分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成.定义接口的基本格式如下: [修饰符] interfa ...

  3. java 子接口中定义与父接口相同的方法

    今天碰到一个很有意思的问题,在java中如果子接口中定义了与父接口中已经有的方法会发生什么事情呢?比如: interface IRunnable extends Runnable{ void run( ...

  4. 【Java学习笔记之二十三】instanceof运算符的用法小结

    instanceof运算符用法 运算符是双目运算符,左面的操作元是一个对象,右面是一个类.当左面的对象是右面的类创建的对象时,该运算符运算的结果是true,否则是false 说明: (1)一个类的实例 ...

  5. Java -- 封装访问控制级别,包, instanceof 运算符, 初始化块

    1. 可以用 package name1.name2; 显式的定义包名, *.class文件位置应该对应包 name1 name2 的目录下. 2. instanceof 运算符 Object obj ...

  6. Java——抽象类、接口

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  7. java8函数式接口详解、函数接口详解、lambda表达式匿名函数、方法引用使用含义、函数式接口实例、如何定义函数式接口

    函数式接口详细定义 函数式接口只有一个抽象方法 由于default方法有一个实现,所以他们不是抽象的. 如果一个接口定义了一个抽象方法,而他恰好覆盖了Object的public方法,仍旧不算做接口的抽 ...

  8. 【48】java抽象类和接口的定义和区别

    首先看看他们的区别: 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法. 抽象类与接口是Java语言中对抽象概念进行定义的两种机制,正是由于他们的存在才赋予java强大的面向对象的能力. ...

  9. Java 基础 面向对象: 接口(interface )概念 以及接口之练习3 -定义一个接口用来实现两个对象的比较并 判断instanceof是否为同类

    接口(interface )概念概念笔记 及测试代码: /** 面向对象: 接口(interface ) 是与类并行的一个概念: * 1.接口可以看成一个特殊的抽象类,它是常量与抽象方法的一个集合 * ...

随机推荐

  1. 009-2010网络最热的 嵌入式学习|ARM|Linux|wince|ucos|经典资料与实例分析

    前段时间做了一个关于ARM9 2440资料的汇总帖,很高兴看到21ic和CSDN等论坛朋友们的支持和鼓励.当年学单片机的时候datasheet和学习资料基本都是在论坛上找到的,也遇到很多好心的高手朋友 ...

  2. vue踩坑 导出new Vue.Store首字母要大写

    控制台报错  : Uncaught TypeError: vuex__WEBPACK_IMPORTED_MODULE_6__.default.store is not a constructor 根据 ...

  3. Genymotion模拟器安装搜狗输入法

    Genymotion模拟器默认没有中文输入法,如果在一些调试中涉及到需要输入中文则必须需要安装中文输入法. 这里以搜狗输入法为例. 这里需要注意一下几点就行: 百度下载一个搜狗输入法,需要特别注意的是 ...

  4. 《计算机网络 自顶向下方法》 第2章 应用层 Part1

    常见的应用层协议有哪些?  HTTP(HyperText Transfer  Protocol):超文本传输协议 FTP(File Transfer Protocol):文件传输协议 SMTP(Sim ...

  5. vim编辑中断后,重新编辑的警告删除

    使用vim 编辑,遇到突然中断,比如ssh远程时断网了. 如果再次ssh连接,重新vim 打开之前在编辑的文件,会有类似如下的警告 这是因为vim会在被编辑的目录下新建一个名为.filename.sw ...

  6. Unittest框架的从零到壹(一)

    前言 Python中有非常多的单元测试框架,如unittest.pytest.nose.doctest等,Python2.1及其以后的版本已经将unittest作为一个标准模块放入Python开发包中 ...

  7. Redis面试题详解:哨兵+复制+事务+集群+持久化等

    Redis主要有哪些功能? 1.哨兵(Sentinel)和复制(Replication) Redis服务器毫无征兆的罢工是个麻烦事,如何保证备份的机器是原始服务器的完整备份呢?这时候就需要哨兵和复制. ...

  8. 小程序api的promise封装

    微信小程序和支付宝小程序的api封装方法是一样的,都是外部新建一个js,使用module.exports导出,要注意的是,最好使用post请求,虽然get请求没什么不好,主要是好修改.这里使用的MD5 ...

  9. 解决 bash cd too many arguments 报错

    解决 bash: cd: too many arguments 本来想着用git bash进入文件夹,但是文件夹名称中带有空格,例如:my blog,导致出错. 在查找资料后,找到一种并不可行的方案, ...

  10. Photoshop CS2软件下载与安装教程

    Photoshop CS2精简版下载地址: 链接:https://pan.baidu.com/s/1ryJPLuKG_MixWjGJgLebOg提取码:nzz9 软件介绍: Photoshop主要处理 ...