come from:
内部类分类
内部类:将一个类定义在另一个类里面或者一个方法里面
类别:成员内部类、局部内部类、匿名内部类和静态内部类
成员内部类:
定义位于另一个类(外部类)的内部,可以访问外部类的所有属性与方法(包括private与static)
编译器在进行编译的时候,会将成员内部类单独编译成一个字节码文件。内部类的构造函数中会默认添加一个参数,此参数为外部类对象的一个引用,内部类以来外部类。
class Circle { private double radius = 0; public static int count =1; public Circle(double radius) { this.radius = radius; } class Draw { //内部类 public void drawSahpe() { System.out.println(radius); //外部类的private成员 System.out.println(count); //外部类的静态成员 } }}
覆盖:
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
外部类访问内部类:
在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问
依赖关系:
成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
访问权限:
内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。
局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
只能访问局部final对象
class People{ public People() { }} class Man{ public Man(){ } public People getWoman(){ class Woman extends People{ //局部内部类 int age =0; } return new Woman(); }}
匿名内部类
主要用于事件监听
只能访问局部final对象
scan_bt.setOnClickListener( new OnClickListener() { //此处new了一个匿名内部类 @Override public void onClick(View v) { // TODO Auto-generated method stub } }); history_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } });
权限
匿名内部类也是不能有访问修饰符和static修饰符
范围与用法
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写
静态内部类
static+成员内部类
静态内部类是不需要依赖于外部类的,不能使用外部类的非static成员变量或者方法
可以在不创建外部类对象的情况下创建内部类的对象
public class Test { public static void main(String[] args) { Outter.Inner inner = new Outter.Inner(); }} class Outter { public Outter() { } static class Inner { public Inner() { } }}
内部类使用场景
使用内部类的意义
1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整,
2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
3.方便编写事件驱动程序
4.方便编写线程代码
成员内部类与静态内部类的初始化形式
public class innerclass { public static void main(String[] args) { // 初始化Bean1 innerclass i1 = new innerclass(); innerclass.Bean1 bean1 = i1.new Bean1(); bean1.I++; // 初始化Bean2 innerclass.Bean2 bean2 = new innerclass.Bean2(); bean2.J++; } class Bean1 { public int I = 0; } static class Bean2 { public int J = 0; }}
内部类(闭包与回调)
首先回顾一下javascript闭包
闭包就是能够读取其他函数内部变量的函数,定义在一个函数内部的函数,闭包就是将函数内部和函数外部连接起来的一座桥梁。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
function f1(){ var n=999; function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000
函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
java的回调
回调实质上是指一个类尽管实际上实现了某种功能,但是没有直接提供相应的接口,客户类可以通过这个类的内部类的接口来获得这种功能。而这个内部类本身并没有提供真正的实现,仅仅调用外部类的实现。可见,回调充分发挥了内部类所具有的访问外部类的实现细节的优势。
package basic.Test;class innerclassCallback2 extends Base { private int temperature; // 调节温度的真真实现在外部内中,但不提供给外部,只能通过内部类回调 private void adjustTemperature(int temperature) { System.out.println("adjust temperature!"); this.temperature = temperature; } // 实现回调接口 //如果实现了Adjustable接口中的adjust()方法,并且把Base类中的adjust()方法覆盖了, //这意味着本类仅仅有调节温度的功能,但失去了调节速度的功能。或以使用内部类来解决这一问题 private class Closure implements Adjustable { public void adjust(int temperature) { // 通过回调外部类中的实现来完成温度调节功能 adjustTemperature(temperature); } } // 获取回调节引用 public Adjustable getCallBackReference() { return new Closure(); } public static void main(String[] args) { innerclassCallback2 sub = new innerclassCallback2(); // 具有调节速度的功能 sub.adjst(1); /* * 回调: 又具有调节温度的功能 * 客户类先调用sub实例的getCallBackReference()方法,获得 * 内部类的Closure实例,然后再调用Closure实例的adjust()方 * 法,该方法又调用Sub实例的adjustTemperature()方法。这种 * 调用过程称为回调。 */ sub.getCallBackReference().adjust(2); }}interface Adjustable { //功能:调节温度 public void adjust(int temperature);}class Base { private int speed; //功能:调节速度 public void adjst(int spped) { System.out.println("adjust speed!"); this.speed = speed; }}