接口的方法默认死public,接口的属性默认为public static final。

为什么要接口,而不是使用抽象类。一个对象只能继承一个类,却可以实现多个接口。

clone:

Object的浅拷贝

Object类的默认拷贝机制是浅拷贝:对于拷贝对象的属性:基本类型属性,拷贝值,对象属性,拷贝引用。

Object将clone设为protected方法,无法在外部调用。如果要使用,必须在使用的类里,将它设置为public。如下:

  1. @Override
  2.    public Person clone() throws CloneNotSupportedException {
  3.       return (Person)super.clone();
  4.    }

关于CloneNotSupportedException:

当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。

重写 clone 方法的应用程序也可能抛出此异常,指示不能或不应克隆一个对象。

所以,还要在类的声明中加入implements Cloneable。

上面说的都是调用Object的默认clone的限制,如果你自己写Clone方法,是不会抛出CloneNotSupportedException异常的。如:

  1. @Override
  2.    public Person clone() {
  3.       Person p = new Person(this.id);
  4.       return p;
  5.    }

关于Cloneable 接口

此类实现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。

如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常。

按照惯例,实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。请参阅 Object.clone(),以获得有关重写此方法的详细信息。

注意,此接口不包含 clone 方法。因此,因为某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。

所以,Cloneable是标记接口。

深拷贝

如果要实现深拷贝,就要手动会所有可变的对象属性进行克隆。

数组克隆

所有的数组都包含了一个clone方法,这个方法是public的,可以通过它对数组克隆。

内部类

内部类(inner class)是定义在另一个类中的类.为什么需要使用内部类呢?其主要原因有以下三点:

  • 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据.
  • 内部类可以对同一个包中的其他类隐藏起来.
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名(annoymous)内部类比较便捷.

只有内部类可以是私有类,而常规类只可以具有包可见性,或公有可见性.

内部类可以访问外部类的属性。即使是私有的。也可以直接访问,不需要this或者super这种。

内部类的特殊语法规则

内部类其实维护了一个外部类的引用。所以可以访问外部类的属性。

我们可以在内部类里使用OuterClass.this 来访问外部类的引用。

内部类是一种编译器现象,与虚拟机无关.编译器将会把内部类翻译成用$分隔外部类名与内部类名的常规类文件,而虚拟机则对此一无所知.

局部内部类

可以在一个方法中定义局部类.

  1. public void start()  
  2. {  
  3.     class TimePrinter implements ActionListener  
  4.     {  
  5.         public void actionPerformed(ActionEvent event)  
  6.         {  
  7.             Date now = new Date();  
  8.             System.out.println("At the tone, the time is " + now);  
  9.             if (beep)  
  10.                 Toolkit.getDefaultToolkit().beep();  
  11.         }  
  12.     }  
  13.     ActionListener listener = new TimePrinter();  
  14.     Timer t = new Timer(interval, listener);  
  15.     t.start();  
  16. }  

局部类不能用 public 或 private 访问说明符进行声明,它的作用域被限定在声明这个局部类的块中.

局部类有一个优势,即对外部世界可以完全地隐藏起来.即使TalkingClock类中的其他代码也不能访问它.

与其他内部类相比较,局部类还有一个优点,它们不仅能够访问它们的外部类,还可以访问局部变量.不过那些局部变量必须被声明为 final,下面是一个典型的示例.这里,将TalkingClock构造器的参数interval和beep移至start方法中.

  1. public void start(int interval, final boolean beep)  
  2. {  
  3.     class TimePrinter implements ActionListener  
  4.     {  
  5.         public void actionPerformed(ActionEvent event)  
  6.         {  
  7.             Date now = new Date();  
  8.             System.out.println("At the tone, the time is " + now);  
  9.             if (beep)  
  10.                 Toolkit.getDefaultToolkit().beep();  
  11.         }  
  12.     }  
  13.     ActionListener listener = new TimePrinter();  
  14.     Timer t = new Timer(interval, listener);  
  15.     t.start();  
  16. }  

请注意,TalkingClock类不再需要存储实例变量beep了,它只是引用start方法中的beep参数变量.
    这看起来好像没什么值得大惊小怪的,程序

  1. if (beep) ...  

毕竟在start方法内部,为什么不能访问beep变量的值呢?仔细看一下调用流程:
    1.调用start方法
    2.调用内部类TimePrinter的构造器,以便初始化对象变量listener
    3.将listener引用传递给Timer构造器,定时器开始计时,start方法结束.此时start方法的beep参数变量不复存在.
    4.然后,actionPerformed方法执行 if(beep) ...
    为了能够让actionPerformed方法工作,TimePrinter类在beep域释放之前将beep域用start方法的局部变量进行备份.实际上也是这样做的.
    局部类的方法只可以引用定义为 final 的局部变量.鉴于此情况,在列举的实例中,将beep参数声明为 final,对它进行初始化后不能够再进行修改,因此,就使得局部变量与局部类内建立的拷贝保持一致.

个人理解:因为局部变量在局部方法块结束之后就结束了它的生命,但是内部类其实是可以作为参数传递给外部的对象。所以把局部变量设置为final,所以其实内部类在引用外部的局部变量的时候,是引用的副本,我们对副本进行修改是不能映射到原始版本的,为了避免逻辑混乱,就把原始版本设置为final,不能修改它。

匿名局部类

将局部内部类的使用再深入一步,假如只创建这个类的一个对象,就不必命名了.这种被被称为匿名内部类(annoymous inner class).

匿名内部类,是一种局部内部类。所以也有局部内部类的特征。

静态内部类

如果使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类对象.为此,可以将内部类声明为 static,以便取消产生的引用.

静态内部类的不能对生成它的外围类对象的引用,因为它不是对象生成的,是属于包围它的类的。

注释:在内部类不需要访问外围类对象的时候,应该使用静态内部类.
注释:声明在接口中的内部类自动称为 static 和 public 类.

代理

利用代理(proxy)可以在运行时创建一个实现了一组给定接口的新类.这个功能只有在编译时无法确定需要实现哪个接口时才有必要使用.对于应用程序设计人员来说,遇到这种情况的机会很少.但对于系统程序设计人员来说,代理带来的灵活性非常重要.
    假设有一个表示接口的Class对象,它的确切类型在编译时无法知道.这确实有些难度.要想构造一个实现这些接口的类,就需要使用newInstance方法或反射找出这个类的构造器.但是,不能实例化一个接口,需要在程序处于运行状态时定义一个新类.
    为了解决这个问题,有些程序将生成代码;将这些代码放置在一个文件中;调用编译器,然后再加载结果类文件.但这样做的速度会比较慢,并且需要将编译器与程序放在一起.而代理机制则是一种更好的解决方案.代理类可以在运行时创建全新的类.这样的代理类能够实现指定的接口.尤其是,它具有下列方法:
    指定接口所需要的全部方法
    Object类中的全部方法,例如,toString,equals等
    然而,不能在运行时定义这些方法的新代码,而是要提供一个调用处理器(invocation handler).调用处理器是实现了InvocationHandler接口的类对象.在这个接口中只有一个方法:

  1. Object invoke(Object proxy, Method method, Object[] args);  

无论何时调用代理对象的方法,调用处理器的invoke方法都会被调用,并向其传递Method对象和原始的调用参数.

Java 接口和内部类的更多相关文章

  1. 解决Java接口内部类的main()方法无法打印输出的问题

    问题源自<Thinking in Java>关于内部类的章节,例子如下: public interface ClassInInterface{ void howdy(); public c ...

  2. [core java学习笔记][第六章接口与内部类]

    接口域内部类 接口 描述类具有什么功能,不给出具体实现. 内部类 用于设计协作关系的类集合 代理 实现任意接口的对象. 6.1 接口 接口声明 public interface Comparable ...

  3. Java核心技术卷一基础知识-第6章-接口与内部类-读书笔记

    第6章 接口与内部类 本章内容: * 接口 * 对象克隆 * 接口与回调 * 内部类 * 代理 接口技术主要用来描述类具有什么功能,而并不给出每个功能的具体实现.一个类可以实现(implement)一 ...

  4. Java程序设计8——抽象类、接口与内部类

    1 抽象类 当编写一个类时,常常会为该类定义一些方法,这些方法用以描述该类的行为方式,那么这些方法都有具体的方法体.但在某些情况下,某个父类并不需要实现,因为它只需要当做一个模板,而具体的实现,可以由 ...

  5. JAVA基础之接口与内部类

    接口与内部类 目录 接口与内部类 1. Lambda表达式 1. 关于懒计算 2. Predicate接口 3. 关于方法引用 4. 关于构造器引用 5. 关于变量的作用域 2. 内部类 1. 局部内 ...

  6. Unit06 - 抽象类、接口和内部类(下) 、 面向对象汇总

    Unit06 - 抽象类.接口和内部类(下) . 面向对象汇总 1.多态:  1)意义:    1.1)同一类型的引用指向不同的对象时,有不同的实现        行为的多态:cut().run(). ...

  7. java基础之 内部类

    Java中的内部类共分为四种: 静态内部类static inner class (also called nested class) 成员内部类member inner class 局部内部类loca ...

  8. java 笔记(2) —— 内部类的作用

    一.内部类简介 个人觉得内部类没多少研究价值,GUI中的事件响应算是非常典型的应用了. Java内部类其实在J2EE编程中使用较少,不过在窗口应用编程中特别常见,主要用来事件的处理.其实,做非GUI编 ...

  9. JAVA 第二天 内部类

    package com.company; /** * Created by Administrator on 2016/8/23. */ public class Outter {//生成的字节码文件 ...

随机推荐

  1. Custom Configuration 的两种方法:2.XmlSerializer XmlAttribute

    第二种:XmlSerializer XmlAttribute 1.CustomConfiguration.xml 2.CustomConfigurationSetting.cs 3.CustomCon ...

  2. 使用 tcpdump 抓包分析 TCP 三次握手、四次挥手与 TCP 状态转移

    目录 文章目录 目录 前文列表 TCP 协议 图示三次握手与四次挥手 抓包结果 抓包分析 TCP 三次握手 数据传输 四次挥手 TCP 端口状态转移 状态转移 前文列表 <常用 tcpdump ...

  3. 63不同路径II

    题目: 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” ).机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为“Finish”).现在考 ...

  4. bat中if语句的用法

    (作者:sanqima ) 例如,删除“C:\Documents and Settings\Administrator\桌面\T1\txt\批处理实验\unit1”里的a.txt文件,使用if的代码如 ...

  5. Linux 常用命令之 mv cp scp

    1.mv 命令是move的缩写,用于文件(或文件夹)移动的. 1)将 luna 目录下的文件 a.txt,移动到 miracle 目录下: mv ./luna/a.txt ./miracle/ 2)将 ...

  6. Oracle 数据字典视图(V$,GV$,X$)

    常用的几个数据字典: user_objects : 记录了用户的所有对象,包含表.索引.过程.视图等信息,以及创建时间,状态是否有效等信息,是非DBA用户的大本营.想知道自己有哪些对象,往这里查. u ...

  7. 手写BP(反向传播)算法

    BP算法为深度学习中参数更新的重要角色,一般基于loss对参数的偏导进行更新. 一些根据均方误差,每层默认激活函数sigmoid(不同激活函数,则更新公式不一样) 假设网络如图所示: 则更新公式为: ...

  8. spring实战第五版总结

  9. vue如何实现热更新

    我们都知道,对于node来说,前端vue代码的迭代节奏是很快的,可能一周要迭代几次,但是node的迭代却没那么平凡,可能一周更新一次甚至更久,那么为了node服务的稳定,减少node服务的发布次数,是 ...

  10. 【VS开发】使用WinPcap编程(2)——打开网络设备并且开始捕获数据包

    这里需要特别强调的一个数据结构是pcap_t,它相当于一个文件描述符,代表一个已经打开的设备.我们对这个设备进行操作,就是对这个文件描述符进行操作. 首先是打开一个已知的设备,使用pcap_open( ...