内部类总结
- 定义:指在一个外部类的内部再定义一个类。
- 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。
- 内部类可以对同一个包中的其他类隐藏起来。
- 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。
- 内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。
-
使用内部类访问对象状态
内部类可以是静态static的,也可用public,default,protected和private修饰,而常规的类只能具有包的可见性(default),或公有的可见性(public)。
内部类的对象有一个隐式引用(这个引用在内部类的定义中是不可见的),它引用了实例化该内部类对象的外围类对象。通过这个指针,可以访问外围类对象的全部状态。
所以,内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。
-
内部类的特殊语法规则
使用外围类引用的正规语法:
OuterClass.this
可以采用下列语法格式更加明确地编写内部对象的构造器:
OuterObject.new InnerClass(construction parameters)
在外围类的作用域之外,可以这样引用内部类:
OuterClass.InnerClass
- Java中内部类共分为四种:
静态/嵌套内部类 static inner class (also called nested class)
成员内部类 member inner class
局部内部类 local inner class
匿名内部类 anonymous inner class
静态/嵌套内部类 static inner class (also called nested class)
- 最简单的内部类形式。
- 类定义时加上static关键字。不需要内部类对象和外部类对象之间的联系,可直接引用outer.inner,即不需要创建外部类,也不需要创建内部类。
- 不能和外部类有相同的名字。
- 只可以访问外部类的静态成员和静态方法,包括了私有的静态成员和方法。
- 嵌套类和普通的内部类还有一个区别:普通内部类不能有static数据和static属性,也不能包含嵌套类,但嵌套类可以。而嵌套类不能声明为private,一般声明为public,方便调用。
- 注意,声明在接口中的内部类自动成为public和static。
声明静态内部类对象的方式为:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
1 public class StaticInner { 2 static int a=1; 3 int b=2; 4 /* 也可在外部类里生成内部类对象: 5 * StaticInner.Inner inner = new StaticInner.Inner(); 6 */ 7 //定义一个内部类 8 public static class Inner{ 9 int a = 3; 10 int b = 4; 11 public void display(){ 12 System.out.println(a);//此时调用Inner类中的a 13 System.out.println(StaticInner.a);//此时调用StaticInner类中的a 14 System.out.println(b);//此时调用Inner类中的b 15 } 16 } 17 18 public static void main(String[] args) { 19 /* 声明静态内部类对象的方式为 20 * OuterClass.InnerClass name = new OuterClass.InnerClass(); 21 */ 22 StaticInner.Inner inner = new StaticInner.Inner(); 23 inner.display(); 24 } 25 26 }
3 1 4
成员内部类Member Inner Class
- 定义时不用static修饰,成员内部类就像一个实例变量。
- 成员内部类不能含有static的变量和方法,因为成员内部类需要先创建了外部类,才能创建它自己的。
- 可直接使用外部类的所有变量和方法,不管是静态的还是非静态的都可以,即使是private的。
- 外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取。
在外部类里面创建成员内部类的实例:
this.new Innerclass();
在外部类之外创建内部类的实例:
(new Outerclass()).new Innerclass();
在内部类里访问外部类的成员: 访问外部类static成员:
Outerclass.this.member Outerclass.member
1 public class Outer { 2 int a=0; 3 int b=1; 4 5 Inner inner = this.new Inner();// 在外部类里面创建成员内部类的实例 6 7 //定义一个内部类 8 public class Inner{ 9 int a = 2; 10 public void display(){ 11 System.out.println(b);//直接访问外部类对象 12 System.out.println(Outer.this.a);// 访问外部类成员 13 14 System.out.println(a);// 访问内部类成员 15 System.out.println(this.a);// 访问内部类成员 16 } 17 } 18 19 public static void main(String[] args) { 20 /*在外部类之外创建内部类的实例: 21 Outer.Inner inner = new Outer().new Inner(); 22 */ 23 Outer outer = new Outer(); 24 outer.inner.display(); 25 } 26 27 }
1 0 2 2
局部内部类Local Inner Class
- 局部内部类定义在方法中,比方法的范围还小。是内部类中最少用到的一种类型。
- 像局部变量一样,不能被public, protected, private和static修饰。
- 只能访问方法中定义的final类型的局部变量,对它进行初始化后不能够再修改。
- 局部类的一个优势即对外部世界可以完全地隐藏起来。
- 局部内部类在方法中定义,所以只能在方法中使用,即只能在方法当中生成局部内部类的实例并且调用其方法。
1 class LocalInner 2 { 3 int a = 1; 4 5 public void doSomething() 6 { 7 int b = 2; 8 final int c = 3; 9 // 定义一个局部内部类 10 class Inner3 11 { 12 public void test() 13 { 14 System.out.println("Hello World"); 15 System.out.println(a); 16 17 // 不可以访问非final的局部变量 18 // error: Cannot refer to a non-final variable b inside an inner 19 // class defined in a different method 20 // System.out.println(b); 21 22 // 可以访问final变量 23 System.out.println(c); 24 } 25 } 26 27 // 创建局部内部类的实例并调用方法 28 new Inner3().test(); 29 } 30 } 31 32 public class LocalInnerClassTest 33 { 34 public static void main(String[] args) 35 { 36 // 创建外部类对象 37 LocalInner inner = new LocalInner(); 38 // 调用外部类的方法 39 inner.doSomething(); 40 } 41 42 } 43 44 点击查看代码
Hello World
1
3
匿名内部类Anonymous Inner Class
- 假如只创建这个类的一个对象,就不必为它命名了,这种没有名字的局部内部类被称为匿名内部类。
通常的语法格式为:
new SuperType(construction parameters)
{
inner class methods and data
}
SuperType可以是类也可以是接口,匿名内部类隐式地继承了一个父类或者实现了一个接口。
- 不能加访问修饰符,不使用关键字class, extends, implements。
- 由于构造器的名字必须和类名相同,而匿名类没有类名,所以匿名类不能有构造器。
- 匿名内部类中使用的外部局部变量是final变量。
- 匿名内部类使用得比较多,通常是作为一个方法参数。
1 import java.util.Date; 2 3 public class AnonymouseInnerClass 4 { 5 6 @SuppressWarnings("deprecation") 7 public String getDate(Date date) 8 { 9 return date.toLocaleString(); 10 11 } 12 13 public static void main(String[] args) 14 { 15 AnonymouseInnerClass test = new AnonymouseInnerClass(); 16 17 // 打印日期: 18 String str = test.getDate(new Date()); 19 System.out.println(str); 20 System.out.println("----------------"); 21 22 // 使用匿名内部类 23 String str2 = test.getDate(new Date() 24 { 25 });// 使用了花括号,但是不填入内容,执行结果和上面的完全一致 26 // 生成了一个继承了Date类的子类的对象 27 System.out.println(str2); 28 System.out.println("----------------"); 29 30 // 使用匿名内部类,并且重写父类中的方法 31 String str3 = test.getDate(new Date() 32 { 33 34 // 重写父类中的方法 35 @Override 36 @Deprecated 37 public String toLocaleString() 38 { 39 return "Hello: " + super.toLocaleString(); 40 } 41 42 }); 43 44 System.out.println(str3); 45 } 46 }
生成的.class文件中,匿名类会生成OuterClass$1.class文件,数字根据是第几个匿名类而类推。
参考网站:
http://android.blog.51cto.com/268543/384844/
http://www.cnblogs.com/mengdd/archive/2013/02/08/2909307.html

浙公网安备 33010602011771号