接口的方法默认死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. flutter textfield

    释放光标 FocusScope.of(context).unfocus() 输入类型 keyboardType: TextInputType.number, 键盘右下角按键类型 textInputAc ...

  2. wpf prism4 出现问题:无法加载一个或多个请求的类型。有关更多信息,请检索 LoaderExceptions 属性。

    WPF Prism 框架 程序 出现 问题: 无法加载一个或多个请求的类型.有关更多信息,请检索 LoaderExceptions 属性. 1.开始以为是配置的问题,找了半天,最后原来是有个依赖类库没 ...

  3. 阶段3 2.Spring_03.Spring的 IOC 和 DI_11 set方法注入

    复制AccountServiceImpl类改名叫做AccountServiceImpl2 生成三个属性值的set方法.注入只需要set方法,并不需要get方法 配置bean,用到property这个标 ...

  4. Dojo入门:DOM操作

      作为一款功能齐全的js工具包,dojo提供了统一的DOM操作方法. dojo.byId dojo.byId 函数使您可以通过 id 属性选择一个 DOM 节点.该函数是标准 document.ge ...

  5. 车牌识别1:License Plate Detection and Recognition in Unconstrained Scenarios阅读笔记

    一.WHAT 论文下载地址:License Plate Detection and Recognition in Unconstrained Scenarios [pdf] github 的项目地址: ...

  6. Vue --》this.$set()的神奇用法

    作为一名开发者,我们都知道: data中数据,都是响应式.也就是说,如果操作data中的数据,视图会实时更新: 但在实际开发中,遇到过一个坑:若data中数据类型为对象,方法methods中改变对象的 ...

  7. 线程间的协作(wait/notify/sleep/yield/join)(五)

    一.线程的状态 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线 ...

  8. Tomcat配置:java.lang.UnsatisfiedLinkError: D:\DevelopTool\tool20150402\tomcat\apache-tomcat-8.5.16\bin\tcnative-1.dll: Can't load AMD 64-bit .dll on a IA 32-bit platform

    解决办法: tomcat启动时提示java.lang.UnsatisfiedLinkError: D:\soft\devTool\apache-tomcat-7.0.57\bin\tcnative-1 ...

  9. idea常用快捷键列表

    在使用IntelliJ Idea的时候,使用快捷键是必不可少的.掌握一些常用的快捷键能大大提高我们的开发效率.有些快捷键可以熟练的使用,但是还有另外一些快捷键虽然很好用,但是由于因为没有形成使用习惯或 ...

  10. noip2013day1-货车运输

    题目描述 \(A\)国有\(n\)座城市,编号从 \(1\)到\(n\),城市之间有 \(m\) 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 \(q\) 辆货车在运输货物, 司机们想知 ...