为什么要使用内部类呢?
1.内部类提供了更好的封装,只有外部类能访问内部类
2.内部类可以独立继承一个接口,不受外部类是否继承接口影响
3.内部类中的属性和方法即使是外部类也不能直接访问,相反内部类可以直接访问外部类的属性和方法,即使private
4.利于回调函数的编写
在Java中内部类主要分为成员内部类、方法内部类、匿名内部类、静态内部类。今天先来了解一下静态内部类和成员内部类。
静态内部类:
关键字static可以修饰成员变量、方法、代码块,其实它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:
-
静态内部类的创建是不需要依赖于外围类,可以直接创建
-
静态内部类不可以使用任何外围类的非static成员变量和方法,而内部类则都可以
结合下面的代码来加深理解。
public class OuterClass1{ //静态变量 private static String s1="A"; //成员变量 private String s2="B"; //静态方法 private static void m1(){ System.out.println("static's method m1 is excuted!"); } //成员方法 private void m2(){ System.out.println("static's method m2 is excuted!"); } /* public static void main(String args[]){ System.out.println("sd"); } */ //静态内部类,可以用访问控制权限修饰,public,protected,private,缺省 static class InerClass{ //静态内部类中的静态方法 public static void m3(){ System.out.println(s1); //内部类方法访问外部类private静态变量 //System.out.println(s2); //内部类方法访问外部类private成员变量,出错,无法从静态上下文中引用非静态变量 s2 m1(); //内部类访问外部类的静态方法 //m2(); //出错,无法从静态上下文中引用非静态方法 m2() } //静态内部类中的成员方法 public void m4(){ } } public static void main(String args[]){ //外部类方法访问静态内部类的静态方法,静态方法的访问,直接类名.方法名访问 OuterClass1.InerClass.m3(); //外部类方法访问静态内部类的成员方法,需要创建对象 InerClass t=new OuterClass1.InerClass(); t.m4(); } } //输出:A //static's method m1 is excuted!
从上面代码可以看出:
1.静态内部类可以等同于静态变量。
2.静态内部类可以直接访问外部类的静态数据,包括静态变量和静态方法,但无法访问成员数据(成员变量和成员方法)。
成员内部类:
成员内部类也是最普通的内部类,它是外部类的一个成员,所以他是可以无限制的访问外围类的所有成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
在成员内部类中要注意两点:
-
成员内部类中不能存在任何static的变量和方法
-
成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类
public class OuterClass2{ //静态变量 private static String s1="A"; //成员变量 private String s2="B"; //静态方法 private static void m1(){ System.out.println("static's method m1 is excuted!"); } //成员方法 private void m2(){ System.out.println("static's method m2 is excuted!"); } /* public static void main(String args[]){ System.out.println("sd"); } */ //成员内部类,可以用访问控制权限修饰,public,protected,private,缺省 class InerClass{ /* public static void m3(){ //成员内部类中不允许有静态声明 System.out.println(s1); m1(); } */ //成员内部类中的成员方法 public void m4(){ System.out.println("sdfsf"); } } public static void main(String[] args){ //访问成员内部类中的成员方法,m4()方法。m4()方法为成员方法,所以InerClass先创建对象。InerClass为成员,所以先创建出来OuterClass的对象。 //先创建外部类对象 OuterClass2 t2=new OuterClass2(); InerClass inner=t2.new InerClass(); inner.m4(); } }
需要记住:
1.成员内部类可以等同看做成员变量
2.成员内部类不能有静态声明
3.成员内部类可以访问外部类的所有数据
局部内部类:
局部内部类定义在外部类的方法中,和成员内部类基本一致,只是它们的作用域不同,局部内部类只能在该方法中被使用,出了该方法就会失效。 对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。
public class OuterClass3{ //方法 public void m1(){ final int i=10; //局部内部类,局部内部类不能用访问权限修饰符修饰 class InnerClass{ //public static void m1(){} 内部类不能有静态声明 //成员方法 public void m2(){ System.out.println(i); } } InnerClass inner=new InnerClass(); inner.m2(); } //想要在外部类中访问m2()方法,m2()方法在局部内部类中,不能直接访问,作用范围不同,出了大括号就不认识了 public static void main(String[] args){ OuterClass3 t3=new OuterClass3(); t3.m1(); } }
关于局部内部类,需要记住以下几点:
1.局部内部类等同于局部变量
2.局部内部类不能用访问控制权限修饰符修饰
3.局部内部类在访问局部变量的时候,局部变量必须使用final修饰。
匿名内部类:
匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,除此之外,还有一些地方需要注意:
-
匿名内部类是没有访问修饰符的。
-
匿名内部类必须继承一个抽象类或者实现一个接口
-
匿名内部类中不能存在任何静态成员或方法
-
匿名内部类是没有构造方法的,因为它没有类名。
public class Testa{ public static void t(CustomerService cs){ //t方法调用接口 cs.logout(); } //程序入口 public static void main(String[] args){ //调用t方法 // t(new CustomerService()); 出错,接口无法创建对象 t(new CustomerService(){ //new CustomerService(){}整个就是匿名内部类 public void logout(){ System.out.println("系统已经安全退出"); } }); } }
匿名内部类有它的优点,那就是可以少定义一个类,它的缺点就是无法重复利用。
搜索微信公众号“程序员考拉”,欢迎关注!