现在的位置: 首页 > 综合 > 正文

深入理解java嵌套类和内部类、匿名类 深入理解java嵌套类和内部类

2013年03月13日 ⁄ 综合 ⁄ 共 7135字 ⁄ 字号 评论关闭
 

深入理解java嵌套类和内部类、匿名类


一、什么是嵌套类及内部类

  可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类。静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner)。嵌套类从JDK1.1开始引入。其中inner类又可分为三种:
  其一、在一个类(外部类)中直接定义的内部类;
  其二、在一个方法(外部类的方法)中定义的内部类;
  其三、匿名内部类。

  下面,我将说明这几种嵌套类的使用及注意事项。


二、静态嵌套类

  如下所示代码为定义一个静态嵌套类,

  1. public class StaticTest {   
  2.         private static String name = "javaJohn";           
  3.   private String id = "X001";  
  4.   static class Person{  
  5.     private String address = "swjtu,chenDu,China";  
  6.     public String mail = "josserchai@yahoo.com";//内部类公有成员  
  7.     public void display(){  
  8.       //System.out.println(id);//不能直接访问外部类的非静态成员  
  9.       System.out.println(name);//只能直接访问外部类的静态成员  
  10.       System.out.println("Inner "+address);//访问本内部类成员。  
  11.     }  
  12.   }  
  13.   
  14.   public void printInfo(){  
  15.     Person person = new Person();  
  16.     person.display();  
  17.     //System.out.println(mail);//不可访问  
  18.     //System.out.println(address);//不可访问  
  19.     System.out.println(person.address);//可以访问内部类的私有成员  
  20.     System.out.println(person.mail);//可以访问内部类的公有成员  
  21.   
  22.   }  
  23.   public static void main(String[] args) {  
  24.   StaticTest staticTest = new StaticTest();  
  25.   staticTest.printInfo();  
  26. }  
  27. }  

  在静态嵌套类内部,不能访问外部类的非静态成员,这是由Java语法中"静态方法不能直接访问非静态成员"所限定。若想访问外部类的变量,必须通过其它方法解决,由于这个原因,静态嵌套类使用很少。注意,外部类访问内部类的的成员有些特别,不能直接访问,但可以通过内部类来访问,这是因为静态嵌套内的所有成员和方法默认为静态的了。同时注意,内部静态类Person只在类StaticTest 范围内可见,若在其它类中引用或初始化,均是错误的。


三、在外部类中定义内部类

  如下所示代码为在外部类中定义两个内部类及它们的调用关系:
  

  1. public class Outer {   
  2.            int outer_x = 100;  
  3.     class Inner{  
  4.       public int y = 10;  
  5.       private int z = 9;  
  6.       int m = 5;  
  7.       public void display(){  
  8.         System.out.println("display outer_x:"+ outer_x);  
  9.       }  
  10.       private void display2(){  
  11.         System.out.println("display outer_x:"+ outer_x);  
  12.       }  
  13.     }  
  14.     void test(){  
  15.       Inner inner = new Inner();  
  16.       inner.display();  
  17.       inner.display2();  
  18.       //System.out.println("Inner y:" + y);//不能访问内部内变量  
  19.       System.out.println("Inner y:" + inner.y);//可以访问  
  20.       System.out.println("Inner z:" + inner.z);//可以访问  
  21.       System.out.println("Inner m:" + inner.m);//可以访问  
  22.       InnerTwo innerTwo = new InnerTwo();  
  23.       innerTwo.show();  
  24.     }  
  25.     class InnerTwo{  
  26.       Inner innerx = new Inner();  
  27.       public void show(){  
  28.         //System.out.println(y);//不可访问Innter的y成员  
  29.         //System.out.println(Inner.y);//不可直接访问Inner的任何成员和方法  
  30.         innerx.display();//可以访问  
  31.         innerx.display2();//可以访问  
  32.         System.out.println(innerx.y);//可以访问  
  33.         System.out.println(innerx.z);//可以访问  
  34.         System.out.println(innerx.m);//可以访问  
  35.       }  
  36.     }  
  37.     public static void main(String args[]){  
  38.       Outer outer = new Outer();  
  39.       outer.test();  
  40.     }  
  41.   }  

  以上代码需要说明有,对于内部类,通常在定义类的class关键字前不加public 或 private等限制符,若加了没有任何影响,同时好像这些限定符对内部类的变量和方法也没有影响(?)。另外,就是要注意,内部类Inner及InnterTwo只在类Outer的作用域内是可知的,如果类Outer外的任何代码尝试初始化类Inner或使用它,编译就不会通过。同时,内部类的变量成员只在内部内内部可见,若外部类或同层次的内部类需要访问,需采用示例程序中的方法,不可直接访问内部类的变量。

四、在外部类中定义内部类

  匿名类就是没有名字的内部类,是内部类的一种特殊情况。?????????  这句话对吗???

前端时间在写.net项目中,一直错将.cs里的两个class当作内部类,原来是一个文件里的两个类而已,这让我想起了Java中的内部类,比较内部类,那么还有两个类,那就是匿名类和匿名内部类。今天我想就Java中的这三种类进行个比较。

我们知道在Java语言规范中可以做很多事,例如一个类或一个接口中可以声明一个类或接口,在一个方法中可以声明一个类,类与接口声明可以嵌套任意深度等。

 

匿名类:

      1、new <类或接口><类的主体>,匿名类的声明是在编译时进行的,实例化是在运行时进行的,所以在for循环中一个new语句会创建相同匿名类的几个实例,而不是创建几个不同匿名类的一个实例。

      2、如果要执行的对象需要一个对象,但却不值得创建全新的对象(可能是因为该对象只在一个方法内部使用),在这个时候使用匿名类就会非常合适,所以说,匿名类一般会在swing程序中快速创建事件处理程序。

Java代码  收藏代码
  1. firstButton.addActionListener(new ActionListener() {  
  2.         @Override  
  3.         public void actionPerformed(ActionEvent e) {  
  4.             getTxtValue().setText("第一个按钮触发的事件!");  
  5.         }  
  6.     });   

       3、从技术上说,匿名类可以被看作非静态的内部类,所以他们具有方法内部声明的非静态内部类相同的权限和限制。

 

 

内部类:

内部类顾名思义就是在一个类的内部还有一个类

Java代码  收藏代码
  1. package com.iflytek.innerclass;  
  2.   
  3. /** 
  4.  * @author xudongwang 2012-1-11 
  5.  *  
  6.  *         Email:xdwangiflytek@gmail.com 
  7.  */  
  8. public class InnerClassDemo {  
  9.     public static void main(String[] args) {  
  10.         new Outer().fun();  
  11.     }  
  12. }  
  13.   
  14. class Outer {  
  15.   
  16.     private String name = "Hello 内部类";  
  17.   
  18.     class Inner {  
  19.         public void print() {  
  20.             System.out.println("name = " + name);  
  21.   
  22.         }  
  23.     };  
  24.   
  25.     public void fun() {  
  26.         new Inner().print();  
  27.     }  
  28. }  

 

 内部类生成的.class文件名为:Outer$Inner.class,从上面的结构发现内部类的的缺点是“结构非常的混乱”。

Java代码  收藏代码
  1. package com.iflytek.innerclass;  
  2.   
  3. /** 
  4.  * @author xudongwang 2012-1-11 
  5.  *  
  6.  *         Email:xdwangiflytek@gmail.com 
  7.  */  
  8. public class InnerClassDemo02 {  
  9.     public static void main(String[] args) {  
  10.         new Outer02().fun();  
  11.     }  
  12. }  
  13.   
  14. class Outer02 {  
  15.   
  16.     private String name = "Hello 内部类";  
  17.   
  18.     public void fun() {  
  19.         new Inner02(this).print();  
  20.     }  
  21.   
  22.     public String getName() {  
  23.   
  24.         return this.name;  
  25.     }  
  26. };  
  27.   
  28. class Inner02 {  
  29.     private Outer02 out;  
  30.   
  31.     public Inner02(Outer02 out) {  
  32.         this.out = out;  
  33.     }  
  34.   
  35.     public void print() {  
  36.         System.out.println("name = " + this.out.getName());  
  37.   
  38.     }  
  39. };  

 从上可以看出内部类的优点是“可以方便的访问外部类中的私有成员”;

如果要在外部直接使用内部类的实例化对象:

      外部类.内部类 内部类对象 = 外部类实例.new 内部类实例();

Java代码  收藏代码
  1. package com.iflytek.innerclass;  
  2.   
  3. /** 
  4.  * @author xudongwang  2012-1-11 
  5.  * 
  6.  *  Email:xdwangiflytek@gmail.com 
  7.  */  
  8. public class InnerClassDemo03 {  
  9.     public static void main(String[] args) {  
  10.         Outer03 out = new Outer03();//外部类实例  
  11.         Outer03.Inner inner = out.new Inner();//实例化内部类对象  
  12.         inner.print();  
  13.     }  
  14. }  
  15. class Outer03{  
  16.     private String name = "Hello 内部类";  
  17.     class Inner {  
  18.         public void print() {  
  19.             System.out.println("name = " + name);  
  20.         }  
  21.     }  
  22. }  

 

 一个内部类如果使用static关键字声明的话,则此内部类就将成为外部类,可以直接通过外部类.内部类的形式访问

Java代码  收藏代码
  1. package com.iflytek.innerclass;  
  2.   
  3. /** 
  4.  * @author xudongwang 2012-1-11 
  5.  *  
  6.  *         Email:xdwangiflytek@gmail.com 
  7.  */  
  8. public class InnerClassDemo04 {  
  9.     public static void main(String[] args) {  
  10.         Outer04.Inner inner = new Outer04.Inner();// 实例化内部类对象  
  11.         inner.print();  
  12.     }  
  13. }  
  14.   
  15. class Outer04 {  
  16.     private static String name = "Hello 内部类";  
  17.   
  18.     static class Inner {  
  19.         public void print() {  
  20.             System.out.println("name = " + name);  
  21.         }  
  22.     }  
  23. }  

 

 内部类可以在任意的地方使用,例如方法中声明

Java代码  收藏代码
  1. package com.iflytek.innerclass;  
  2.   
  3. /** 
  4.  * @author xudongwang 2012-1-11 
  5.  *  
  6.  *         Email:xdwangiflytek@gmail.com 
  7.  */  
  8. public class InnerClassDemo05 {  
  9.     public static void main(String[] args) {  
  10.         new Outer05().fun();  
  11.     }  
  12. }  
  13.   
  14. class Outer05 {  
  15.     private static String name = "Hello 内部类";  
  16.   
  17.     public void fun() {  
  18.         class Inner {  
  19.             public void print() {  
  20.                 System.out.println("name = " + name);  
  21.             }  
  22.         }  
  23.         new Inner().print();  
  24.     }  
  25. }  

 

 在方法中定义的内部类,可以直接访问外部类中的各个成员,但是如果要访问方法中的参数,则需要在参数上加上final关键字声明;

Java代码  收藏代码
  1. package com.iflytek.innerclass;  
  2.   
  3. /** 
  4.  * @author xudongwang 2012-1-11 
  5.  *  
  6.  *         Email:xdwangiflytek@gmail.com 
  7.  */  
  8. public class InnerClassDemo06 {  
  9.     public static void main(String[] args) {  
  10.         new Outer06().fun(20);  
  11.     }  
  12. }  
  13.   
  14. class Outer06 {  
  15.     private static String name = "Hello 内部类";  
  16.   
  17.     public void fun(final int temp) {  
  18.         class Inner {  
  19.             public void print() {  
  20.                 System.out.println("temp = " + temp);  
  21.                 System.out.println(

抱歉!评论已关闭.