成员内部类
- 内部类可以访问外部类的所有成员。
- 通过
外部类.this.*
访问外部类同名成员。 - 通过
外部类.内部类 name=new 外部类().内部类()
实例化对象。 - 内部类中不能有任何static成员。
public class InnerClass1 { public int a; protected double b; char c; private String d; InnerClass1(int a){ this.a=a; } class inner{ int a; inner(int a){ this.a=a; } private void A(){ System.out.println(a); System.out.println(this.a); System.out.println(InnerClass1.this.a); } public void B(){ System.out.println(b); } } public static void main(String[] args) { InnerClass1.inner inner=new InnerClass1(10).new inner(5); inner.A(); inner.B(); } }
局部内部类
- 定义在方法里,不能有修饰符,只能在方法里使用。
- 只能使用外部类的final成员。
- 除了装逼暂时想不出这东西有什么用了...
/** * 局部内部类 */ public class InnerClass2 { final static int a=5; public static void main(String[] args) { class inner{ int sum(int n){ int ans=0; for(int i=1;i<=n;i++){ ans+=i; } return ans+a; } } System.out.println(new inner().sum(5)); System.out.println(new inner().sum(15)); } }
静态内部类
- 静态内部类较为独立,不依赖于外部类,通过
外部类.内部类 name=new 外部类.内部类()
实例化对象,不需要创建外部类实例。 - 只能访问外部类的static成员。
/** * 静态内部类 */ public class InnerClass3 { int a=5; static int b=10; static class inner3{ int a=15; static int b=20; void A(){ System.out.println(a); // System.out.println(InnerClass3.a); } static void B(){ System.out.println(b); System.out.println(InnerClass3.b); } } public static void main(String[] args) { InnerClass3.inner3 inner3=new InnerClass3.inner3(); inner3.A(); InnerClass3.inner3.B(); } }
匿名内部类
- 匿名内部类比较常见,比如回调函数,将匿名内部类作为方法参数传递。
- 直接使用方法就是
接口 name=new 接口(){[重写接口所有函数]}
。 - 匿名内部类没有构造器。
- 匿名内部类可以访问外部方法的局部变量,但必须是final声明的或者实际不变的。
- 原因是当外部方法结束返回时,内部类对象,方法有可能还在,如果引用的外部的局部变量已经没了,就会发生错误,所以通过final修饰,将局部变量复制一份到内部类中,保证数据的一致性。
public class CallBackUser{ public static void main(String[] args) { int b=5; // b=5; CallBackSystem callBackServer=new CallBackSystem(); callBackServer.onBtnClick("CallBack", new CallBack() { @Override public void fun(String name) { System.out.println("Hello "+name+" "+b); } }); } }
回调函数
考虑一个问题,如何让系统调用你写的一个方法? 比如点击某个按钮就执行你写的方法。
- 我们可以把自己写的函数传给[点击按钮]这个函数,在这个函数里面系统就能调用这个参数(是一个函数),比如Arrays.sort就是一个中间函数,而传进去的匿名内部类(别的语言可以是传递函数指针)就是一个回调函数,sort函数内部就会调用这个compare函数去进行比较,排序。
- 其他语言比如C++/Python可以直接把函数作为另一个函数的参数传入,从而进行回调操作。
在Java中实现一个简单的回调功能需要以下几步:
- 规定一个统一的接口
相当于把要回调的函数封装在这个接口里面,把实现这个接口的匿名内部类传递给调用者(系统)。
public interface CallBack { void fun(String name); }
- 系统端写好的API函数
系统写API函数的时候不知道用户具体会传递什么回调函数,只能是根据统一的接口来写代码,所以就调用CallBack类型的参数的对应函数。
public class CallBackSystem { public void onBtnClick(String name,CallBack callBack){ System.out.println("点击按钮后系统调用你写的方法"); callBack.fun(name); } }
- 用户调用系统函数,传入回调函数等待系统回调
这里就用到了匿名内部类,因为系统函数的参数是一个接口类型,所以用户需要一个实现该接口的具体实现类,因为在这里经常需要不同的实现类,所以用匿名内部类是最好的,不需要这个具体的类名。
public class CallBackUser{ public static void main(String[] args) { CallBackSystem callBackServer=new CallBackSystem(); callBackServer.onBtnClick("CallBack", new CallBack() { @Override public void fun(String name) { System.out.println("Hello "+name); } }); } }
来源:https://www.cnblogs.com/zxcoder/p/12241784.html