非静态内部类作用:

  1. 最基本的作用:名字隐藏和组织代码

    • 用例:内部类不访问外部类的元素时可以直接new。(bad style!)
    • 用例:通过外部类的非静态方法返回内部类的引用,这样隐含了内部类对象和其对应的外部类对象的关系(需要先创建外部类对象,然后通过外部类对象创建内部类对象)。
    • 注意:内部类访问内部类的元素时,直接new内部类编译会报错

      No enclosing(外围的) instance of type xxx is accessible
  2. 链接到外部类:访问其外围类所有成员的访问权
    • 实现机制:普通内部类(非静态)对象和外部类对象之间存在联系。创建内部类对象时,该对象保存指向其外部类对象的引用。
    • 用例:"迭代器"设计模式

非静态内部类使用:

  1. 外部类类名 + .this

    • 用法:返回内部类对象引用的外部类对象
  2. 外部类对象 + .new

    • 用法:返回内部类的引用,告知其它对象或静态方法中使用
    // Creating an inner class directory using the .new syntax
    
    public class DotNew {
    public class Inner {}
    public static void main(String[] args) {
    DotNew dotNew = new DotNew();
    DotNew.Inner inner = dotNew.new Inner();
    }
    }
  3. 权限修饰符

    1. 私有内部类,隐藏内部类信息。接口的实现不可见也不可用,仅能得到指向基类或者接口的引用。
    2. 保护内部类,自己、子类、同一个包中的类可以访问
    // 接口所有成员自动是public的
    interface Destination {
    String readLabel();
    } interface Contents {
    int value();
    } class Parcel4 {
    // 私有内部类,隐藏内部类信息。接口的实现不可见也不可用,仅能得到指向基类或者接口的引用。
    private class PContents implements Contents {
    private int i = 11;
    public int value() { return i; }
    }
    // 保护内部类,自己、子类、同一个包中的类可以访问
    protected class PDestination implements Destination {
    private String label;
    private PDestination(String whereTo) {
    this.label = whereTo;
    }
    public String readLabel() { return this.label; }
    }
    public Destination destination(String s) {
    PDestination pDestination = new PDestination(s);
    // Exercise 8: 外部类是否可以访问内部类的private元素
    // 答:外部类访问内部类的private对象就像访问自己的private对象一样
    // 理由:编译器对内部类实现时,生成两个类,对于private变量的访问,编译器会生成一个accessor函数.
    System.out.println(pDestination.label);
    return pDestination;
    }
    public Contents contents() {
    return new PContents();
    }
    } public class TestParcel {
    public static void main(String[] args) {
    Parcel4 p = new Parcel4();
    Contents c = p.contents();
    Destination d = p.destination("Tasmania");
    // The type Parcel4.PContents is not visible
    // 不能向下转型成private内部类,因为名字不可访问
    // ! Parcel4.PContents pc = p.new PContents();
    }
    }
    • 注意:嵌套类(内部静态类)不需要对外部对象的引用
    // Exercise 8: 外部类是否可以访问内部类的private元素
    // 答:可以,外部类访问内部类的private对象就像访问自己的private对象一样
    // 实现机制:编译器对内部类实现时,生成两个类,对于private变量的访问,编译器会生成一个 accessor函数.

方法和作用域内的内部类

  1. 目的

    • 实现了某种类型的接口,可以创建并返回对其的引用
    • 创建一个类以解决问题,但不希望这个类是公共可用的
  2. 局部内部类

    • 在方法内部定义类
    • 局部内部类可以嵌入某个作用域内(如if作用域),则在作用域外不可访问
  3. 匿名内部类

    • 创建继承/实现自公共类/接口的匿名类的对象
    // Returning an instance of an anonymous inner class.
    
    // 普通类被当作“公共”接口来使用
    class Wrapping {
    private int i;
    public Wrapping(int x) { i = x; }
    public int value() { return i; }
    } public class Parcel7 {
    public Contents contents() {
    // 创建一个实现/继承自Contents的匿名类的对象,且使用默认的构造器
    return new Contents() {
    private int i = 11;
    public int value() { return i; }
    };
    } public Wrapping wrapping(int x) {
    // Base constructor call:
    return new Wrapping(x) { // Pass constructor argument
    public int value() {
    return super.value() * 47;
    }
    };
    } public static void main(String[] args) {
    Parcel7 parcel7 = new Parcel7();
    Wrapping wrapping = parcel7.wrapping(4);
    System.out.println(wrapping.value());
    }
    }
    public class Parcel9 {
    // Argument must be final to use inside
    // anonymous inner class:
    public Destination destination(final String dest) {
    return new Destination(){
    private String label = dest;
    @Override
    public String readLabel() {
    return label;
    }
    };
    }
    public static void main(String[] args) {
    Parcel9 p = new Parcel9();
    Destination d = p.destination("Tasmania");
    System.out.println(d.readLabel());
    }
    }
    • 匿名内部类、局部内部类:若要使用一个在其外部定义的对象,那么编译器会要求其参数引用是final的

    Java编译器实现的只是capture-by-value,并没有实现capture-by-reference

        interface AnnoInner(){addXYZ();}
    public class Outer {
    public AnnoInner getAnnoInner(final int x) {
    final int y = 100;
    return new AnnoInner(){
    // 编译器相当于拷贝外部自由变量的副本到匿名类
    // int copyX=x;
    // int copyY=y;
    int z = 100;
    public int addXYZ() {
    return x + y + z;
    }
    }
    }
    }
    • 利用实例初始化,以达到为匿名内部类创建一个构造器的效果
    • 注意:匿名内部类既可以扩展类,也可以实现接口,但不能同时扩展类和实现接口,且如果是实现接口,也只能实现一个接口

嵌套类

不需要内部类对象与其外部类对象之间有联系。

  1. 意义

    • 要创建嵌套类的对象,并不需要其外围类的对象
    • 不能从嵌套类的对象中访问非静态的外围类对象
    • 嵌套类可包含static数据和字段,但普通内部类不行

Java编程思想读书笔记 第十章 内部类的更多相关文章

  1. 《Java编程思想》笔记 第十章 内部类

    1.创建内部类对象 创建内部类对象(相当于new内部类对象) 外围类对象.new 内部类( ). 创建内部类对象一种方法是 外围类有一个方法返回内部类对象. 没有外围类对象就不能创建内部类对象,因为内 ...

  2. JAVA编程思想读书笔记(五)--多线程

    接上篇JAVA编程思想读书笔记(四)--对象的克隆 No1: daemon Thread(守护线程) 参考http://blog.csdn.net/pony_maggie/article/detail ...

  3. JAVA编程思想读书笔记(四)--对象的克隆

    接上篇JAVA编程思想读书笔记(三)--RTTI No1: 类的克隆 public class MyObject implements Cloneable { int i; public MyObje ...

  4. JAVA编程思想读书笔记(三)--RTTI

    接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...

  5. JAVA编程思想读书笔记(二)--容器

    接上篇JAVA编程思想读书笔记(一) 第八章.对象的容纳 No1: java提供了四种类型的集合类:Vector(矢量).BitSet(位集).Stack(堆栈).Hashtable(散列表) No2 ...

  6. Java编程思想读书笔记之内部类

    现在是够懒得了,放假的时候就想把这篇笔记写出来,一直拖到现在,最近在读<Java编程思想>,我想会做不止这一篇笔记,因为之前面试的时候总会问道一些内部类的问题,那这本书的笔记就从内部类开始 ...

  7. Java编程思想读书笔记(一)【对象导论】

    2018年1月7日15:45:58 前言 作为学习Java语言的经典之作<Java编程思想>,常常被人提起.虽然这本书出版十年有余,但是内容还是很给力的.很多人说这本书不是很适合初学者,我 ...

  8. Java编程思想读书笔记

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  9. <Java编程思想>读书笔记(1)-对象导论、一切都是对象

    1.面向对象编程:OOP (Object-oriented Programming) 2.Alan Kay 总结的面向对象语言5个基本特性: 1) 万物皆为对象 2) 程序是对象的集合,他们通过发送消 ...

随机推荐

  1. R_Studio(关联)使用apriori函数简单查看数据存在多少条关联规则,并按支持度降序排序输出

    查看数据menu_orders.txt文件存在多少条关联规则,并按支持度降序排序输出 #导入arules包 install.packages("arules") library ( ...

  2. Dynamic Web Module 2.3 change to 3.0 maven工程解决办法

    pom.xml <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <a ...

  3. Java基础教程免费分享

    这是我自己早前听课时整理的Java全套知识,适用于初学者,也可以适用于中级进阶的人,你们可以下载,我认为是比较系统全面的,可以抵得上市场上90%的学习资料.讨厌那些随便乱写的资料还有拿出来卖钱的人!在 ...

  4. Zookeeper(二)数据模型

    Zookeeper数据模型ZNode 问题 ZK的数据模型ZNodes是什么样的: 树形结构,每个叶子节点都存储着数据,且可挂载子节点: 路径作为叶子节点名称,数据作为叶子节点内的数据: Znode可 ...

  5. LeetCode 96. 不同的二叉搜索树(Unique Binary Search Trees )

    题目描述 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 输出: 解释: 给定 n = , 一共有 种不同结构的二叉搜索树: \ / / / \ \ / / ...

  6. echarts+json笔记

    echart_test.html <!DOCTYPE html> <head> <meta charset="utf-8"> <scrip ...

  7. shell初级-----结构化命令

    if-then语句 bash shell的if语句会执行if后面的那个命令,如果该命令的退出码状态为0会执行then部分的命令,如果是其他值不会执行. 格式如下: if command then co ...

  8. IDEA里面maven项目使用maven插件tomcat启动项目

    1.首先在pom.xml添加tomcat插件依赖: <?xml version="1.0" encoding="UTF-8"?> <proje ...

  9. 利用开源SlidingMenu框架实现左右侧滑菜单的功能

    package com.loaderman.slidingmenudemo; import android.os.Bundle; import android.support.v4.app.Fragm ...

  10. Jmeter(一) - 调用数据的参数化

    1. 做性能测试, 不可避免的一点一定会有使用不同的用户密码进行登陆. 如何使登陆用户参数化呢?