接口域内部类

接口

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

内部类

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

代理

实现任意接口的对象。

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. ant学习(1)

    路径:/home/framework_Study/springinAction/webRoot/WEB-INF <?xml version="1.0" encoding=&q ...

  2. 对plist文件的简单封装

    常常会用到对plist文件的封装 +(NSArray *)LoadFriendsDataFromPlist:(NSString *)plistName{ NSString * filePath = [ ...

  3. iOS的属性声明:retain和strong的区别

    声明属性时用strong或者retain效果是一样的(貌似更多开发者更倾向于用strong).不过在声明Block时,使用strong和retain会有截然不同的效果.strong会等于copy,而r ...

  4. CSS书写规范、顺序和命名规则

    写了这么久的CSS,但大部分前端er都没有按照良好的CSS书写规范来写CSS代码,这样会影响代码的阅读体验,这里总结一个CSS书写规范.CSS书写顺序供大家参考   这些是参考了国外一些文章以及我的个 ...

  5. hdu3714 三分

    Error Curves Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  6. Tree 使用方式

    Traditional Ways of Tree Traversal This page contains examples of some “standard” traversal algorith ...

  7. Fun with dynamicobject dynamic and the settings table

    What came before In my previous post I discussed ways of making the settings table using Generics to ...

  8. INI文件格式

    最近在看git命令,遇到INI文件格式,上网查了一下,把它总结一下: 程序没有任何配置文件,那么它对外是全封闭的,一旦程序需要修改一些参数必须要修改程序代码本身并重新编译,为了让程序出厂后还能根据需要 ...

  9. js各种进制数之间的转换

    计算机中常用的进制数有二进制.八进制.十进制.十六进制 一.十进制 to 其他 var x = 10; // 或定义其他值均可 x.toString(n); // n 代表要转换到的进制,比如n可以为 ...

  10. 如何删除textarea的移动版Safari的阴影?

    如何删除textarea的移动版Safari的阴影? 在iphone的Safari上运行网页,textarea无法使用box-shadow样式,而且顶部有内阴影,如何清除? 添加评论 分享   赞同1 ...