Java内部类学习笔记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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、一个定义在方法中的类
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调试过一遍
- 内部类与控制框架
- 内部类的继承
- 内部类覆盖,无效;可以显式继承某内部类;
- 局部内部类,与匿名内部类的区别
以上是关于Java内部类学习笔记的主要内容,如果未能解决你的问题,请参考以下文章