Java内部类学习笔记
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、一个定义在方法中的类
 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内部类学习笔记的更多相关文章
- 【09-04】java内部类学习笔记
		
java中的内部类 静态内部类 成员内部类 方法内部类 匿名内部类 1.静态内部类 class Outer { private static String outer = "outer&qu ...
 - Java内部类——学习笔记
		
参考:http://blog.csdn.net/aaronsi/article/details/187322 和 http://openhome.cc/Gossip/JavaGossip-V1/Inn ...
 - Android(java)学习笔记267:Android线程池形态
		
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
 - Java基础学习笔记总结
		
Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...
 - Android(java)学习笔记211:Android线程池形态
		
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
 - 尚学堂JAVA基础学习笔记
		
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
 - Kotlin for Java Developers 学习笔记
		
Kotlin for Java Developers 学习笔记 ★ Coursera 课程 Kotlin for Java Developers(由 JetBrains 提供)的学习笔记 " ...
 - 20145213《Java程序设计学习笔记》第六周学习总结
		
20145213<Java程序设计学习笔记>第六周学习总结 说在前面的话 上篇博客中娄老师指出我因为数据结构基础薄弱,才导致对第九章内容浅尝遏止地认知.在这里我还要自我批评一下,其实我事后 ...
 - [原创]java WEB学习笔记95:Hibernate 目录
		
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
 
随机推荐
- iOS之UILabel的自动换行
			
思路: 获取UILabel的frame大小 获取UILabel的字体大小 获取UILabel的文本内容 根据上面的3部分数据,计算文本显示区域大小 根据4计算的大小,实时改变UILabel的frame ...
 - 信息安全-2:python之hill密码算法[原创]
			
转发注明出处:http://www.cnblogs.com/0zcl/p/6106513.html 前言: hill密码算法我打算简要介绍就好,加密矩阵我用教材上的3*3矩阵,只做了加密,解密没有做, ...
 - Autofac 的点滴
			
泛型类型的注册和使用 public interface IRepository<T> where T:class { } public interface ISchoolDetailRep ...
 - VS2013中的MVC5模板部署到mono上的艰辛历程
			
部署环境:CentOS7 + Mono 3.10 + Jexus 5.6 在Xamarin.Studio创建的asp.net项目,部署过程非常顺利,没有遇到什么问题:但在VS2013中创建的asp.n ...
 - WPF - 属性系统 (3 of 4)
			
依赖项属性元数据 在前面的章节中,我们已经介绍了WPF依赖项属性元数据中的两个组成:CoerceValueCallback回调以及PropertyChangedCallback.而在本节中,我们将对其 ...
 - Restful WebApi项目开发实践
			
前言 踩过了一段时间的坑,现总结一下,与大家分享,愿与大家一起讨论. Restful WebApi特点 WebApi相较于Asp.Net MVC/WebForm开发的特点就是前后端完全分离,后端使用W ...
 - Module Zero学习目录
			
Module-Zero是实现了ASP.NET Boilerplate框架抽象概念的模块,对于企业web应用也添加了一些有用的东西: 实现了ASP.NET Identity框架的用户和角色管理. 提供了 ...
 - 编程之美—烙饼排序问题(JAVA)
			
一.问题描述 星期五的晚上,一帮同事在希格玛大厦附近的"硬盘酒吧"多喝了几杯.程序员多喝了几杯之后谈什么呢?自然是算法问题.有个同事说:"我以前在餐 馆打工,顾 ...
 - LLBL Gen Pro 5.0 企业应用开发入门
			
Solutions Design 公司于2016年5月发布了LLBL Gen Pro 5.0,这个新版本的发布出乎于我的意料.我的猜想是从4.2升级到4.5,再升级5.x版本,主版本号的变更会给原有客 ...
 - SQL Server 批量主分区备份(Multiple Jobs)
			
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 方案一(Solution One) 方案二(Solution Two) ...