Java面向对象(3) —— 抽象类、接口、内部类、匿名内部类

目录

  • 抽象类(abstract)
    • 抽象类的使用方法
    • 抽象类的应用:模板方法模式
  • 接口
    • 接口的概念
    • 接口的特点
    • 接口的使用
    • 接口实现与抽象类继承的区别
    • 接口的多继承
  • 内部类
    • 概念
    • 成员内部类(使用较多)及应用
      • 创建成员内部类的实例
      • 在成员内部类中访问外部类的成员方法和属性
      • 外部类不能直接访问内部类的成员,必须先建立内部类的对象才能访问
    • 成员内部类有以下限制
  • 匿名内部类
    • 概念
    • 匿名内部类的创建与访问

抽象类(abstract)

java中可以定义没有方法体(只有方法头)的方法,该方法由子类来具体实现。该没有方法体的方法我们称之为抽象方法,含有抽象方法的类我们称之为抽象类。

有抽象方法的类,一定是抽象类。即抽象方法只能放在抽象类中。
但是抽象类中可以有具体方法,可以没有抽象方法。

特点

(1)抽象方法不能被调用

抽象方法代表一种不确定的操作或行为

(2)抽象类不能被实例化

虽然按照提示也能完成方法体实例化,但这是不靠谱的使用方式(这种不靠谱的方式也是后面提及的匿名的内部类)

(3)抽象方法用abstract来修饰

不可以被实例化,那怎么使用这个抽象类呢?

抽象类的使用方法

做一个类来继承这个抽象类,继承的时候把方法体实现了,如下:

//抽象方法只能放到抽象类里面,因此前面也要加abstract
abstract class Test1
{abstract void printInfo(); //在抽象类里面的方法,要么完善方法体,要么作为抽象方法
}                              //没有方法体的方法,该方法由子类来具体实现//类似C语言中对函数的声明class Test2 extends Test1  //继承抽象类,从而使用抽象类
{@Overridepublic void printInfo() {System.out.println("来自:test2");}
}public class Demo1 {public static void main(String[] args){Test2 t2 = new Test2();t2.printInfo();}
}

抽象类的应用:模板方法模式

模板方法模式定义:

父类抽象(abstract)化定义一系列方法作为模板(不具体),把一些步骤推迟到子类去实现,子类将重写这些方法以提供具体行为。

之前做的智能家居可以运行在多个平台上,比如51,32,树莓派,现在就定义在每个平台上完成这个项目的通用模板,然后再在具体平台实现,以51为例子(当然这只是一个类比,java在51单片机上不能运行):

abstract class Control
{abstract void getCommand(); //是概括了在不同平台上完成智能家居项目的模板abstract void socketCommand(); //抽象化这些方法,在子类(类比于具体平台)abstract void lightControl();  //中再进行具体化abstract void cameraControl();public void work(){ //控制的基本流程getCommand();   //接收指令socketCommand(); //来自socket的指令lightControl();  //灯的控制cameraControl(); //相机的控制}
}class C51platform extends Control //当这个地方出现红色波浪线的时候
{                                 //光标放上去,可以看到解决方法的快捷键@Override                     //把抽象方法重写,全部具体实现void getCommand() {System.out.println("getcommand in 51");}@Overridevoid socketCommand() {System.out.println("socketcommand in 51");}@Overridevoid lightControl() {System.out.println("lightcontrol in 51");}@Overridevoid cameraControl() {System.out.println("cameracontrol in 51");}
}public class Test {public static void main(String[] args) {C51platform c51 = new C51platform();  //实例化出一个对象c51.work(); //执行具体流程}
}

运行结果:

getcommand in 51
socketcommand in 51
lightcontrol in 51
cameracontrol in 51

接口

接口的概念

接口(Interface),在JAVA中是一个抽象类型,是抽象方法的集合(重点强调的是方法、是行为,而不是属性、特征)。

interface 接口名{//公有静态常量、抽象方法(抽象方法用的比较多)
} class 类名{}

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法

接口与类的区别:————————

(1) 接口不能用于实例化对象

(2) 接口没有构造方法

而类是默认都有构造方法的(系统默认的参数为空的构造方法)

(3)接口中所有的方法必须是抽象方法

可以不指定修饰符,就默认为隐式抽象

(4)接口不能包含成员变量,除了 static 和 final 变量

接口中也一般不适用成员变量,以方法为主。

(5)接口不是被类继承了,而是要被类实现。而接口可以继承接口。

说法上的东西罢了,不用太纠结,具体看编程

接口的特点

接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。

就像下图,只要你不写修饰符,那就默认为隐式抽象为public abstract,可以编译通过。但凡你使用别的修饰符,马上报错。
在这里插入图片描述

接口的使用

一个类通过继承接口的方式,从而来继承接口的抽象方法。

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法(包括接口继承过来的方法),否则就必须声明为抽象类。

继承是有亲属关系的,is的关系;而接口是双方都有的行为,比如人和狗都要吃东西。

下面的例子是以一些人和狗子都具有的行为作为接口,用Man类和Dog类具体实现:

interface Behavior  //接口,更注重方法
{void eat();   //在接口中,不写修饰符,默认为隐式抽象abstract void drink(); //当然写也无问题
}class Man implements Behavior  //一个类实现了这个接口
{                              //从而来继承接口的抽象方法@Overridepublic void eat() {System.out.println("人吃米");}@Overridepublic void drink() {System.out.println("人喝饮料");}
}class Dog implements Behavior //一个类实现了这个接口
{                             //从而继承接口的抽象方法@Overridepublic void eat() {System.out.println("狗喜欢吃骨头");}@Overridepublic void drink() {System.out.println("狗喝水");}
}public class Test {public static void main(String[] args) {new Man().eat(); //new就是实例化一个对象,所以new Man()已经是一个对象了new Man().drink();new Dog().eat();new Dog().drink();}
}

接口实现与抽象类继承的区别

1)抽象类和具体实现之间是一个继承关系,也就是如果采用抽象类的方式,则父类和子类在概念上应该是相同的 ,是is -a的关系。

比如父类为老师,子类为语文老师,那么可以说语文老师是(is)一个(a)老师

(2)接口和实现类之间在概念上不要求相同,接口不去关注类之间的关系,它可以使没有层次关系的类具有相同的行为

抽象类是对一组具有相同属性和行为的逻辑上有关系的事物的一种抽象。
而接口则重点对一组具有相同行为的事物的一种抽象。

(3)抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。

(4)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。(但接口强调行为,少用变量)

(5)接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。

(6)一个类只能继承一个抽象类,而一个类却可以实现多个接口

class People implements Survival,EnjoyLife //people这个类实现了多个接口
  • 1

其实到后面你可以发现,一个类实现多个接口接口的多继承再被类实现很像。

接口的多继承

在Java中,类的多继承是不合法,但接口允许多继承。

在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下:(足球这一接口继承了其他接口)

public interface Sport extends Basketball, Football,Ping_pong
  • 1

继承过来后,类依旧要完成所有接口的抽象方法

举个简单的小例子:

interface Survival  //人关于生存的行为
{void eat();void drink();
}interface EnjoyLife  //人享受生活的行为
{void seeMovie();
}interface HowPeopleLive extends Survival,EnjoyLife //这个接口继承了上面两个接口
{void happy();/*void life(){ 接口中不允许有方法体}*/void life(); //只能在类的实现中赋予方法体
}class People implements HowPeopleLive
{//当一个类实现接口时,就要把接口里所有的抽象方法实现,具体化@Overridepublic void eat() {System.out.println("主要吃大米饭");}@Overridepublic void drink() {System.out.println("主要喝白开水");}@Overridepublic void seeMovie() {System.out.println("看电影感悟生活");}@Overridepublic void happy() {System.out.println("你开心就好");}@Overridepublic void life() {   //实现接口的方法体eat();drink();seeMovie();happy();}
}public class Demo1 {public static void main(String[] args) {People man = new People();man.life();}
}

运行结果:

主要吃大米饭
主要喝白开水
看电影感悟生活
你开心就好

内部类

概念

所谓内部类(Inner Class),就是讲一个类定义在另一个类的内部,内部的类就称为内部类。

public class Outer{class Inner{}
}

内部类可以很好地实现隐藏,成员内部类属于外部类的实例成员,成员内部类可以有权限修饰符。

可以使用protected private修饰符内部类可以直接访问外部类的所有成员,包括私有的成员。

外部类不能直接访问内部类的成员,必须首先建立内部类的对象才能访问。

成员内部类(使用较多)及应用

创建成员内部类的实例

外部类名.内部类名 实例 = 外部类实例名.new 内部类构造方法(参数)
  • 1

下面以访问内部类的方法为例子:

class Outer
{int data;void printData(){System.out.println("外部类打印");}class Inner{int data;void innerPrint(){System.out.println("内部类打印");}}}public class Test {public static void main(String[] args) {Outer ou = new Outer();         //要使用内部类的方法,必须先实例化一个外部类的对象Outer.Inner in = ou.new Inner();//再通过这个外部类的对象实例化一个内部类的对象in.innerPrint();                //在进行访问方法即可}
}

在成员内部类中访问外部类的成员方法和属性

外部类名.this.成员方法
//或者
外部类名.this.成员属性

例如:

class Outer
{int data;void printData(){System.out.println("外部类打印");}class Inner{int data;void innerPrint(){System.out.println("内部类打印");Outer.this.printData();  //内部类对外部类方法的访问System.out.println("内部类访问外部类的属性:data="+Outer.this.data);//对属性的访问}}
}

外部类不能直接访问内部类的成员,必须先建立内部类的对象才能访问

(意义不大,用的较多的还是内部类访问外部类)

class Outer
{int data;void printData(){System.out.println("外部类打印");}//外部类不能直接访问内部类的成员,必须先建立内部类的对象才能访问void visitInner(){Inner in = new Inner();//先建立内部类的对象in.innerPrint();       //通过内部类的对象进行访问}class Inner{int data;void innerPrint(){System.out.println("内部类打印");}}
}public class Test {public static void main(String[] args) {Outer ou = new Outer();         //要使用内部类的方法,必须先实例化一个外部类的对象Outer.Inner in = ou.new Inner();//再通过这个外部类的对象实例化一个内部类的对象ou.visitInner();                //外部类访问内部类打印}
}

成员内部类有以下限制

(1)成员内部类不能和外部类重名

(2)不能在成员内部类中定义static属性、方法、类。(static final形式的常量定义除外)

因为一个成员内部类实例必然与一个外部类实例关联,static成员完全可以移到其外部类中去。

匿名内部类

概念

匿名内部类是没有名称的内部类,没办法引用它们。必须在创建时,作为new语句的一部分来声明并创建它们的实例。

这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口,并同时创建该匿名类的一个新实例。

匿名内部类的创建与访问

匿名内部类必须继承一个类(抽象的,非抽象的都可以),或者实现一个接口,所有父类(或者父接口)是抽象类,则匿名内部类必须实现其所有抽象方法。

语法:

new interface/superclass(){类体}
  • 1

例如:

(1)创建后立即访问

abstract class Demo1          //声明了一个抽象类
{abstract void printInfo();//声明了一个抽象方法
}public class Test {public static void main(String[] args) {new Demo1(){//既初始化又要实现内部的方法 不是实例化 而是创建了匿名内部类并实例化匿名内部类void printInfo(){ //匿名内部类必须实现继承的类的所有方法System.out.println("这不是demo1,而是匿名内部类的方法");}}.printInfo();//new的返回值就是一个对象,所以可以直接通过“.”这样访问匿名内部类的方法}
}

运行结果:

这不是demo1,而是匿名内部类的方法
  • 1

(2)当然,也可以用“多态”进行访问(目前我也不知道多态是啥)

abstract class Demo1
{abstract void printInfo();
}public class Test {public static void main(String[] args) {Demo1 d = new Demo1(){    //这感觉像是实例化了一个Demo1得到对象d,实际上得出的这个Demo1是抽象类的子类void printInfo(){    //匿名内部类必须实现继承的类的所有方法System.out.println("这不是demo1,而是匿名内部类的方法");}};d.printInfo();}
}

运行结果:

这不是demo1,而是匿名内部类的方法
  • 1

(3)匿名内部类实现一个接口

这种用法可能会在安卓的线程,按键响应做这样的事情。

interface Demo2 //接口
{abstract void interprint();
}public class Test {public static void main(String[] args) {new Demo2(){public void interprint(){  //这里不使用public就报错了System.out.println("这不是接口的实例,而是匿名内部类的方法");}}.interprint();}
}

运行结果:

这不是接口的实例,而是匿名内部类的方法
  • 1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kohana和Zencart

2019独角兽企业重金招聘Python工程师标准>>> 我有一个Kohana php框架但是客户求和zencart系统结合。我有一个想法是Kohana重新zencart 有没有人用过?应该没有吧 Kohana 是一款纯 PHP5 的框架,基于 MVC 模式开发, 它的特点就是高安…

Linux stmac网卡代码分析 -- open

Open stmmac_open是在stmmac_netdev_ops结构体里的,这个ops在probe时就已经注册到了net_device结构体里,在网卡对于stmmac_open函数调用的时间我还不确定是否是在网卡link up时 下面看看stmmac_open函数,文件位置: drivers/net/…

g++ linux 编译开栈_方舟编译器编译hello world踩坑全记录

闲来无事,看到方舟编译器完整开源,于是打算拿来试着编译一个东西来,接下来把踩过的一些坑记录一下。参考文档方舟编译器的官网是OpenArkCompiler​www.openarkcompiler.cn但是这个网站上的文档其实是过时的,没有更新过的&#xff…

绘制自定义键盘

先看下微信当中的自带的数字键盘 这种实现方式比较简单,可以直接用inline-block标签,设置每行平均宽度,比如一行要放4个按钮,可以那么宽度就可以设为25%,同时要注意设置css样式为box-sizing: border-box,这样在设置边框…

配置管理小报100329:脚本中ftp命令无法自动输入密码怎么办?

为什么80%的码农都做不了架构师?>>> 知识点: 作者:王(zbwangjian.cn) 脚本中ftp命令无法自动输入密码怎么办?参考: http://www.linji.cn/post/1620/ http://www.hamo…

linux下使用网易邮箱发邮件

0x0 最近要写个脚本监视系统运行情况,有异常及时通过邮件通知我。 本次测试中使用网易的邮箱作为邮件发送服务器(邮箱账号需要开启smtp服务如下图),由于网易邮箱验证比较严格,需要进行一些额外操作才可以正常发送邮件…

ubuntu下网易云音乐适配高分辨率屏幕

0x0 环境 ubuntu20处理器 AMD 我主流工作环境是Ubuntu20,而且很依赖音乐,网易云音乐适配了Ubuntu,而最近我换了个4K屏幕 开机启动网易云音乐后发现界面文字变得很小完全没法看,如下图 分析发现网易云音乐是通过 /opt/netease/ne…

Java基础 —— 异常

目录异常的概念及分类异常的处理try-catch-finally异常抛出throw(s)自定义异常异常的概念及分类 什么是异常 异常是指在程序的运行过程中发生的一些不正常事件。比如:除0溢出、数组下标越界、所要读取的文件不存在。 异常导致的后果 项目JAVA程序的执行过程中如出现…

解决网站请求速度慢的一些方法

开门见山,网站请求反应速度慢首先考虑服务器问题。 我在开发中遇到的就是服务器实例限制cpu占用10%以内访问正常,超出则限制访问速度,也就是网站请求速度慢 具体和阿里工程师聊天截图如下: 按照对方说的,升级了相关配置…

Windows Server 2012 在个人终端上使用的推荐设置

Windows Server 2012,也就是 Windows 8 的服务器版本,相对于 Windows 8 企业版而言,增强了作为服务器的功能,弱化了作为终端系统的功能。   目前微软官方提供了 Windows 8 企业版(90 天评估期)和 Windows…

Java高级 —— 泛型

目录泛型概念泛型可设置多个类型参数泛型继承泛型接口限制泛型可用类型泛型通配声明泛型方法泛型方法限制泛型可用类型泛型概念 问题引入:如果我们需要产生多个对象,每个对象的逻辑完全一样,只是对象内的成员啊变量的类型不同。那我们如何去…

wopihost

项目介绍 基于wopi协议开发的WopiHost, 支持word, excel,ppt(仅支持预览)等文档的预览和编辑。 运行环境 需要安装Office online 2016才可以使用,基于jdk 1.8,spring boot开发。 使用案例 word文档预览 http://[owas.domain]/wv/wordviewerfr…

java 人物属性

写代码,可以浏览人物的属性:package day14; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ImageIcon; import javax.swing.JComboBox; im…

安卓APP_ Fragment(5)—— Fragment + ViewPager2 模拟微信首页 (2)两者联动翻页

摘自:安卓APP_ Fragment(5)—— Fragment ViewPager2 模拟微信首页 (2)两者联动实现翻页 作者:丶PURSUING 发布时间: 2021-04-22 00:11:43 网址:https://blog.csdn.net/weixin_4474…

stmmac描述符的结构和初始化

stmmac 描述符(Descriptors) stmmac的描述符有两个个模式,分别是ring模式和chain模式,根据特性的不同支持,描述符又有以下3个形式norm、Alternate 、 Enhanced。下面主要讲下ring模式下的Enhanced描述符结构&#xff…

Android中利用productFlavors配置多渠道

build.gradle(app)设置 android {flavorDimensions "default"productFlavors{//不同渠道360{dimension "default"//替换AndroidManifest中的值manifestPlaceholders [channel_value:"360"]}qq{dimension "default"//替换AndroidManif…

Ubuntu服务器安装snmpd(用于监控宝)

2019独角兽企业重金招聘Python工程师标准>>> 一、安装snmpd: sudo apt-get install snmpd 二、修改配置文件 vi /etc/snmp/snmpd.conf 找到这样的两行 agentAddress udp:127.0.0.1:161 #agentAddress udp:161,udp6:[::1]:161 将他们的注释交换一下 #…

安卓APP_ 四大基本组件(1)—— Activity

摘自:安卓APP_ 四大基本组件(1)—— Activity 作者:丶PURSUING 发布时间: 2021-04-22 15:56:18 网址:https://blog.csdn.net/weixin_44742824/article/details/116006048 配合菜鸟教程食用效果更佳&#xf…

radare2 常用操作总结

radare2 简介 radare2是一个用C语言编写的跨平台的二进制分析工具,支持ARM、MIPS、X86等平台,支持分析多种格式的二进制文件如ELF、Mach-O、Fatmach-O, PE、PE、 MZ、 COFF等,同时也支持多种操作系统如Windows (since XP)、GNU/Linux、GNU/D…

序列化与反序列化(1)Serializable —— Java原生态方法

摘自:序列化与反序列化(1)Serializable —— Java原生态方法 作者:丶PURSUING 发布时间: 2021-05-08 19:20:21 网址:https://blog.csdn.net/weixin_44742824/article/details/116503261 本文为学习笔记&…