先来理解2个概念:闭包和回调

  •   什么是闭包?

闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建他的作用域。通过这个定义,可以看出内部类是面向对象的闭包,因为他不仅包含了外部类对象的信息,还自动拥有一个指向外部类对象的引用,在此作用域里,内部类有权操作所有的成员,包括外部类的private修饰的成员。

  •   什么是回调?

回调就是对象携带一些信息,这些信息允许它在稍后的某个时刻调用初始化的对象。说白了就是说:某个方法一旦获得了内部类对象的引用,就可以在合适的时候反过来调用外部类实例的方法。非静态内部类,可以很方便的实现回调。

  •   值得说明的是:内部类最大的作用就是实现了多继承。java是单继承的,使用内部类可以使得编程更加的灵活。

看下面3种情形:

  1,必须在同一个类中以某种方式实现2个接口?

public class Linkin implements A,B{

    @Override
public void testB() { } @Override
public void testA() { } } interface A{
public void testA();
} interface B{
public void testB();
}



上面的情形很简单,但是举一个例子,说这2个方法同名呢? 那要怎么办呢?我们可以在实现类里面直接实现那个方法,但是这样子肯定是不好的。一个接口规范了一个功能,怎么好意思讲同一个实现类同一个实现来实现2个不同规范的功能呢?     有解决办法:使用内部类。

public class Linkin implements A{

    //定义一个方法,返回一个实现了B的匿名内部类,去实现B
B makeB(){
return new B(){ @Override
public void test() {
System.out.println("实现接口B...");
} };
} //这里是外部类,直接实现了接口A
@Override
public void test() {
System.out.println("实现接口A...");
} } interface A{
public void test();
} interface B{
public void test();
}

2,还是上面一样的情形,但是一个是普通的类,一个是抽象类呢? 这个时候就只能使用内部类了。

public class Linkin extends A{
//使用内部类,可以很好实现多继承
B makeB(){
return new B(){ @Override
public void test() {
System.out.println("这里来实现下面那个抽象类B的方法。。。");
} };
} } class A{
public void test(){
System.out.println("这里是A类的一个方法。。。");
}
} abstract class B{
abstract public void test();
}

3,还是上面的情形,现在一个是普通的类,一个是接口,里面都包含一个同名的方法,要如何实现写一个新的class来实现上面2个功能呢?如何正常一个直接继承,一个实现,代码是这样子的:

public class Linkin extends A implements Binger{

    @Override
public void test(){
System.out.println("这里是B类的一个方法。。。");
} public static void main(String[] args) {
Linkin linkin = new Linkin();
linkin.test();
} } class A{
public void test(){
System.out.println("这里是A类的一个方法。。。");
}
} interface Binger{
//以后再写接口的时候,就不要再罗里吧嗦的写什么public了 默认都是public abstract的
void test();
}

很明显的不符合需求,那么要怎么办呢?内部类。

public class Linkin extends A {

    public Binger getBinger(){
return new Binger(){ @Override
public void test() {
System.out.println("这里是B接口的实现。。。");
} };
} public static void main(String[] args) {
Linkin linkin = new Linkin();
linkin.test();
linkin.getBinger().test();
} } class A{
public void test(){
System.out.println("这里是A类的一个方法。。。");
}
} interface Binger{
//以后再写接口的时候,就不要再罗里吧嗦的写什么public了 默认都是public abstract的
void test();
}

上面的代码呢?符合需求了,但是如果我想有的时候直接在外部类就使用到binger这个接口里面的那个规范方法呢?有没有稍微高深点的方法呢?回调。

/**
*
* @version 1L
* @author LinkinPark
* @since 2014-11-6
* @motto 梦似烟花心似水,同学少年不言情
* @desc ^现在的代码就有点NB了,我们既可以直接使用外部类2个不同名的方法,来调用A和BInger里面那2个方法,又可以调用一个方法,得到内部类,使用同名的方法
*/
public class Linkin extends A {
//A类里面的Test方法通过继承得到
//这里的这个方法其实就是接口Binger的Test实现方法
public void otherTest(){
System.out.println("这里是B接口的实现。。。");
} private class BingerImpl implements Binger{
@Override
public void test() {
otherTest();
}
} //这里返回上面那个内部类的引用,在以后使用的时候就不用来每次new内部类了
public Binger getBinger(){
return new BingerImpl();
} public static void main(String[] args) {
Linkin linkin = new Linkin();
linkin.test();
//下面2行代码功能一样
linkin.otherTest();
linkin.getBinger().test();
} } class A{
public void test(){
System.out.println("这里是A类的一个方法。。。");
}
} interface Binger{
//以后再写接口的时候,就不要再罗里吧嗦的写什么public了 默认都是public abstract的
void test();
}























































linkin大话面向对象--闭包和回调的更多相关文章

  1. linkin大话面向对象--类和对象

    我们每天在撸码,那么我们在敲什么东西呢?明显的我们在写类,写一个类,写一个接口,写某个接口里面写一些属性,在某个类里面写一个方法,然后以一个对象调用方法,对于j2ee来讲的话,可能还会写一些jsp,静 ...

  2. linkin大话面向对象--多态

    java引用变量有2个类型,一个是编译时类型,一个是运行时类型: 编译时类型:声明的类型,把它看做是什么东西 运行时类型:真正的类型,实际上指的是什么东西 如果编译时类型和运行时类型不同,就出现多态. ...

  3. linkin大话面向对象--GC和jar包

    GC java的垃圾回机制是java语言的重要机制之一.当程序创建对象,数组等引用类型实体时,系统都会在堆内存中为之分配一块内存区,对象就保存在这块内存区中.当这块内存不再被任何变量引用时,这块内存就 ...

  4. linkin大话面向对象--内部类

    内部类说白了就是类中有类 内部类:嵌套类 外部类:宿主类 内部类主要有以下作用:记住了3个字:多继承... 1,内部类提供了更好的封装,可以把内部类隐藏在外部类中,不允许同一个包中的其他类访问该类. ...

  5. linkin大话面向对象--枚举

    枚举类(enum) 其实我们使用到枚举的地方还是很多的,其实我们可以完全人工的来实现枚举的功能.比如说我现在手里的项目我就是自己实现的枚举,说白了,枚举就是一个类的多例模式. 1,使用enum声明,默 ...

  6. linkin大话面向对象--包装类

    Java提倡的万物皆对象,但是数据类型的划分出现了基本数据类型和引用数据类型,那么我们怎么能把基本数据类型称为对象呢? 基本数据类型 包装类 byte Byte short Short int Int ...

  7. linkin大话面向对象--java关键字

    java中的关键字有以下几个,他们不能作任何其它的用途. 发现没,java中的关键字全是小写,java是严格区分大小写的. abstract  default  null  synchronized ...

  8. linkin大话面向对象--初始化块

    java使用构造器来对单个对象进行初始化操作,使用构造器先完成整个java对象的状态初始化,然后将java对象返回给程序,从而让整个java对象的信息更加完整.与构造器作用非常类似的是初始化块,它也可 ...

  9. linkin大话面向对象--组合

    继承是实现类重用的重要手段,但是它有一个最大的坏处:破坏封装.相比之下,组合也是实现类重用的重要方式,但是采用组合方式实现类重用则能提供更好的封装性.比如人有手一样,在人的类中增加一个手的属性. 何时 ...

随机推荐

  1. C#串口发送数据

    使用指定的端口名.波特率.奇偶校验位.数据位和停止位初始化 SerialPort 类的新实例 SerialPort serialPort = new SerialPort("COM3&quo ...

  2. 【数论·错位排列】bzoj4517 排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1428  Solved: 872[Submit][Statu ...

  3. CSS列表及导航条

    大多数网页中都包含某种形式的列表,今天我们就来联系几个基本的导航条.   垂直导航条 注意要点: 去掉默认的项目符号(list-style-type:none),将外边距和内边距都设为0. 以em设置 ...

  4. [转载]github在线更改mysql表结构工具gh-ost

    GitHub正式宣布以开源的方式发布gh-ost:GitHub的MySQL无触发器在线更改表定义工具! gh-ost是GitHub最近几个月开发出来的,目的是解决一个经常碰到的问题:不断变化的产品需求 ...

  5. SQL 语句优化方法

    尽量避免非操作符的使用,在索引上使用 NOT,<> 等操作符,数据库管理系统是不会使用索引的,可以将查询语句转化为可以使用索引的查询. 避免对查询的列的操作,任何对列的操作都可能导致全表扫 ...

  6. Java之CountDownLatch ---控制线程执行顺序

    一,类介绍 这是java.util.concurrent包里的一个同步辅助类,它有两个主要的常用方法  countDown()方法以及await()方法.在完成一组正在其他线程中执行的操作之前,它允许 ...

  7. gradle学习记录

    一.Gradle简介 Gradle是Android现在主流的编译工具,虽然在Gradle出现之前和之后都有对应更快的编译工具出现,但是Gradle的有时就在于它是亲儿子,Gradle确实比较慢,这和它 ...

  8. HashSet源码阅读

    HashSet的实现基于HashMap 看几个简单的初始化方法 public HashSet() { map = new HashMap<>(); } public HashSet(Col ...

  9. python端口扫描器

    吃了个火鸡面后感觉到了怀疑人生!!!!!!!!!妈耶,在也不吃了.思路都给辣没了!!! python端口扫描器代码如下: #-*-coding:utf-8 from socket import * i ...

  10. [bzoj2594][Wc2006]水管局长数据加强版 (lct)

    论蒟蒻的自我修养T_T.. 和noi2014魔法森林基本一样...然而数据范围大得sxbk...UPD:这题如果用lct判联通的话可能会被卡到O(mlogm)..所以最好还是用并查集吧 一开始数组开太 ...