zoukankan      html  css  js  c++  java
  • Java内部类学习笔记

    20160923

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

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

     1 public class Parcel5 {
     2     public Destination destination(String s){
     3         class PDestination implements Destination{
     4             private String label;
     5             private PDestination(String whereTo){
     6                 label = whereTo;
     7             }
     8             @Override
     9             public String readLabel() { return label; }
    10         }
    11         return new PDestination(s);
    12     }
    13     public static void main(String[] args) {
    14         Parcel5 p = new Parcel5();
    15         Destination destination = p.destination("Tasmania");
    16     }
    17 }

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

     1 public class Parcel6 {
     2     private void internalTracking(boolean b) {
     3         if (b){
     4             class TrackingSlip {
     5                 private String id;
     6                 public TrackingSlip(String s) {
     7                     id = s;
     8                 }
     9                 String getSlip(){ return id;}
    10             }
    11             TrackingSlip ts = new TrackingSlip("slip");
    12             String s = ts.getSlip();
    13         }
    14         //Can't use it here!Out of scope:
    15         //TrackingSlip ts = new TrackingSlip("x");
    16     }
    17     public void track(){internalTracking(true);}
    18     public static void main(String[] args) {
    19         Parcel6 p = new Parcel6();
    20         p.track();
    21     }
    22 }

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

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

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

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

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

      

  • 相关阅读:
    MAC使用小技巧(一)
    开发者:网站 & SDK
    编译 & 预处理
    归并排序 & 快速排序
    算法 & 分析 (收集)
    栈 & 堆 |--> 内存管理
    [ 单例、代理 & 通知 ]
    博客园:CSS & HTML
    比较、字符串
    Swift # 异常处理
  • 原文地址:https://www.cnblogs.com/heleiz/p/5901487.html
Copyright © 2011-2022 走看看