抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是并不是所有的类都是用来描绘对象的.
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
比如:如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形 这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。

抽象方法:一种特殊的方法,它只有声明,而没有具体的实现(无方法体)。抽象方法的声明格式为:

abstract void f();

抽象方法必须用abstract关键字进行修饰。abstract 只能修饰类或类中的成员方法,不能修饰属性。被修饰的类或方法分别称作抽象类或抽象方法。其中抽象方法不能有方法体,而抽象类不能实例化,如果一个类含有抽象方法,则这个类一定为抽象类,抽象类必须在类前用abstract关键字修饰。当然,抽象类也可以没有抽象方法。

abstract class Test1{abstract void f();//正确,  抽象方法不能有方法体abstract void g(){;}//编译错,  抽象方法不能有方法体void h();//编译错,  非抽象类必须有方法体
}

【注意】:abstract 不能修饰最终方法、静态方法或构造函数,因为这三类方法都不能被子类重写。

abstract class Test2{abstract Test2();//编译错,  构造函数不能被abstract修饰abstract final void f();编译错,  final方法不能被abstract修饰abstract static void g();编译错,  静态方法不能被abstract修饰
}
  • 抽象类是契约的重量级应用方式
  • 接口是契约的轻量级应用方式

接口

Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类,既接口中的方法必须全部是抽象方法。
特点:

  • 就像一个类一样,一个接口也能够拥有方法和属性,但是在接口中声明的方法默认是抽象的。(即只有方法标识符,而没有方法体)。
  • 接口指明了一个类必须要做什么和不能做什么,相当于类的蓝图。
  • 一个接口就是描述一种能力,比如“运动员”也可以作为一个接口,并且任何实现“运动员”接口的类都必须有能力实现奔跑这个动作(或者implement move()方法),所以接口的作用就是告诉类,你要实现我这种接口代表的功能,你就必须实现某些方法,我才能承认你确实拥有该接口代表的某种能力。
  • 如果一个类实现了一个接口中要求的所有的方法,然而没有提供方法体而仅仅只有方法标识,那么这个类一定是一个抽象类。(必须记住:抽象方法只能存在于抽象类或者接口中,但抽象类中却能存在非抽象方法,即有方法体的方法。接口是百分之百的抽象类)。

为什么要用接口:

  • 接口被用来描述一种抽象。
  • 因为Java不像C++一样支持多继承,所以Java可以通过实现接口来弥补这个局限。
  • 接口也被用来实现解耦。
  • 接口被用来实现抽象,而抽象类也被用来实现抽象,为什么一定要用接口呢?- 接口和抽象类之间又有什么区别呢?原因是抽象类内部可能包含非final的变量,但是在接口中存在的变量一定是final,public, static的。

接口的实现:

[修饰符] interface 接口名 [extends 父接口列表]{[public][static][final]类型 成员常量 = 常量值[public][abstract]  返回类型  成员方法名([参数列表])
}

具体的例子:
我们知道,如果某个设备需要向电脑中读取或者写入某些东西,这些设备一般都是采用USB方式与电脑连接的,我们发现,只要带有USB功能的设备就可以插入电脑中使用了,那么我们可以认为USB就是一种功能,这种功能能够做出很多的事情(实现很多的方法),其实USB就可以看做是一种标准,一种接口,只要实现了USB标准的设备我就认为你已经拥有了USB这种功能。(因为你实现了我USB标准中规定的方法)。

//先声明USB接口:其中规定了要实现USB接口就必须实现接口规定实现的read( )和write( )这两个方法。
interface USB {void read();void write();
}//然后在写一个U盘类和一个键盘类,这两个类都去实现USB接口。(实现其中的方法)
class YouPan implements USB {@Overridepublic void read() {System.out.println("U盘正在通过USB功能读取数据");}@Overridepublic void write() {System.out.println("U盘正在通过USB功能写入数据");}
}class JianPan implements USB {@Overridepublic void read() {System.out.println("键盘正在通过USB功能读取数据");}@Overridepublic void write() {System.out.println("键盘正在通过USB功能写入数据");}
}//那么,现在U盘和键盘都实现了USB功能,也就是说U盘和键盘都能够调用USB接口中规定的方法,并且他们实现的方式都不一样。
public class Main {public static void main(String[] args) {//生成一个实现可USB接口(标准)的U盘对象YouPan youPan = new YouPan();//调用U盘的read( )方法读取数据youPan.read();//调用U盘的write( )方法写入数据youPan.write();//生成一个实现可USB接口(标准)的键盘对象JianPan jianPan = new JianPan();//调用键盘的read( )方法读取数据jianPan.read();//调用键盘的write( )方法写入数据jianPan.write();}
}

运行结果

U盘正在通过USB功能读取数据
U盘正在通过USB功能写入数据
键盘正在通过USB功能读取数据
键盘正在通过USB功能写入数据

【注意】:
1)接口不是类,接口中的方法都是抽象的,是没有方法体的没有构造函数,也不能实例化出对象。
2)一个类可以实现不止一个接口。
3)一个接口可以继承于另一个接口,或者另一些接口,接口也可以继承,并且可以多继承。
4)一个类如果要实现某个接口的话,那么它必须要实现这个接口中的所有方法。
5)接口中所有的方法都是抽象的和public的,所有的属性都是public,static,final的。
6)接口用来弥补类无法实现多继承的局限。
7)接口也可以用来实现解耦。

interface A{int x = 1;
}
interface B{int y = 2;
}
interface C extends A,B{int z = 3;
}//也称C为复合接口,它有A,B两个父接口

类中的特殊成员

——内嵌类型、初始化块、本地方法

内嵌类型

内嵌类型就是在类或接口内部定义的自定义类型,你包括内部类和内部接口。包围内部类或内部接口的类称为囿类型,或包围类型、外部类型等。

class A{   //A是包围类class B{   //内部类int x;}interface C{  //内部接口int y = 0;}
}
编译后将产生三个文件:A.class、A$B.class、A$C.classinterface X{   //X是包围接口class Y{   //内部类int x;}interface Z{   //内部接口int y = 0;}
}
编译后将产生三个文件:X.class、X$Y.class、X$Z.class

内部类存取规则:
1、作为囿类的成员,内部类可以存取囿类的其他所有成员,包括私有成员。
2、存取内部类及其成员必须要借助囿类或囿类的对象。显然,若囿类对象不能访问,那么内部类也不能访问。

public class Ch_4_27 {public static void main (String[] args) {Z a=new Z();Z.B ab=a.g();               //★★★借助囿类提供的方法获得内部类对象ab.h2();                     //★★★正确,可调用内部类的public方法//ab.y=6;                    //编译错,不能访问私有成员//A.B ab1=new A.B();       //编译错,不能以这种方式创建内部类对象//A.B ab1=new a.B();       //编译错,不能以这种方式创建内部类对象Z.B ab1=new Z().new B();  //★★★可用这种方式直接创建内部类对象Z.B ab2=a.new B();         //★★★可用这种方式直接创建内部类对象}
}
class Z{public class B{    //内部类定义private int y;private void h1(){x=10;} //内部类的成员方法可直接访问囿类的私有成员public void h2(){          //用于测试对外部内部类成员的调用System.out.println("Hi, Executed innerClass Method!"); Z.this.x=5;         //★★★此句显示:在内部类中如何引用囿类对象自身}}private int x;private void f(){//y=5;                       //编译错,囿类成员方法不能直接访问内部类成员B b=new B(); b.y=5;       //★★★只能借助内部类对象访问内部类的成员}public B g(){  return new B(); }//返回内部类的实例对象
}

1、内部类和囿类可以任意访问,没有权限上的限制。但囿类成员方法访问内部类成员,必须要借助内部类的对象,反之则无此限制。

2、在囿类外部,只要权限允许,也可以通过囿类对象访问内部类的成员,如ab.h2();。但是,ab.y=6则编译错误,因为权限不允许。

3、两种在外部获取内部类对象的方式:
1)通过囿类的public方法返回,如a.g();。
2)直接调用内部类的构造函数,但方式特殊,如new A().new B();或者a.new B();。

静态内部类
Java规定:若内部类中有静态成员,则该内部类必须是静态内部类。

class A{static class A1{int x; static int y;//正确}class A2{int a ;static int b; //编译错,非静态内部类中不能有静态成员}
}
A.A1.y = 10;//合法

测试静态类和非静态类

成员内部类(可以使用private、default、 protected、 public任意进行修饰。类文件:外部类$内部类.class)
a)非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)
i. 非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。
ii. 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
iii. 非静态内部类不能有静态方法、静态属性和静态初始化块。
iv. 外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例。
v. 成员变量访问要点:
1.内部类里方法的局部变量:变量名。
2.内部类属性: this.变量名。
3.外部类属性:外部类名.this.变量名。

public class TestInnerClass {public static void main(String[] args) {//创建内部类对象Outer.Inner inner = new Outer().new Inner();inner.show();}
}class Outer{private int age = 10;public void testOuter() {System.out.println("Outer.testOuter()");}class Inner{int age = 20;public void show() {int age = 30;System.out.println("外部类的成员变量age:"+Outer.this.age);System.out.println("内部类的成员变量age:"+this.age);System.out.println("局部变量age:"+age);}}
}

局部内部类和匿名内部类
成员方法中只有局部变量、常量、内部类相应地称作局部内部类。局部变量不能用权限属性、static、abstract等属性的修饰,局部内部类也是如此。局部内部类的作用范围,仅限于其所在的方法。

class A{public void f(){int x;class B{int a;public void g(){a = x;  //编译错误  局部内部类不能引用所在方法中定义的变量。因为局部变量x存于f()的栈空间,f运行结束x将自动销毁。但对象存在于堆空间,若允许存取x,将可能导致错误。}}//局部内部类B b = new B();}

没有名字的内部类成为匿名类

public class Ch_4_28{public static void main (String[] args) {A a=new A() {   //定义A的匿名子类(匿名的局部内部类) public void f(){System.out.println("匿名类.f()");}public void g(){;}     //可通过编译但无法使用};          //作为语句结束符的分号不能少,匿名类定义结束a.f();//  a.g();      //编译错,因为a是A类型,A中无g()方法}
}
class A{public void f(){ System.out.println("A.f()"); }
}

初始化块
初始化块就是在类中独立于成员方法之外的代码段,它没有名字,不带参数,无返回值。被static修饰就是静态初始化块,否则就是实力初始化块。初始化块的执行遵循以下规则:
1)初始块的执行顺序遵循其出现的次序。
2)实例初始化块先于构造函数。
3)静态初始化块在类中的初次加载时执行,仅执行一次,且先于实例初始化块。

public class Ch_4_29{public static void main(String[] args) {System.out.print("ppppp== ");new TestBlock(); new TestBlock(99);}
}class TestBlock {TestBlock (int x){System.out.print("1== ");}TestBlock (){System.out.print("2== ");}static {System.out.print("Static 3 == ");} //静态初始化块{System.out.print("4== ");}                 //实例初始化块{System.out.print("5== ");}                 //实例初始化块static {System.out.print("Static 6== ");} //静态初始化块
}

Java抽象类、接口、类的特殊成员相关推荐

  1. python 全栈开发,Day21(抽象类,接口类,多态,鸭子类型)

    一.昨日复习 派生方法和派生属性 super 只有在子父类拥有同名方法的时候, 想使用子类的对象调用父类的方法时,才使用super super在类内 : super().方法名(arg1,..) 指名 ...

  2. java 抽象接口类,Java接口(interface)和Java抽象类(abstract class)的区别(详诉版)

    1.概述 一个软件设计的好坏,我想很大程度上取决于它的整体架构,而这个整体架构其实就是你对整个宏观商业业务的抽象框架, 当代表业务逻辑的高层抽象层结构合理时,你底层的具体实现需要考虑的就仅仅是一些算法 ...

  3. 13.0_[Java 面向接口]-类和接口

    ################################################## 目录 接口基础知识 什么是接口 如何定义和实现接口 接口表示一种能力 为什么需要接口 使用接口实现 ...

  4. JAVA抽象类接口初始化块实验_抽象类和接口 - 逝水无痕7777的个人空间 - OSCHINA - 中文开源技术交流社区...

    抽象类和接口 1.抽象类 抽象方法是只有方法签名,没有方法实现的方法.有抽象方法的类只能被定义成抽象类,抽象类可以没有抽象方法.抽象方法和抽象类必须使用abstract修饰符来定义. 抽象类不能被实例 ...

  5. Java抽象类+接口详细图解 一篇博客拿下

    目录 抽象类 抽象类的概念 抽象类的语法 抽象类的特性 抽象类的作用 接口 接口的概念 接口的语法 接口特性 实现多个接口 接口间的继承 接口实例 1.Compareable 2.Comparator ...

  6. java抽象类接口举例代码_Java接口和抽象类实例分析

    本文实例讲述了Java的接口和抽象类.分享给大家供大家参考.具体分析如下: 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相 ...

  7. java 成员类_Java类的五大成员之一——内部类

    一. 类的五大成员: 属性.构造方法.一般方法.块.内部类 这篇主要描写内部类. 下面代码演示类的结构: package com.company.project.test.t41; import ja ...

  8. java 抽象类 普通类_java的抽象类,接口,普通类是否可以直接NEW,并且复写方法?

    我看那个内部匿名类的写法(代码1),接口可以直接new,代码2中抽象类可以直接NEW,那是否可以直接 new 一个普通类然后复写其中方法比如代码3? 代码1 interface Person { pu ...

  9. java comparator接口类_常见的接口与类 -- Comparator

    接口Comparator 1.1 前面我们讲过Java提供了一个用于比较的接口Comparable,提供了一个比较的方法,所有实现该接口的类,都动态的实现了该比较方法.实际上Java中除了比较一个接口 ...

  10. java派生类_我可以使派生类从Java的基类继承派生成员...

    我有看起来像这样的代码: public class A { public void doStuff() { System.out.print("Stuff successfully done ...

最新文章

  1. VCL 中的 Windows API 函数(6): BeginDeferWindowPos
  2. SQL Server 跨域访问
  3. java视频流传输_java – 使用Xuggler流式传输视频
  4. 排序算法——冒泡排序、选择排序、直接插入排序
  5. dev控件ASPxComboBox设置ReadOnly=true后
  6. python远程执行shell脚本文件_python SSH模块登录,远程机执行shell命令实例解析
  7. excel转word_excel怎么转word?常用方法合集,看你使用哪一种
  8. python股票量化交易从入门到实践df_python股票量化交易从入门到实践df_Python股票量化交易从入门到实践/金融科技系列......
  9. 客户关系管理之会员管理
  10. 一元高次方程c语言实现,c语言实现一元二次方程求解
  11. 海尔空调、新风系统加装wifi模块
  12. 图片心理性格测试
  13. EF(一) -- EF简介
  14. 该网页无法访问未连接上服务器是什么意思,浏览器打不开该网页,因为无法连接到服务器...
  15. 荷池堪作镜,盈盈可鉴心。(递推
  16. Excel按照单元格内设定好的次序进行工作表排序
  17. QT实现浏览器访问网页,使用QWebEngineView
  18. Javascript——高级进阶
  19. 王国栋青岛大学计算机学院,王国栋
  20. 3天学会Jenkins_1_Jenkin与CI(Continuous Integration,持续集成)?

热门文章

  1. LeetCode MySQL 1501. 可以放心投资的国家
  2. LeetCode 592. 分数加减运算(字符串+最大公约数)
  3. LeetCode 712. 两个字符串的最小ASCII删除和(DP,类似编辑距离)
  4. 微信小程序中带参数返回上一页的方法总结(三种)
  5. 执行计划 分析一条sql语句的效率 mysql_MySQL中一条SQL语句的执行过程
  6. 讯达机器人_科大讯飞新品频发完善场景布局“双11”斩获三大平台25项冠军
  7. python3.6是用来干嘛的_学 Python 都用来干嘛的?
  8. 视频问答兴起,多跳问答热度衰退,92篇论文看智能问答的发展趋势
  9. BAT Java面试笔试33题:JavaList、Java Map等经典面试题!答案汇总!
  10. 领域应用 | HiTA知识图谱 “药品-适应证”图谱数据发布!