技术开发 频道

JAVA学习:成员内部类基本概念及用法

  说了一通概念,下面用例子来实现具体的细节;下面通过一个小例子说明成员内部类的基本用法

1 package unit10.innerclassers;
2  
3 /**
4  * 内部类的展示举例
5  *
@author coffee
6
*/
7 public class Example1 {
8     private int value;
9
10     public void setValue(int num){
11         value = num;
12     }
13
14     public int getValue() {
15         return value;
16     }
17
18     public class InnerclassOfExample1 {
19         private int value2;
20
21         public void setValue2(int value) {
22             this.value2 = value;
23         }
24
25         public int getValue2() {
26             return value;
27         }
28
29         public void setValue(int num) {
30             Example1.this.value = num;// 可以直接访问外围类的所有成员和方法
31         }
32
33         public int getValue() {
34              //或者用Example1.this.getValue();来直接访问外围类的所有方法
35             return Example1.this.value;
36         }
37     }
38
39     public static void main(String[] args) {
40         Example1 e = new Example1();
41         System.out.println("外围类自己设置自己的成员变量value为" + 10);
42         e.setValue(10);
43         System.out.println("设置后,外围类的成员变量value为" + e.getValue());
44         Example1.InnerclassOfExample1 i = e.new InnerclassOfExample1();// 实例化了一个内部类
45         System.out.println("内部类自己设置自己的成员变量value2为" + 20);
46         e.setValue(20);
47         System.out.println("设置后,内部类的成员变量value2为" + e.getValue());
48         i.getValue();
49        
50         //通过内部类来操作外围类
51         System.out.println("内部类设置外围类的成员变量value为" + 26);
52         i.setValue(26);
53         System.out.println("设置后,内部类设置后外围类的成员变量value为" + i.getValue());
54     }
55 }

  运行后的结果是:

  外围类自己设置自己的成员变量value为10

  设置后,外围类的成员变量value为10

  内部类自己设置自己的成员变量value2为20

  设置后,内部类的成员变量value2为20

  内部类设置外围类的成员变量value为26

  设置后,内部类设置后外围类的成员变量value为26

  而在经过javac编译后,生成了Example1.class和Example1$InnerclassOfExample1.class这样的两个字节码文件;

  通过这个例子,看出一般的内部类(即非静态的的内部类)的作用可以概括为:代码隐藏+元素访问权;内部类可以访问外围类的所有成员变量和方法,注意是所有,不管是不是private的,而这与c++嵌套类的设计不同,在c++中只是单纯的名字隐藏机制,与外围对象没有联系,也没有隐含的访问权.

  下面介绍下刚刚所提到的静态的内部类,通常java编程中,我们只能申明一个static的变量或者方法,那么静态内部类有哪些作用?我们进行下对比就清楚了.

  非静态的内部类只能声明非静态成员或方法,可以使用外围类的静态成员或变量;而静态内部类则可拥有静态的成员和方法。,但静态内部类中只能引用其外部类的静态成员或变量。

  因为静态内部类并不与外围类对象关联,其他的内部类的实例化之前都只能在与其外围类相关联的情况下才能被创建,但是有一个看起来像是特例:静态方法中的匿名内部类。

  先说下什么是匿名内部类吧,将下面这段代码加到上面的那个例子中即可

public   Example1 zm(){
        
return new Example1(){//这就是匿名内部类,继承自Example1,也可以继承接口,使用方法相同
            public int value;
            
//!public static int zm;//匿名内部类不能申明static成员和方法
            public void setValue(int num){
                value
= Example1.a;//可以访问外围类的静态变量
                value = Example1.this.value;//可以访问外围类的非静态变量
            }
            
public int getValue(){
                
return value;
            }
        };
//在匿名内部类末尾的分号,并不是用来标记此内部类结束(C++中是那样)。实际上,它是表达式的结束,只不过这个表达式正巧包含了内部类罢了。因此,这与别的地方使用的分号是一致的
    }

  看起来是一种很奇怪的方法,zm()方法返回一个对象,这个对象是Example1的子类的实例,如果把zm()改为static的方法后,就可以直接调用Example1.zm()然后返回一个Example1的子类的实例了,下面我比较下static zm()和zm()的区别:

  不加static的方法中的匿名内部类:可以使用外围类的所有的成员变量及方法;

  加static的方法中的匿名内部类:只可以使用外围类的静态成员和方法了;

  注意:这里的外围类不是说所继承的类,例子中的代码只是碰巧继承了外围类而已。

  写到这儿,想想内部类的基础知识也回忆的差不多了,至于应用的话,原文所说的在应用程序框架里面会经常使用,还可以利用内部类实现回调,其中比较重要的有:内部类可以实现多重继承,因为内部类可以继承多个非接口类型,即类和抽象类;正常的情况下,接口中是不可以写任何代码的,但是可以再接口中实现静态内部类,然后写上公共的代码。

  总结: 比起面向对象编程中的其他的概念来,接口和内部类算的上很复杂的了;像c++就没有这些,讲两者结合起来,可以解决c++中的用多重继承所能解决的问题,然而c++的多重继承却是很难使用的,相对而言java中的接口和内部类就容易理解多了,内部类的这些特性说出来是很直观的,但是就像多态机制一样,这些特性的使用应该是设计阶段应该考虑的问题,随着经验的累积,见多识广后,自己心中就会有杆称,权衡什么时候用接口,什么时候用内部类,或者两者都用。

0
相关文章