20160923

  • 定义:将一个类的定义放在另一个类的内部;
  • 从外部类的非静态方法之外,创建某个内部类的对象:OutClassName.InnerClassName;
  • 内部类拥有所有其外部类的成员的访问权;
  • 成员内部类不能含有static修饰的变量和方法,因为成员内部类需要先创建了外部类,才能创建它自己的
  • 内部类中生成外部类对象的引用,可以使用OutClassName.this;
 public class DoThis {
void f(){System.out.println("DoThis.f()");}
public class Inner{
public DoThis getOuter(){
return DoThis.this;
}
}
public Inner getInner(){
return new Inner();
}
public static void main(String[] args) {
DoThis dThis = new DoThis();
DoThis.Inner dThisInner = dThis.getInner();
dThisInner.getOuter().f();
}
}
  • 创建内部类的对象,必须使用外部类对象的引用;
 public class DoNew {
public class Inner{};
public static void main(String[] args) {
DoNew doNew = new DoNew();
DoNew.Inner dInner = doNew.new Inner();
}
}
  • 创建嵌套类(静态内部类),不需要外部类对象的引用;
  • private修饰的内部类,只能在其外部类内部访问;protected修饰的内部类,只有其外部类、其外部类的子类、其外部类同一个包中的其他类可以访问;
 class Parcel4{
private class PContents implements Contents {
private int i = 11;
@Override
public int value() { return i; }
}
protected class PDestination implements Destination {
private String label;
private PDestination(String whereTo) { label = whereTo; }
@Override
public String readLabel() { return label; }
}
public Destination destination(String s){ return new PDestination(s); }
public Contents contents(){ return new PContents(); }
Parcel4.PContents t;//PContents是private,只能在Parcel4内部访问
}
public class TestParcel {
public static void main(String[] args) {
Parcel4 p = new Parcel4();
Contents contents = p.contents();
Destination destination = p.destination("Tasmania");
//Parcel4.PContents pc = p.new PContents();//PContents是private,只能在Parcel4内部访问,此处报错
}
}
  • 复杂的内部类:在方法或作用域内定义内部类,理由如下:
  1. 实现了某个类型的接口,可以创建并返回对接口的引用
  2. 需解决复杂的问题,想创建一个类辅助实现解决方案,但不希望这个类被公用
  • 举例

    1、一个定义在方法中的类

 public class Parcel5 {
public Destination destination(String s){
class PDestination implements Destination{
private String label;
private PDestination(String whereTo){
label = whereTo;
}
@Override
public String readLabel() { return label; }
}
return new PDestination(s);
}
public static void main(String[] args) {
Parcel5 p = new Parcel5();
Destination destination = p.destination("Tasmania");
}
}

    2、一个定义在作用域中的类,作用域在方法的内部

 public class Parcel6 {
private void internalTracking(boolean b) {
if (b){
class TrackingSlip {
private String id;
public TrackingSlip(String s) {
id = s;
}
String getSlip(){ return id;}
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
//Can't use it here!Out of scope:
//TrackingSlip ts = new TrackingSlip("x");
}
public void track(){internalTracking(true);}
public static void main(String[] args) {
Parcel6 p = new Parcel6();
p.track();
}
}

    3、一个实现了接口的匿名类

    4、一个匿名类,扩展了有非默认构造器的类

    5、一个匿名类,执行字段初始化

    6、一个匿名类,通过实例初始化实现构造(匿名类没有构造器)

  • 传递给匿名内部类的参数,并且在匿名内部类中使用,该参数须定义为final;
  • 匿名内部类可扩展类,也可以实现接口,但不能同时;如果实现接口,只能实现一个接口;
  • 《Java编程思想》199页,10.6.1再访工厂方法,使用匿名内部类的例子,非常好;
  • 嵌套类:static修饰的内部类,无法访问非静态的外部类对象
  • 嵌套类可以作为接口的一部分,甚至实现外部接口
  •  public interface ClassInInterface {
    void howdy();
    class Test implements ClassInInterface{
    @Override
    public void howdy() { System.out.println("Howdy"); }
    public static void main(String[] args){
    new Test().howdy();
    }
    }
    }
  • 内部类能够多层嵌套,并且能够透明的访问所有它嵌入的外部类的成员
  •  class A{
    private void f(){}
    class B {
    private void g(){}
    public class C {
    void h() {
    g();
    f();
    }
    }
    }
    }
    public class MultiNestingAccess {
    public static void main(String[] args) {
    A a = new A();
    A.B ab = a.new B();
    A.B.C abc =ab.new C();
    abc.h();
    }
    }
  • 为什么需要内部类?
    • 《Java编程思想》204页解释为:每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响;
    • 简单讲就是,内部类实现接口、继承某个类,比外部类实现接口少了许多顾虑,外部类实现接口需要考虑全面,在其他地方是否有影响;
    • 内部类可以继承多个具体类或抽象类,与接口配合,使“多重继承”的解决方案变得完美;
    • 内部类可以有多个实例,每个实例都有自己的状态信息,并且与外部类对象相互独立;
    • 在单个外部类中,可以使多个内部类以不同的方式实现同一个接口,或继承同一个类;
    • 内部类对象的创建,并不依赖于外部类对象的创建
    • 内部类没有“is-a”关系,内部类是独立的实体
  • 闭包,记录了创建闭包的作用域的一些信息,使得闭包可调用其外部作用域数据;内部类就是面向对象的闭包;
  • 回调,
  • 通过内部类提供闭包功能举例:
  •  package com.helei.innerclasses;
    interface Incrementable {
    void increment();
    }
    class Callee1 implements Incrementable {
    private int i = 0;
    @Override
    public void increment() {
    i++;
    System.out.println(i);;
    }
    }
    class MyIncrement {
    public void increment() { System.out.println("Other operation");}
    static void f(MyIncrement mi) {mi.increment();}
    }
    class Callee2 extends MyIncrement {
    private int i = 0;
    public void increment() {
    super.increment();
    i++;
    System.out.println(i);
    }
    private class Closure implements Incrementable {
    public void increment() {
    Callee2.this.increment();
    }
    }
    Incrementable getCallbackReference() {
    return new Closure();
    }
    }
    class Caller {
    private Incrementable callbackReference;
    Caller(Incrementable cbh){callbackReference = cbh;}
    void go() {callbackReference.increment();}
    }
    public class Callbacks {
    public static void main(String[] args) {
    Callee1 c1 = new Callee1();
    Callee2 c2 = new Callee2();
    MyIncrement.f(c2);
    Caller caller1 = new Caller(c1);
    Caller caller2 = new Caller(c2.getCallbackReference());
    caller1.go();
    caller1.go();
    caller2.go();
    caller2.go();
    }
    }
  • 看了好几遍才梳通了以上流程,最好能够敲一遍,通过debug调试过一遍
  • 内部类与控制框架
  • 内部类的继承
  • 内部类覆盖,无效;可以显式继承某内部类;
  • 局部内部类,与匿名内部类的区别

  

Java内部类学习笔记的更多相关文章

  1. 【09-04】java内部类学习笔记

    java中的内部类 静态内部类 成员内部类 方法内部类 匿名内部类 1.静态内部类 class Outer { private static String outer = "outer&qu ...

  2. Java内部类——学习笔记

    参考:http://blog.csdn.net/aaronsi/article/details/187322 和 http://openhome.cc/Gossip/JavaGossip-V1/Inn ...

  3. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  4. Java基础学习笔记总结

    Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...

  5. Android(java)学习笔记211:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  6. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

  7. Kotlin for Java Developers 学习笔记

    Kotlin for Java Developers 学习笔记 ★ Coursera 课程 Kotlin for Java Developers(由 JetBrains 提供)的学习笔记 " ...

  8. 20145213《Java程序设计学习笔记》第六周学习总结

    20145213<Java程序设计学习笔记>第六周学习总结 说在前面的话 上篇博客中娄老师指出我因为数据结构基础薄弱,才导致对第九章内容浅尝遏止地认知.在这里我还要自我批评一下,其实我事后 ...

  9. [原创]java WEB学习笔记95:Hibernate 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

随机推荐

  1. C# 实时折线图,波形图

    此Demo是采用VS自带的Chart图表控件,制作实时动态显示的折线图,和波形图. 涉及到知识如下: Chart 控件,功能强大,可以绘制柱状图,折线图,波形图,饼状图,大大简化了对图的开发与定制. ...

  2. Linux基础介绍【第二篇】

    远程连接Linux的原理 SHH远程连接介绍 当前,在几乎所有的互联网企业环境中,最常用的Linux提供远程连接服务的工具就是SSH软件,SSH分为SSH客户端和SSH服务端两部分.其中,SSH服务端 ...

  3. .NET面试题系列[6] - 反射

    反射 - 定义,实例与优化 在面试中,通常会考察反射的定义(操作元数据),可以用反射做什么(获得程序集及其各个部件),反射有什么使用场景(ORM,序列化,反序列化,值类型比较等).如果答得好,还可能会 ...

  4. 集成基于OAuth协议的单点登陆

    在之前的一篇文章中,我们已经介绍了如何为一个应用添加对CAS协议的支持,进而使得我们的应用可以与所有基于CAS协议的单点登陆服务通讯.但是现在的单点登陆服务实际上并不全是通过实现CAS协议来完成的.例 ...

  5. 向Java技术进军

    前两天有个朋友要我帮忙写个打印机服务,要求能应用在.net .Dephi.和java程序上面.看了下需求不难也就串口操作,所以就在周未写了个Win32的动态库,对于一个曾经写MFC程序的.net程序员 ...

  6. 一种简单,轻量,灵活的C#对象转Json对象的方案(续)

    本文参考资料 一种简单,轻量,灵活的C#对象转Json对象的方案 [源码]Literacy 快速反射读写对象属性,字段 一段废话 之前我已经介绍了这个方案的名称为JsonBuilder,这套方案最大的 ...

  7. .NET 基础一步步一幕幕[out、ref、params]

    out.ref.params out: 如果你在一个方法中,返回多个相同类型的值的时候,可以考虑返回一个数组. 但是,如果返回多个不同类型的值的时候,返回数组就不行了,那么这个时候, 我们可以考虑使用 ...

  8. 初学者--bootstrap(六)组件中的字体图标----在路上(9)

    组件---字体图标 无数可复用的组件,包括字体图标.下拉菜单.导航.警告框.弹出框等更多功能. 1.如何使用:        出于性能的考虑,所有图标都需要一个基类和对应每个图标的类.把下面的代码放在 ...

  9. SQL Server 远程连接出错~~~无法访问服务器

    异常处理汇总 ~ 修正果带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4599258.html 代理开一下 tcp/ip协议开一下 收工

  10. 【.NET深呼吸】元组数据(Tuple)

    各位观众,大家好,欢迎收看由火星电视台直播的<老周吹牛>节目,注意:本节目没有任何技术含量,如果您没有兴趣,请砸掉电视机. 今天说一下System命名空间下的一个数据类型——Tuple,翻 ...