接口的方法默认死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. 阶段3 2.Spring_09.JdbcTemplate的基本使用_5 JdbcTemplate在spring的ioc中使用

    resources下新建File文件 bean.xml 配置jdbcTemplate 注入DataSource 新建测试方法 复制demo1改个名字叫做demo2 编写Insert的方法

  2. 阶段3 2.Spring_01.Spring框架简介_02.今日课程内容介绍

    spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...

  3. java调用支付宝 支付api 【沙箱环境】

    由于支付宝支付api需要各种备案,但学校项目需要引入支付功能  先演示  ,所以采用 沙箱环境 一.登录支付宝 开放平台 及配置相关 https://openhome.alipay.com/platf ...

  4. DJANGO MODEL FORMSETS IN DETAIL AND THEIR ADVANCED USAGE

    Similar to the regular formsets, Django also provides model formset that makes it easy to work with ...

  5. P2085 最小函数值

    题目链接hhh:https://www.luogu.org/problemnew/show/P2085好嘛,运气真好,刚A掉序列合并,正好碰到这题,可以说是序列合并的升级版了 那么简单说一下思路,首先 ...

  6. python基本成分

    一.常量 常量即代表不变的量,其实在python里不存在真正不变的量,只不过潜规则在我们想定义一个常量的时候变量名为大写即为常量: 比如:一个人的年纪不断的增长,那么年纪就叫常量,如果这个人死了,那么 ...

  7. 【神经网络与深度学习】【CUDA开发】caffe-windows win32下的编译尝试

    [神经网络与深度学习][CUDA开发]caffe-windows win32下的编译尝试 标签:[神经网络与深度学习] [CUDA开发] 主要是在开发Qt的应用程序时,需要的是有一个使用的库文件也只是 ...

  8. 【神经网络与深度学习】深度学习实战——caffe windows 下训练自己的网络模型

    1.相关准备 1.1 手写数字数据集 这篇博客上有.jpg格式的图片下载,附带标签信息,有需要的自行下载,博客附带百度云盘下载地址(手写数字.jpg 格式):http://blog.csdn.net/ ...

  9. Idea 竖选文本、竖向选择、横向纵向选择文本代码

    在使用Idea的时候,可能需要在相同类型的文字中增加数据,所以Idea提供一种列式选择方式,提高开发的效率. 如果需要使用,我们可以选中代码,右键单击,在弹出的菜单中选中[Column Selecti ...

  10. 思考--PostgreSQL在与mysql的比较中稍微弱势项

    PostgreSQL在与mysql的比较中稍微弱势项: 1.都是堆表,没有所谓的聚集索引表,其实问题不大,聚集索引表也只是在使用聚集索引那些列有加速,而且pg也有聚集索引,只不过要定期重建. 2.mv ...