菜鸟学习笔记:Java基础篇5(抽象类与接口、回调函数、内部类)
菜鸟学习笔记:Java面向对象篇下
- 抽象类
- 接口
- 回调函数
- 内部类
- 成员内部类
- 匿名内部类
抽象类
通过前面知识的学习,抽象类这个概念应该不难理解,但比较容易和后面要说的接口混淆,而且在面试中也比较爱问这两者的区别,所以希望大家可以通过对比来学习。
抽象类可以理解为它子类一个模板,所有继承了抽象类的子类都必须遵守抽象类的规定,子类可以在这个模板上进行扩展。通过抽象类可以避免子类的随意性。
还是之前Animal的例子,我们把Animal定义成一个抽象类:
//在访问控制符后加上abstract代表为抽象类或方法
public abstract class Animal{//抽象类int old; //注意Java中没有抽象属性String environment;String metabolize;//抽象方法定义时加上abstract关键字,只能定义在抽象类和接口中(接口中方
//法默认为抽象方法)该类方法没有方法体,并且规定子类中必须实现这些方法abstract void reproduction();//默认为public方法abstract void move();
//抽象类也可以定义普通方法public void grow(){System.out.println("我在成长。。。");}
}
它的子类:
class Fish extends Animal{//必须实现abstract方法public void reproduction(){System.out.println("小鱼在繁殖。。。");}public void move(){System.out.println("小鱼游啊游。。。");}
}
//鸟类继承动物类
class Bird extends Animal{//必须实现abstract方法public void reproduction(){System.out.println("小鸟在繁殖。。。");}public void move(){System.out.println("小鱼飞啊飞。。。");}//也可以重写普通方法public void grow(){System.out.println("小鸟在成长。。。");}
}
对于抽象类有几个注意点:
- 用abstract修饰的方法只能在抽象类中(接口中的方法也是抽象方法,但不需要用abstract修饰)
- 抽象类只能被继承,无法实例化,但可以实现多态(抽象类引用指向子类对象)
- 抽象类可以有构造方法,但不能用来new实例,只能用来被子类调用(super())。
接口
自然界中有些事务的关系很复杂,比如一根火腿肠,它属于肉类,但也属于零食类,还属于商品类。但Java之中的继承规定是单继承,一个类只能有一个父类,所以依靠继承关系无法全面的反应出自然界里所有的关系,这时候就需要引入一个全新的概念:接口。
接口与抽象类有一定的相似性,但也有区别,首先在接口中不允许定义普通方法,这让接口变得比抽象类更加严格。其次一个类可以实现多个接口,并且类中要实现它所有接口中的方法,这一点很好的实现了一个对象同时属于不同类的情况。举例说明:
//在访问控制符后加上interface代表为接口
public interface Animal{//Animal接口//接口中的变量即使不做声明,注意接口中的属性默认为//static final类型,不可改变,并且必须赋予初值int old=6; String environment = "water";//即使不做声明,接口中的方法也默认为public abstract方法。void reproduction();void move();
}public interface MarineOrganism{//海洋生物接口void BreatheWithGills();
}
这样鱼类就可以实现这两个接口:
class Fish implements Animal,MarineOrganism{public int height = 5;//必须实现接口中的所有方法public void reproduction(){System.out.println("小鱼在繁殖。。。");}public void move(){System.out.println("小鱼游啊游。。。");}public void BreatheWithGills(){System.out.println("小鱼用鳃呼吸。。。");}
}
在main函数中:
public static void main(String[] args) {Animal oFish = new Fish(); //接口和抽象类一样也可以作为引用变量类型,指向实现类类型的对象System.out.println(oFish.old); //实现类可以获得接口中的属性,但不可以修改//这里补充一点,因为静态属性和方法随类的加载而定义,先于对象,//所以其不仅可以通过类名进行调用,也可以通过类的实例来调用,调//用效果和类名调用一致,但还是建议用类名调用静态方法((Fish)oFish).height = 4;//oFish的引用类型为Animal,Animal接口没有height这个属性,//所以需要通过强制类型转换来解决这个问题,下面方法同理((Fish)oFish).BreatheWithGills(); //调用方法会打印小鱼用鳃呼吸。。。
}
对于抽象类和接口的区别一直是面试的考点,相信大家根据上面的讲解应该可以自己总结出来,我找了一篇专门做对比的博客分享给大家。链接
回调函数
首先大家应该都知道我们可以把一块实现同一功能的代码块封装成一个方法,在使用时可以直接调用。但在程序中有时候会出现一个问题,某一段开始和结束的逻辑相同,但中间的代码存在差异。假设把每个人使用电脑的过程写成一段代码:
public void UseComputer(){System.out.println("做到电脑前");System.out.println("按开机键");//中键过程每个人都不相同System.out.println("按关机键");System.out.println("离开电脑前");
}
这段代码中前后过程一致,但中间操作不同人大不相同,而前后的代码无法进行封装,所以我们采用回调函数来解决这个问题。
首先新建一个接口:
public interface Operation {public void Do();
}
然后我们新建一个程序员类来继承操作接口,重写Do方法:
public class Programmer implements Operation{@Overridepublic void Do() {System.out.println("写代码,写代码。。。");}
}
改写UseComputer方法为:
public void UseComputer(Operation o){System.out.println("做到电脑前");System.out.println("按开机键");o.Do();System.out.println("按关机键");System.out.println("离开电脑前");
}
这样我们针对不同身份的人使用电脑,就可以调用不同的函数实现,这就是回调函数。我们在main函数中做测试:
public static void main(String[] args) {Programmer oProgrammer = new Programmer();new test().UseComputer(oProgrammer);//打印//做到电脑前//按开机键//写代码,写代码。。。//按关机键//离开电脑前}
回调函数主要运用了23种设计模式中所讲的模板方法模式(感兴趣的同学可以去了解了解,这里不做太多介绍),回调函数的运用非常广泛,比如我们在点击某个按钮时按钮接收响应的方式都是一样的,唯一不同的就是点击时要做的操作,所以我们就可以将这些操作用回调函数传入其中,大大简化开发复杂度。
个人感觉回调函数这个概念对老手很简单,但新手不太好理解,大家如果看完没有理解可以结合这个例子再看一些介绍概念的博客。我在这里推荐一篇 ,相信大家多看多写很快就能掌握。
内部类
简单的说就是在另一个类里面定义的类,这样使得这个类只能是它的外部类访问,对其他类不可见。而且这个类可以访问外部类的私有属性更加灵活方便。一般情况下内部类只有为外部类提供服务的情况下优先使用。
成员内部类
成员内部类分为静态内部类和非静态内部类,和静态和非静态属性和方法的区别相似,先举一个非静态内部类的例子:
public class Human{int age;String name;public Human(int age, String name) {super();this.age = age;this.name = name;}public void Grow() {System.out.println("我在成长。。。");}class Eyes{String color = "黄";void see(){System.out.println(color + "眼睛的" + name + "看到你们了。。。");}}
}
这样在调用时:
public static void main(String[] args) {Human oHuman = new Human(30,"老王");Eyes e = oHuman.new Eyes();//实例化内部类e.see();//会打印黄眼睛的老王看到你们了。。。表名内部类可以访问外部类属性}
注意非静态内部类不能有静态属性、静态方法、静态代码块。
而静态内部类和静态成员方法对应,并不依赖于外部类对象,所以它不能用外部类对象的属性和方法,但可以访问外部类的静态成员。稍微修改下上一个例子:
public class Human{int age;String name;static final int numberOfeyes = 2;public Human(int age, String name) {super();this.age = age;this.name = name;}public void Grow() {System.out.println("我在成长。。。");}static class Eyes{String color = "黄";void see(){System.out.println("人有" + numberOfeyes + "只眼睛");}}
}
调用时:
public static void main(String[] args) {//Human oHuman = new Human(30,"老王");Human.Eyes e = new Human.Eyes();e.see();}
匿名内部类
适合那种只需要使用一次的类,比如键盘监听操作,运用静态内部类我们可以更好的使用回调函数操作,在使用回调函数时我们可以不定义程序员Programmer类,而直接用静态内部类实现:
public static void main(String[] args) {new test().UseComputer(new Operation() {@Overridepublic void Do() {System.out.println("写代码,写代码。。。");}});//打印//做到电脑前//按开机键//写代码,写代码。。。//按关机键//离开电脑前}
匿名内部类通常用来简化代码编写,但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
至此Java面向对象方面的知识就全部讲完了,希望大家学到这对Java的编程思想有个清晰的认识,在之后几篇中会介绍几个Java的常用类,帮助大家更更好的运用Java来编程。
上一篇:菜鸟学习笔记:Java基础篇4(面向对象三大特征).
下一篇:菜鸟学习笔记:Java基础篇6(数组、字符串).
菜鸟学习笔记:Java基础篇5(抽象类与接口、回调函数、内部类)相关推荐
- Java基础篇:抽象类与接口
1.抽象类和接口的定义: (1)抽象类主要用来抽取子类的通用特性,作为子类的模板,它不能被实例化,只能被用作为子类的超类. (2)接口是抽象方法的集合,声明了一系列的方法操作,自身并不能做任何事情.如 ...
- 【JAVA基础篇】抽象类和接口的区别
抽象类和接口是定义抽象概念的两种方式,正是由于抽象类和接口,才赋予了Java强大的面向对象的能力.在讨论他们的不同点之前,我们先来了解抽象类和接口. 抽象类 在面向对象的领域一切事物都是对象.对象都是 ...
- Java学习笔记之基础篇
Java学习笔记之基础篇 目录 Java如何体现平台的无关性? 面向对象(OO)的理解 面向对象和面向过程编程的区别 面向对象三大特征 静态绑定和动态绑定(后期绑定) 延伸:类之间的关系 组合(聚合) ...
- jqGrid 学习笔记整理——基础篇
jqGrid 学习笔记整理--基础篇 jqGrid 实例中文版网址:http://blog.mn886.net/jqGrid/ 国外官网:http://www.trirand.com/blog/ 本人 ...
- java提高篇之抽象类与接口
转载自 java提高篇之抽象类与接口 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法. 抽象类与接口是java语言中对抽象概念进行定义的两种机制,正是由于他们的存在才赋予java强大的 ...
- C++基础篇之抽象类的接口
C++基础篇之抽象类的接口 接口描述了类的行为和功能,而不需要完成类的特定实现. C++ 接口是使用抽象类来实现的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念. 如果类 ...
- 基于c++和asio的网络编程框架asio2教程基础篇:2、各个回调函数的触发顺序和执行流程
基于c++和asio的网络编程框架asio2教程基础篇:2.各个回调函数的触发顺序和执行流程 以tcp举例: tcp服务端流程: #include <asio2/asio2.hpp>int ...
- 学习笔记-java基础-网络编程
刚在培训机构学习完JAVA基础和WEB,感觉边学边忘.就把这作为记忆的笔记,我也不知道要不要记笔记,写在本子上太耗费时间了. 一.要想实现网络通信,首先要解决两个问题: ①:如何从网络中定位到一台或多 ...
- Java菜鸟教程系列 学习笔记总结 基础篇(1)
基础语法 本博客通过学习菜鸟教程Java专栏,并整理得出的Java基础知识. 命名规范 1.项目名全部小写 2.包名全部小写 3.类名首字母大写,如果类名由多个单词组成,每个单词的首字母都要大写.如: ...
- Java快速教程--vamei 学习笔记(基础篇)
链接:http://www.cnblogs.com/vamei/archive/2013/03/31/2991531.html java快速教程第1课 从HelloWorld到面向对象 学习网址:ht ...
最新文章
- R语言dplyr包和tidyr包创建交叉表(列联表、crosstab)实战
- 你还是只会用数组吗?不懂Java集合,还想找工作?(集合概述)
- 洛谷模拟赛 部落冲突
- 【Java面试题】41 两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?...
- (五)操作系统安全概念和设计思想
- 数据结构与算法之美-哈希算法
- java 调用tomcat api,Tomcat采用双向认证https协议通过JavaAPI调用(一)配置SSL
- 腾讯x5加载本地html乱码,腾讯X5内核播放器遇到的问题
- Web前端求职必备 常见前端面试题汇总(二)
- 微信读书App来了 小伙伴们快去占榜吧
- 常见概率分布图表总结
- mysql 以空间换时间专研
- RxJava串行执行任务
- VS2010出现重复的代码项原因及解决方式
- 干货!旋转预测能够告诉我们分类器准确度的哪些信息?
- Ti 官方文档阅读笔记
- 基于Plot.ly Dash 使用 Python 开发交互式互动数据图
- 商业源码QQ币,YY币,充值支付系统源码
- 45岁,拿到华为20级架构师offer要去吗
- python爬取抖音粉丝数据_爬取抖音粉丝数据1(作品、喜欢、ID 、关注) 完整源代码...
热门文章
- cefsharp异步抓取html5,winform插件cefsharp65最新版完美demo,完美flash、html5、和调用摄像头支持,部署就能用...
- Intellij IDEA 配置
- npm 报错 Module build failed: Error: No PostCSS Config found in:
- Linux环境下利用句柄恢复Oracle误删除的数据文件
- Centos7下安装python3
- Python笔记:使用pywin32处理excel文件
- IT项目中的6类知识转移
- Emacs+hideif.el 隐藏预编译代码(或彩色显示预编译代码)
- 《Pro ASP.NET MVC 3 Framework》学习笔记之二十四【Controllers和Actions】
- Firewoks——层与蒙版