The inner class is a valuable feature because it allows you to group classes that logically belong together and to control the visibility of one within the other. However, it's important to understand that inner classes are distinctly different from composition.

  The kind of code you can write with inner classes is more elegant and clear.

  More typically, an outer class will have a method that returns a reference to an inner class.

  If you want to make an object of the inner class anywhere except from within a non-static method of the outer class, you must specify the type of that object as OuterClassName.InnerClassName.

The linke to the outer class

  When you create an inner class, an object of the  inner class has a link to the enclosing object that made it, and so it can access the members of the enclosing object. In addition, inner class have access rights to all the elements in the enclosing class.

  The inner class secretly captures a reference to the particular object of the enclosing class that was responsible for creating it. An object of an inner class can be created only in association with an objecct of the enclosing class (When ,as you shall see, the inner class is non-static).

Using .this and .new

  If you need to produce the reference to the outer-class object, you name the outer class followed by a dot and this.

  Sometimes you want to tell some other object to create an object of one of its inner classes. To do this you must provide a reference to the outer-class object in the new expression, using the .new syntax.

  DotNew dn = new DotNew();

  DotNew.Inner dni = dn.new Inner();

  It's not possible to create an object of the inner class unless you already have an object of the outer class. This is because the object of the inner class is quietly connected to the object of the outer class that it was made from. However, if make a nested class (a static inner class), then it doesn't need a reference to the outer-class object.

Inner classes and upcasting

  Inner class really come into their own (有了用武之地) when you start upcasting to a base cass, and in particular to an interface.

Inner classes in methods and scopes

  In general, the code that you'll write and read involving inner classes will be "plain" inner classes that are simple and easy to understand. However, the syntax for inner classes covers a number of other, more obscure techniques. Inner classes can be created within a method or even an arbitrary scope. Theare are two reasons for doing this:

  1. As shown previously, you're implementing an interface of some kind so that you can create and return a reference.

  2. You're solving a complicated problem and you want to create a class to aid in youre solution, but you don't want to publicly available.

  The class created within the scope of a method is called a local inner class.

  The fact that the class is placed inside a method doesn't mean that The  object of the class is not a valid object once the method returns.

  The class is nested inside the scope of an if statement. This does not mean that the class is conditionally created--it gets compiled along with everything else. However, it's not available outside the scope in which it is defined. Other than that, it looks just like an ordinary class.

Anonymous inner classes

  public Contents contents() {

    return new Contents() { // Insert a class definition

      private int i = 11;

      public int value() { return i;}

    }; // Semicolon required in this case

  }

  What this strange syntax means is "Create an object of an anonymous class that's inherited from Contents." The reference returned by the new expression is automatically upcast to a Contents reference.

  The anonymous  inner-class syntax is a shorthand for:

  class Mycontents implements Contents {

    private int i = 11;

    public int value() { return i;}

  }

  public Contents contents() {return new MyContents();}

  return new Wrapping(x) { // Pass constructor argument.

    public int value() {

      return super.value() * 47;

    }

  }; // Semicolon required

  

  public Destination destination (final String dest) {

    return new Destination() {

      private String label = dest; // initialization

      public String readLabel() {return label; }

    };

  }

  虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或参数的作用域只在这个方法内部有效。因为编译的时候内部类和方法在同一级别上,所以方法中的变量或参数只有为final,内部类才可以引用。

  You can't have a named constructor in an anonymous class (since there's no name!), but with instance initialization, you can, in effect, create a constructor for an anonymous inner class.

  return new Base(j) {

    { print("Inside instance initializer"); }

    public void f() {...};

  }

  It's limited; you can't overload instance initializers, so you can have only one of these constructors.

  Anonymous inner class are somewhat limited compared to regular inheritance, because they can either extend a class or implement an interface, but not both. And if you do implement an interface, you can only implement one.

  Factory Method revisited

  You often only need a single factory object, and so here it has been created as a static field in the Service implementation by annoymous inner class.

Nested classes

  A nested class means:

    1. You don't need an outer-class object in order to create an object of a nested class.

    2. You can't access a non-static outer-class object from an object of a nested class.

  Fields and methods in ordinary inner classes can only be at the outer level of a class, so ordinary inner classes cant have static data, static fields, or nested classes. Howover, nested classes can have all of these.

  A nested class does not have a special this reference, which makes it analogous to a static method.

  Classes inside interfaces

  Any class you put inside an interfae is automatically public and static.

  You can even implement the surrounding interface in the inner class.

  It's convenient to nest a class inside an interface when you want to create some common code to be used with all different implementations of that interface.

  Java TestBed$Tester

  Reaching outward from a multiply nested class

Why inner classes ?

  an inner class provides a kind of window into the outer class.

  A question that cuts to the heart of inner classes is this: If I just need a reference to an interface, why don't I just make the outer class implement that interface? The answer is that you can't always have the convenience of interfaces-sometimes you're working with implementations.

  Each inner class can independently inherit from an implementation. Thus, the inner class is not limited by whether the outer class is already inheriting from an implementation

  One way to look at the inner class is as the rest of the solution of the multiple-inheritance problem.

  If you didn't need to solve the "multiple implementation inheritance" problem, you could conceivably code around everything else without the need for inner classes. But with inner classes you have these additional features:

  1. The inner class can have multiple instances, each with its own state information that is independent of the information in the outer class object.

  2. In a single outer class you can have several inner classes, each of which implements the same interface or inherits from the same class in a different way.

  3. The point of creation of the inner-class object is not tied to the creation of the outer-class obect (??)

  4. There is no potentially confusing "is-a" relationship with the inner class; it's a separate entity.

  Closures & callbacks (闭包和回调)

  A closure is a callable object that retains information from the scope in which it was created. From this definition, you can see that an inner class is an object-oriented closure, because it doesn't just contain each piece of iinformation from the outer-class object ("the scope in which it was created"), but it automatically holds a reference back to the whole outer-class object, where it has permission to manipulate all the members, even private ones.

  With a callback, some other object is given a piece of information that allows it to call back into the originating object at some later point. But a callback is implemented using a pointer.

  The closure provided by the inner class is a good solution-more flexible and far safer than a pointer.

  Inner classes & control frameworks

  An application framework is a class or a set of classes that's designed to solve a particular type of problem.(应用框架的定义:用于解决某种类型问题的一个类或一组类)

  application framework is an example of the Template Method design pattern (模板方法设计模式)

  The Template Method contains the basic structure of the algorithm, and it calls one or more overrideable methods to complete the action of that algorithm.

  设计模式就是将变化的事物和保存不变的事物分离开。

  Template Method 就是保持不变的部分,而可覆盖的方法就是变化的部分

  A control framework is a particular type of application framework dominated by the need to response to events. (控制框架是一类特殊的应用程序框架,用来解决响应事件的需求)

  A system the primarily responds to events is called an event-driven system. (事件驱动系统)

  Java Swing library is a control framework

  

  public class Controller {

    private List<Event> eventList = new ArrayList<Event>();

    public void addEvent(Event c) { eventList.add(c); }

    public void run() {

      while(eventList.size() > 0)

        // Make a copy so you're not modifying the list

        // while you're selecting the elements in it:

        for (Event e : new ArrayList<Event>(eventList))

          if (e.ready()) {

            System.out.println(e);

            e.action(); // 变动部分

            eventList.remove(e);

          }

    }  

  }

  The is where inner class comme into play. They allow two things:

    1. The entire implementation of a control framework is created in a single class, thereby encapsulating everything that's unique about that implementation. Inner classes are used to express the many different kinds of action() necessary to solve the problem.

    2. Inner classes keep this implementation from becoming awkward, since you're able to easily access any of the members in the outer class. Without the ability the code might become unpleasant enough that you'd end up seeking an alternative.

Inheriting from inner classes

  Because the inner-class constructor must attach to a reference of the enclosing class object, things are slightly complicated when you inherit from an inner class. The problem is that the "secret" reference to the enclosing class object must be initialized, and yet in the derived class there’s no longer a default object to attach to. You must use a special syntax to make the association explicit

  class WithInner {

    class Inner {}

  }

  public class InheritInner extends WithInner.Inner {

    // ! InheritInner() {} // Won't compile

    InheritInner(WithInner wi) { //******

      wi.super();

    }

  }

Can inner classes be overridden ?

  class Egg {

    private Yolk y;

    protected class Yolk {

      public Yolk { print("Egg.Yolk)"); }

    }

    public Egg() {

      print("New Egg()");

      y = new Yolk();

    }

  }

  public class BigEgg extends Egg {

    public class Yolk {

      public Yolk { print("BigEgg.Yolk()"); }

    }

    public static void main(String[] args) {

      new BigEgg();

    }

  } /* Output:

  New Egg()

  Egg.Yolk()

  */

  The two inner classes are completely separate entities, each in its own namespace. However, it’s still possible to explicitly inherit from the inner class  

  class Egg2 {
    protected class Yolk {
      public Yolk() { print("Egg2.Yolk()"); }
      public void f() { print("Egg2.Yolk.f()");}
    }
    private Yolk y = new Yolk();
    public Egg2() { print("New Egg2()"); }
    public void insertYolk(Yolk yy) { y = yy; }
    public void g() { y.f(); }
  }
  public class BigEgg2 extends Egg2 {
    public class Yolk extends Egg2.Yolk {
      public Yolk() { print("BigEgg2.Yolk()"); }
      public void f() { print("BigEgg2.Yolk.f()"); }
    }
    public BigEgg2() { insertYolk(new Yolk()); }
    public static void main(String[] args) {
      Egg2 e2 = new BigEgg2();
      e2.g();
    }
  } /* Output:
  Egg2.Yolk()
  New Egg2()
  Egg2.Yolk()
  BigEgg2.Yolk()
  BigEgg2.Yolk.f()

  */

Local inner classes

  A local inner class canot have an acces specifier because it isn't part of the outer class, but it does have access to the final variables in the current code block and all the members of the enclosing class.

  Since the name of the local inner class is not accessible outside the method, the only justification for using a local inner class instead of an anonymous inner class is if you need a named constructor and/ or an overloaded constructor, since an anonymous inner class can only use instance initialization.

  Another reason to make a local inner class rather than an anonymous inner class is if you need to make more than one object of that class.

Inner-class identifiers

  If inner classes are anonymous, the compiler simply starts generating numbers as inner-class identifiers. If inner classes are nested within inner classes, their names are simply appended after a ‘$’ and the outer-class identifier (s).

Summary

  Interfaces and inner classes solve the same problem that C++ attempts to solve with its multiple inheritance (MI) feature.

Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十)之Inner Classes的更多相关文章

  1. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十四)之Type Information

    Runtime type information (RTTI) allow you to discover and use type information while a program is ru ...

  2. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十二)之Error Handling with Exceptions

    The ideal time to catch an error is at compile time, before you even try to run the program. However ...

  3. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(八)之Reusing Classes

    The trick is to use the classes without soiling the existing code. 1. composition--simply create obj ...

  4. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(七)之Access Control

    Access control ( or implementation hiding) is about "not getting it right the first time." ...

  5. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(六)之Initialization & Cleanup

    Two of these safety issues are initialization and cleanup. initialization -> bug cleanup -> ru ...

  6. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十三)之Strings

    Immutable Strings Objects of the String class are immutable. If you examine the JDK documentation fo ...

  7. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(二)之Introduction to Objects

    The genesis of the computer revolution was a machine. The genesis of out programming languages thus ...

  8. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十一)之Holding Your Objects

    To solve the general programming problem, you need to create any number of objects, anytime, anywher ...

  9. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(九)之Interfaces

    Interfaces and abstract classes provide more structured way to separate interface from implementatio ...

随机推荐

  1. Java并发编程之CAS二源码追根溯源

    Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java: ...

  2. 1.Lambda表达式

    1.Lambda表达式 语法糖 也叫作糖衣语法,增强了代码的可读性 避免了出错的机会 但是,这种语法对于语言的功能并没有增强 和Lambda一样的糖衣语法还有:(1)泛型 <>(2)自动装 ...

  3. requests模块使用二

    1.cookies和session 1.1.什么是cookie和session? cookie是网站用来辨别用户身份,进行会话跟踪,存储在本地终端上的数据. session(会话)起来本含义是指有始有 ...

  4. hdu2642二维树状数组,单点修改+区间查询

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/2642/ 代码如下: #include<bits/stdc++.h> using namespace ...

  5. tpyboard v202 测试tcp通讯,i2c的oled程序,呼吸灯源码,希望对大家有所帮助

    1.下载到板子里的main.py代码如果需要驱动oled的,可以参考我上面那篇文章import time, mathimport machineimport network# from ssd1306 ...

  6. Layui+Servlet+MyBatis+Mysql实现的大学生创新竞赛管理平台

    项目简介 项目来源于:https://gitee.com/fly-liuhao/SCMS 原仓库中未上传jar包及登录异常,现将修改过的源码上传到百度网盘上. 链接:https://pan.baidu ...

  7. 开始 Keras 序列模型(Sequential model)

    开始 Keras 序列模型(Sequential model) 序列模型是一个线性的层次堆栈. 你可以通过传递一系列 layer 实例给构造器来创建一个序列模型. The Sequential mod ...

  8. 图像的特征工程:HOG特征描述子的介绍

    介绍 在机器学习算法的世界里,特征工程是非常重要的.实际上,作为一名数据科学家,这是我最喜欢的方面之一!从现有特征中设计新特征并改进模型的性能,这就是我们进行最多实验的地方. 世界上一些顶级数据科学家 ...

  9. coding++:mybatis update foreach (SQL循环)批量更新

    今天要做批量更新的业务,采用 mybaits 的 foreach 动态语句,遇到一些问题做下记录. 参考示例(1): <update id="" parameterType= ...

  10. python实现十大经典排序算法

    Python实现十大经典排序算法 代码最后面会给出完整版,或者可以从我的Githubfork,想看动图的同学可以去这里看看: 小结: 运行方式,将最后面的代码copy出去,直接python sort. ...