能够将一个类定义在另外一个类里面或者一个方法里面,这样的类称为内部类。java
普遍意义上的内部类通常来讲包括这四种:函数
成员内部类是最普通的内部类,它的定义为位于另外一个类的内部,形以下面的形式:测试
public class testDemo { public static void main(String[] args ) { Outer t = new Outer(); Outer.Inner in = t.new Inner(); // 必须先有外部类对象,才能建立内部类 t.fun(); in.print(); } } class Outer { //外部类 private String msg = "hello world"; public void fun(){ Inner in = new Inner(); System.out.println(in.info); //外部类直接访问内部类的私有属性 } class Inner{ //定义了一个成员内部类 private String info = "世界,你好!"; public void print(){ System.out.println(msg); //内部类直接访问外部类的private属性 } } }
成员内部类能够无条件访问外部类的全部属性和方法(包括private成员和静态成员)。外部类也能够直接访问内部类的全部属性和方法。this
成员内部类是依附外部类而存在的,也就是说,若是要建立成员内部类的对象,前提是必须存在一个外部类的对象设计
在外部类中若是要访问成员内部类的成员,必须先建立一个成员内部类的对象,再经过指向这个对象的引用来访问。code
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认状况下访问的是成员内部类的成员。若是要访问外部类的同名成员,须要如下面的形式进行访问:对象
外部类.this.成员变量 外部类.this.成员方法
局部内部类是定义在一个方法或者一个做用域里面的类,它和成员内部类的区别在于局部内部类的做用域仅限于方法内或者该做用域内。继承
public class testDemo { public static void main(String[] args ) { new Outer().fun(); } } class Outer { //外部类 private String msg = "hello world"; public void fun(){ class Inner{ //在方法中定义了一个局部内部类 public void print(){ System.out.println(Outer.this.msg); //直接访问外部类的private属性 } } new Inner().print(); } }
注意:局部内部类就像是方法里面的一个局部变量同样。接口
在jdk1.7或以前的版本,若是局部内部类要访问方法中定义的参数、局部变量,那么参数和变量前必定要加上"final"修饰符。jdk1.8以及更新的版本则没有这个限制。作用域
public class testDemo { public static void main(String[] args ) { new Outer().fun(100); } } class Outer { //外部类 private String msg = "hello world"; public void fun(final int num){ final double score = 99.9; class Inner{ //在方法中定义了一个局部内部类 public void print(){ System.out.println("属性:"+Outer.this.msg); //直接访问外部类的private属性 System.out.println("方法参数"+ num); System.out.println("方法局部变量"+ score); } } new Inner().print(); } }
使用static修饰的成员内部类叫静态内部类。静态内部类是不须要依赖于外部类的,这点和类的静态成员属性有点相似,而且它不能访问外部类的非static成员变量或者方法。
public class testDemo { public static void main(String[] args ) { Outer.Inner in = new Outer.Inner(); //静态内部类可使用"外部类.内部类"的方式使用 in.print(); } } class Outer { //外部类 static class Inner{ //定义了一个静态内部类 private String info = "世界,你好!"; public void print(){ System.out.println(info); } } }
当某个子类只使用惟一一次的时候,没有必要单独定义出来,可使用匿名内部类的方法简化代码。
匿名内部类就是没有名字的局部内部类。建立格式以下:
new 父类构造器(参数列表)| 要实现的接口 () { //匿名内部类的类体部分 //.... }
匿名内部类是在抽象类和接口的基础上发展而来的,其最大的好处是帮助减小了类的定义。
在使用匿名内部类的过程当中,咱们须要注意以下几点:
示例:
//接口 interface Inner { public String say(); } //抽象类 abstract class Inner1 implements Inner{ } //普通类 class Inner2 implements Inner{ public String say(){ return "this is Inner2"; } } class Outer { public void method1(Inner inner) { System.out.println(inner.say()); } } public class testDemo { public static void main(String[] args) { Outer outer = new Outer(); // 测试1,Inner为接口 outer.method1(new Inner() { String s1 = "this is s1 in Inner"; public String say() { // 外部类和匿名函数类中有同名变量s1 return s1; } }); // 测试2,Inner1为抽象类 outer.method1(new Inner1() { String s2 = "this is s2 in Inner1"; public String say() { // 外部类和匿名函数类中有同名变量s2 return s2; } }); //测试3, Inner2为普通类 outer.method1(new Inner2() { public String say() { return "this is inner2 overrite"; } }); } } 输出结果: this is s1 in Inner this is s2 in Inner1 this is inner2 overrite
为何要使用内部类?在《Think in java》中有这样一句话:使用内部类最吸引人的缘由是:每一个内部类都能独立地继承一个(接口的)实现,因此不管外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
在咱们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候咱们能够利用内部类提供的、能够继承多个具体的或者抽象的类的能力来解决这些程序设计问题。能够这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。内部类最大的优势就在于它可以很是好的解决多重继承的问题.
内部类还可以为咱们带来以下特性: