查看: 52|回复: 0

Java静态内部类、匿名内部类、成员式内部类和局部内部类

发表于 2018-6-12 13:48:38

内部类可以是静态(static)的,可以使用 public、protected 和 private 访问控制符,而外部类只能使用 public,或者默认。

成员式内部类

在外部类内部直接定义(不在方法内部或代码块内部)的类就是成员式内部类,它可以直接使用外部类的所有变量和方法,即使是 private 的。外部类要想访问内部类的成员变量和方法,则需要通过内部类的对象来获取。

请看下面的代码:

1. public class Outer{

2.     private int size;

3.     public class Inner {

4.         public void dostuff() {

5.             size++;

6.         }

7.     }

8.     public void testTheInner() {

9.         Inner in = new Inner();

10.         in.dostuff();

11.     }

12. }

成员式内部类如同外部类的一个普通成员。

成员式内部类可以使用各种修饰符,包括 public、protected、private、static、final 和 abstract,也可以不写。

若有 static 修饰符,就为类级,否则为对象级。类级可以通过外部类直接访问,对象级需要先生成外部的对象后才能访问。

非静态内部类中不能声明任何 static 成员。

内部类可以相互调用,例如:

1. class A {

2.     // B、C 间可以互相调用

3.     class B {}

4.     class C {}

5. }

成员式内部类的访问

内部类的对象以成员变量的方式记录其所依赖的外层类对象的引用,因而可以找到该外层类对象并访问其成员。该成员变量是系统自动为非 static 的内部类添加的,名称约定为“outClassName.this”。

1) 使用内部类中定义的非静态变量和方法时,要先创建外部类的对象,再由“outObjectName.new”操作符创建内部类的对象,再调用内部类的方法,如下所示:

1. public class Demo{

2.     public static void main(String[] args) {

3.         Outer outer = new Outer();

4.         Outer.Inner inner = outer.new Inner();

5.         inner.dostuff();

6.     }

7. }

8. class Outer{

9.     private int size;

10.     class Inner{

11.         public void dostuff() {

12.             size++;

13.         }

14.     }

15. }


2) static 内部类相当于其外部类的 static 成员,它的对象与外部类对象间不存在依赖关系,因此可直接创建。示例如下:

1. public class Demo{

2.     public static void main(String[] args) {

3.         Outer.Inner inner = new Outer.Inner();

4.         inner.dostuff();

5.     }

6. }

7.

8. class Outer{

9.     private static int size;

10.     static class Inner {

11.         public void dostuff() {

12.             size++;

13.             System.out.println("size=" + size);

14.         }

15.     }

16. }

运行结果:
size=1

3) 由于内部类可以直接访问其外部类的成分,因此当内部类与其外部类中存在同名属性或方法时,也将导致命名冲突。所以在多层调用时要指明,如下所示:

1. public class Outer{

2.     private int size;

3.     public class Inner{

4.         private int size;

5.         public void dostuff(int size){

6.             size++;  // 局部变量 size;

7.             this.size;  // 内部类的 size

8.             Outer.this.size++;  // 外部类的 size

9.         }

10.     }

11. }

局部内部类

局部内部类(Local class)是定义在代码块中的类。它们只在定义它们的代码块中是可见的。

局部类有几个重要特性:

1. 仅在定义了它们的代码块中是可见的;

2. 可以使用定义它们的代码块中的任何局部 final 变量;

3. 局部类不可以是 static 的,里边也不能定义 static 成员;

4. 局部类不可以用 public、private、protected 修饰,只能使用缺省的;

5. 局部类可以是 abstract 的。


请看下面的代码:

1. public class Outer {

2.     public static final int TOTAL_NUMBER = 5;

3.     public int id = 123;

4.     public void func() {

5.         final int age = 15;

6.         String str = "http://www.weixueyuan.net";

7.         class Inner {

8.             public void innerTest() {

9.                 System.out.println(TOTAL_NUMBER);

10.                 System.out.println(id);

11.                 // System.out.println(str);不合法,只能访问本地方法的final变量

12.                 System.out.println(age);

13.             }

14.         }

15.         new Inner().innerTest();

16.     }

17.     public static void main(String[] args) {

18.         Outer outer = new Outer();

19.         outer.func();

20.     }

21. }

运行结果:
5
123
15

匿名内部类

匿名内部类是局部内部类的一种特殊形式,也就是没有变量名指向这个类的实例,而且具体的类实现会写在这个内部类里面。

注意:匿名类必须继承一个父类或实现一个接口。

不使用匿名内部类来实现抽象方法:

1. abstract class Person {

2.     public abstract void eat();

3. }

4.

5. class Child extends Person {

6.     public void eat() {

7.         System.out.println("eat something");

8.     }

9. }

10.

11. public class Demo {

12.     public static void main(String[] args) {

13.         Person p = new Child();

14.         p.eat();

15.     }

16. }

运行结果:
eat something

可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用。但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

这个时候就引入了匿名内部类。使用匿名内部类实现:

1. abstract class Person {

2.     public abstract void eat();

3. }

4.

5. public class Demo {

6.     public static void main(String[] args){

7.        

8.         // 继承 Person 类

9.         new Person() {

10.             public void eat() {

11.                 System.out.println("eat something");

12.             }

13.         }.eat();

14.     }

15. }

可以看到,匿名类继承了 Person 类并在大括号中实现了抽象类的方法。

内部类的语法比较复杂,实际开发中也较少用到,本教程不打算进行深入讲解,各位读者也不应该将内部类作为学习Java的重点。

java学习交流群:587131012

参考资料:http://www.makeru.com.cn/


回复

使用道具 举报