接口域内部类

接口

描述类具有什么功能,不给出具体实现。

内部类

用于设计协作关系的类集合

代理

实现任意接口的对象。

6.1 接口

接口声明

public interface Comparable
{
int compareTo(Object other); //接口声明中自动属于public 所以不需要public
}

接口声明不能提供的功能

  • 不能含有实例域
  • 不能在接口中实现方法

注意:提供实例域和方法实现的任务应该由接口实现的那个类完成


接口实现

需要完成两点

  • 将类声明为实现给定的接口

    使用implements这个关键词

    class Employee implements Comparable<Emoloyee>
  • 对接口中的所有方法进行定义

    public int compareTo(Employee other)
    {
    return Double.compare(salary,other.salary);
    }

    实现接口时必须把声明public

具体代码见附录


常用API

  • java.lang.Compareable<T>

    int compareTo(T other)
    用这个对象与other比较,小于other返回负值,相等返回0,大于返回正值
  • java.util.Arrays

    static void sort(Object[] a)
    利用mergesort算法对数组a的元素进行排序,要求数组的类实现了Comparable接口的类
  • java.lang.Integer

    static int compare(int x,int y)
    比较x,y大小 x<y 返回负值

6.1.1 接口特性

  • 可以使用instanceof判断一个对象是否有某个特定的接口

    if(anObject instanceof Comparable){...}
  • 接口还能被扩展

    public interface Powered extends Moveable
    {
    double milesPerGallon();
    }
  • 一个类可以有多个接口

    class Employee implements Cloneable,Comparable

6.1.2 接口与抽象类

  • 接口类似抽象类,但是Java并不支持多个抽象类,即多继承,以避免复杂;
  • C++中的接口就是利用多继承完成

6.2对象克隆

对于每一个类,都需要如下三个判断

  1. 默认clone是否满足要求
  2. 默认clone是否能够通过调用可变对象的clone得到修补
  3. 是否不应该使用clone

如果选择1,2 必须

  • 实现Cloneble 接口
  • 使用public访问修饰符重新定义clone方法

在这里,Cloneable接口的出现与接口的正常使用没有任何关系。尤其是,接口并没有制定clone方法,这个方法继承自Object,接口在这里只是作为一个标记,表明类设计者知道要进行克隆处理。如果没有这个接口,会出现已检验异常(checked exception)

Cloneable接口是Java提供的几个标记接口(tagging interface)之一

  • 使用super.clone()来调用Object的方法

    class Employee implements Cloneable
    {
    public Employee clone()
    {
    return (Employee) super.clone(); //仅仅是一个浅拷贝而已
    }
    }

下面是 深拷贝 clone的实例

class Employee implements Cloneable
{
...
public Employee clone() throws CloneNotSupportedException
{
// call Object.clone()
Employee cloned=(Employee) super.clone();
// clone mutable files
clone.hireDay=(Date) hireDay.clone();
}
}

必须谨慎使用clone,一旦为Employee类定义了clone方法,任何人都可以利用它克隆Manager对象。Employee的克隆方法能完成这项重任吗?很难确定。标准库只有5%实现了clone

代码见附录

6.3 接口与回调

定义

回调(callback)是一种常见的程序设计模式,在这种模式中,可以指出某个特定事件发生时应该采取的动作。例如: 可以指出再按下鼠标或选择某个菜单项时应采取什么行动。

定时器也是一种回调

定时器的代码见代码库

6.4 内部类

为什么要用内部类

  1. 内部类方法可以访问该类定义的所在的作用域的所有数据, 包括私有数据。(继承的类不行)
  2. 内部类可以对同一个包中的其他类隐藏。(即使定义成public也无所谓)
  3. 当想要定义一个回调函数且不想编写大量代码时,使用匿名(anonymous)内部类比较便捷

6.4.1 使用内部类访问对象状态

  • 可以直接访问。

  • InnerClassTest见代码库。

6.4.2 内部类的特殊语法规则

  • OuterClass.this表示外围内引用。

    例:

    public void actionPerformd(ActionEvent event)
    {
    ...
    if(TalkingClock.this.beep) Toolkit.getDefaultToolkit().beep();
    }
  • 采用outObject.new InnerClass() 来声明构造,具体见下面代码

  • 采用OuterClass.InnerClass 在外围类的作用域之外引用内部类

    • 在OuterClass

      既可以

      TimerPrinter listener =new TimerPrinter();

      又能

      TimerPrinter listener =this.new TimerPrinter();
    • 在main中

      只能

      TalkingClock clock=new TalkingClock(1000,true);
      TalkingClock.TimerPrinter listener = clock.new TimerPrinter();

6.4.3 内部类是否有用,必要安全

  • 内部类是一个编译器现象,与虚拟机无关。
  • 编译器会把类翻译成用$分隔外部类和内部类的常规类文件,虚拟机对此一无所知。

    如`TalkingClock$TimerPrinter.class

  • 内部类实际上通过一个access$000(outer)的方法来调用外围的私有变量

  • 注意如果内部类访问了私有数据域,就有可能通过附加在外围类所在包中的其他类访问它们,但做这些事情需要高超的技巧,程序员不可能无意之中就获得权限。

6.4.4 局部内部类

  • 在TalkingClock示例代码中就会发现,TimePrinter这个类只在start方法中创建这个类型的对象时使用了一次,在这种情况下可以使用局部内部类。
  • 对外部世界完全隐藏

      public void start()
    {
    class TimerPrinter implements ActionListener
    {
    public void actionPerformed(ActionEvent event)
    {
    int a=interval;
    Date now = new Date();
    System.out.println("At the tone,the time is "+now);
    if(beep) Toolkit.getDefaultToolkit().beep();
    }
    }
    ActionListener listener =new TimerPrinter();
    Timer t=new Timer(interval,listener);
    t.start();
    }

6.4.5 由外部方法访问final变量

  • 内部类只能访问final局部变量
  • 如果想要更新,使用一维final数组
  • 这种用法以后慢慢细细思考 很复杂的样子

6.4.6 匿名内部类

  • 假如只创建这个类的一个对象,就不必命名了。这种类被称为匿名内部类(anonymous inner class)

    public void start(int interval,final boolean beep)
    {
    ActionListener listener =new ActionListener()
    {
    public void actionPerformed(ActionEvent event)
    {
    int a=interval;
    Date now = new Date();
    System.out.println("At the tone,the time is "+now);
    if(beep) Toolkit.getDefaultToolkit().beep();
    }
    }
    Timer t=new Timer(interval,listener);
    t.start();
    }
  • 通常的语法格式是

    new SuperType(construction parameters)
    {
    inner class methods and data
    }
  • 还能够重载方法//实质是继承了后覆盖

    for(int i=0;i<dates.length;i++)
    dates[i]=new Date()
    {
    public int compareTo(Date other)
    {
    counter[0]++;
    return super.compareTo(other)
    }
    };
  • 双括号初始化

    invite(new ArrayList<String>() {{add("Harry");add("Tony");}})

    注意这里的括号,外括号建立了ArrayList的一个匿名子类。内层括号则是一个对象构造块

  • 不常用: 在静态方法,知道当前类名

    new Object(){}.getClass().getEnclosingClass()

6.4.7 静态内部类

  • 有时候使用内部类只是为了把一个类隐藏到另一个类的内部。并不需要内部类引用外围类对象。为此可以将内部类声明为static,以便取消引用

        Class ArrayAlg
    {
    public static class Pair
    {
    ...
    }
    }

6.5 代理

有点难以后补

[core java学习笔记][第六章接口与内部类]的更多相关文章

  1. Java 学习笔记 ------第六章 继承与多态

    本章学习目标: 了解继承的目的 了解继承与多态的关系 知道如何重新定义方法 认识java.lang.object 简介垃圾回收机制 一.继承 继承是java面向对象编程技术的一块基石,因为它允许创建分 ...

  2. [core java学习笔记][第十一章异常断言日志调试]

    第11章 异常,断言,日志,调试 处理错误 捕获异常 使用异常机制的技巧 使用断言 日志 测试技巧 GUI程序排错技巧 使用调试器 11.1 处理错误 11.1.1异常分类 都继承自Throwable ...

  3. [core java学习笔记][第四章对象与类]

    4.3 用户自定义类 4.3.1 类数组的声明 需要两次new Employee[]=staff=new Employedd[3]; staff[0]=new Employedd(参数列表); sta ...

  4. [core Java学习笔记][第一二三章基本语法]

    基本语法 1 Java 简单的类型 1.1 一些常量 正无穷大 Double.POSITVE_INFINITY 负无穷大 Double.NEGATIVE_INFINITY 不存在 Double.NaN ...

  5. [core java学习笔记][第五章继承]

    5.1 类.超类和子类 定义 class Manager extends Employee { 添加方法和域 } 权限 派生类不能使用基类的私有变量 派生类调用基类的方法 利用super这个关键词 s ...

  6. JVM学习笔记-第六章-类文件结构

    JVM学习笔记-第六章-类文件结构 6.3 Class类文件的结构 本章中,笔者只是通俗地将任意一个有效的类或接口锁应当满足的格式称为"Class文件格式",实际上它完全不需要以磁 ...

  7. sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)

    sql server 关于表中只增标识问题   由于我们系统时间用的过长,数据量大,设计是采用自增ID 我们插入数据的时候把ID也写进去,我们可以采用 关闭和开启自增标识 没有关闭的时候 ,提示一下错 ...

  8. 20145330《Java学习笔记》第一章课后练习8知识总结以及IDEA初次尝试

    20145330<Java学习笔记>第一章课后练习8知识总结以及IDEA初次尝试 题目: 如果C:\workspace\Hello\src中有Main.java如下: package cc ...

  9. Core Java 学习笔记——1.术语/环境配置/Eclipse汉化字体快捷键/API文档

    今天起开始学习Java,学习用书为Core Java.之前有过C的经验.准备把自己学习这一本书时的各种想法,不易理解的,重要的都记录下来.希望以后回顾起来能温故知新吧.也希望自己能够坚持把自己学习这本 ...

随机推荐

  1. CentOS CVS安装使用

    CentOS CVS安装使用   一.CVS简介 CVS(Concurrent Versions System)版本控制系统:是一种GNU软件包,CVS是一个C/S系统,主要用于在多人开发环境下的源码 ...

  2. Javascript进阶篇——(DOM—节点---获取浏览器窗口可视区域大小+获取网页尺寸)—笔记整理

    浏览器窗口可视区域大小获得浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)的方法:一.对于IE9+.Chrome.Firefox.Opera 以及 Safari: • window.innerH ...

  3. js Date扩展Format()函数

    Date.prototype.Format = function (formatStr) { var str = formatStr; var Week = ['日', '一', '二', '三', ...

  4. Objective-C文件和目录操作,IOS文件操作,NSFileManager使用文件操作

    http://blog.csdn.net/swingpyzf/article/details/15185767

  5. 关于WinForm/Web如何使用缓存Cach

    原文链接:http://www.cnblogs.com/zfanlong1314/archive/2013/03/28/2986403.html Cache 的绝对到期与滑动到期 绝对到期:设置绝对过 ...

  6. 1、solr 查询

    solr查询参数: q  查询的关键字,此参数最为重要,例如,q=id:1,默认为q=*:*, fl  指定返回哪些字段,用逗号或空格分隔,注意:字段区分大小写,例如,fl= id,title,sor ...

  7. Java的一点内容(2)

    1 面向对象的三个原则 封装性 封装的基本单元是类(class),类是一个抽象的逻辑结构,而类的对象是一个真实的物理实体:类的目的是封装复杂性,在类内部存在隐藏实现复杂性机制: 封装(encapsul ...

  8. UVa10651(记忆化搜索)

    题意: 给一串-和o组成的字符串,你可以把“-oo"变成”o--",可以把“oo-”变成“--o",问最后最少有多少个o. 状态压缩 ,记忆化搜索 code: #incl ...

  9. show_space/get_alert_log/get_trace_file

    1.get_alert_log 获取alert文件的路径和名称 set serveroutput on        --设置输出,让sqlplus在屏幕上可以输出.(要加入到login.sql中!) ...

  10. Java笔记--java一行一行写入或读取数据

    转自 Ruthless java一行一行写入或读取数据 链接:http://www.cnblogs.com/linjiqin/archive/2011/03/23/1992250.html 假如E:/ ...