Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 337|回复: 0

[Java基础知识]深入理解嵌套类和内部类

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-1 14:01:04 | 显示全部楼层 |阅读模式
    一、什么是嵌套类及内部类?

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

         其一、在一个类(外部类)中直接定义的内部类;

         其二、在一个方法(外部类的方法)中定义的内部类;

         其三、匿名内部类
    下面,我将说明这几种嵌套类的使用及注意事项。  二、静态嵌套类
         如下所示代码为定义一个静态嵌套类,  
      
      
      
       
      


      
      public class StaticTest {
       private static String name = "javaJohn";
       private String id = "X001";

       static class Person{
         private String address = "swjtu,chenDu,China";
         public String mail = "josserchai@yahoo.com";//内部类公有成员
         public void display(){
           //System.out.println(id);//不能直接访问外部类的非静态成员
           System.out.println(name);//只能直接访问外部类的静态成员
           System.out.println("Inner "+address);//访问本内部类成员。
         }
       }

        public void printInfo(){
          Person person = new Person();
          person.display();

          //System.out.println(mail);//不可访问
          //System.out.println(address);//不可访问

          System.out.println(person.address);//可以访问内部类的私有成员
          System.out.println(person.mail);//可以访问内部类的公有成员

        }

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

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


      
    class Outer{
      int outer_x = 100;
      private class Inner{//私有的内部类
       public int y = 10;
       private int z = 9;
       int m = 5;
       public void display(){
         System.out.println("display outer_x:"+ outer_x);
       }
       private void display2(){
        System.out.println("display outer_x:"+ outer_x);
       }
    }
    public Inner getInner(){//即使是对外公开的方法,外部类也无法调用
       return new Inner();
    }
    void test(){
       Inner inner = new Inner(); //可以访问
       inner.display();
       inner.display2();
       //System.out.println("Inner y:" + y);//不能访问内部内变量
       System.out.println("Inner y:" + inner.y);//可以访问
       System.out.println("Inner z:" + inner.z);//可以访问
       System.out.println("Inner m:" + inner.m);//可以访问
       InnerTwo innerTwo = new InnerTwo();
       innerTwo.show();
    }
    class InnerTwo{
       Inner innerx = getInner();//可以访问
       public void show(){
        //System.out.println(y);//不可访问Innter的y成员
        //System.out.println(Inner.y);//不可直接访问Inner的任何成员和方法
        innerx.display();//可以访问
        innerx.display2();//可以访问
        System.out.println(innerx.y);//可以访问
        System.out.println(innerx.z);//可以访问
        System.out.println(innerx.m);//可以访问
       }
    }
    }
    public class Test
    {
    public static void main(String args[]){
      
      Outer outer = new Outer();
    // Outer.Inner a=outer.getInner();//Inner类是私有的,外部类不能访问,如果Inner类是public ,则可以。
      outer.test();
    }
    }[/code]


         内部类Inner及InnterTwo只在类Outer的作用域内是可知的,如果类Outer外的任何代码尝试初始化类Inner或使用它,编译就不会通过。同时,内部类的变量成员只在内部内内部可见,若外部类或同层次的内部类需要访问,需采用示例程序
    中的方法,不可直接访问内部类的变量。

    四、在方法中定义内部类
         如下所示代码为在方法内部定义一个内部类:



    1. public class FunOuter {
    2. int out_x = 100;
    3. public void test(){
    4.   class Inner{
    5.     String x = "x";
    6.     void display(){
    7.        System.out.println(out_x);
    8.     }
    9.   }
    10. Inner inner = new Inner();
    11. inner.display();
    12. }
    13. public void showStr(String str){
    14.   //public String str1 = "test Inner";//不可定义,只允许final修饰
    15.   //static String str4 = "static Str";//不可定义,只允许final修饰
    16.   String str2 = "test Inner";
    17.   final String str3 = "final Str";
    18.   class InnerTwo{
    19.     public void testPrint(){
    20.     System.out.println(out_x);//可直接访问外部类的变量
    21.     //System.out.println(str);//不可访问本方法内部的非final变量
    22.     //System.out.println(str2);//不可访问本方法内部的非final变量
    23.     System.out.println(str3);//只可访问本方法的final型变量成员
    24.     }
    25.   }
    26.   InnerTwo innerTwo = new InnerTwo();
    27.   innerTwo.testPrint();
    28. }
    29. public void use(){
    30.    //Inner innerObj = new Inner();//此时Inner己不可见了。
    31.    //System.out.println(Inner.x);//此时Inner己不可见了。
    32. }
    33. public static void main(String[] args) {
    34.   FunOuter outer = new FunOuter();
    35.   outer.test();
    36. }
    37. }
    复制代码


         从上面的例程我们可以看出定义在方法内部的内部类的可见性更小,它只在方法内部 可见,在外部类(及外部类的其它方法中)中都不可见了。同时,它有一个特点,就是方法内的内部类连本方法的成员变量都不可访问,它只能访问本方法的final型成员。同时另一个需引起注意的是方法内部定义成员,只允许final修饰或不加修饰符,其它像static等均不可用。

    五、匿名内部类
         如下所示代码为定义一个匿名内部类:匿名内部类通常用在Java的事件处理上



      
      
    import java.applet.*;
    import java.awt.event.*;

         public class AnonymousInnerClassDemo extends Applet{
         public void init(){
             addMouseListener(new MouseAdapter(){
                 public void mousePressed(MouseEvent me){
                  showStatus("Mouse Pressed!");
             }
             });
         }
         public void showStatus(String str){
             System.out.println(str);
         }
         }
      
      

    在上面的例子中,方法addMouseListener接受一个对象型的参数表达式,于是,在参数里,我们定义了一个匿名内部类,这个类是一个MouseAdapter类型的类,同时在这个类中定义了一个继承的方法mousePressed,整个类做为一个参数。这个类没有名称,但是当执行这个表达式时它被自动实例化。同时因为,这个匿名内部类是定义在AnonymousInnerClassDemo 类内部的,所以它可以访问它的方法showStatus。这同前面的内部类是一致的。

    六、内部类使用的其它的问题

          通过以上,我们可以清楚地看出内部类的一些使用方法,同时,在许多时候,内部类是在如Java的事件处理、或做为值对象来使用的。同时,我们需注意最后一个问题,那就是,内部类同其它类一样被定义,同样它也可以继承外部其它包的类和实现外部其它地方的接口。同样它也可以继承同一层次的其它的内部类,甚至可以继承外部类本身。下面我们给出最后一个例子做为结束:





    1. public class Layer {
    2.   //Layer类的成员变量
    3.   private String testStr = "testStr";
    4.   //Person类,基类
    5.   class Person{
    6.     String name;
    7.     Email email;
    8.     public void setName(String nameStr){
    9.      this.name = nameStr;
    10.     }
    11.     public String getName(){
    12.       return this.name;
    13.     }
    14.     public void setEmail(Email emailObj){
    15.       this.email = emailObj;
    16.     }
    17.     public String getEmail(){
    18.       return this.email.getMailStr();
    19.     }
    20.     //内部类的内部类,多层内部类
    21.     class Email{
    22.      String mailID;
    23.      String mailNetAddress;
    24.      Email(String mailId,String mailNetAddress){
    25.      this.mailID = mailId;
    26.      this.mailNetAddress = mailNetAddress;
    27.      }
    28.      String getMailStr(){
    29.         return this.mailID +"@"+this.mailNetAddress;
    30.      }
    31.     }
    32.   }
    33.    //另一个内部类继承外部类本身
    34.    class ChildLayer extends Layer{
    35.      void print(){
    36.        System.out.println(super.testStr);//访问父类的成员变量
    37.      }
    38.    }
    39.    //另个内部类继承内部类Person
    40.     class OfficePerson extends Person{
    41.      void show(){
    42.        System.out.println(name);
    43.        System.out.println(getEmail());
    44.      }
    45.     }
    46.     //外部类的测试方法
    47.     public void testFunction(){
    48.       //测试第一个内部类
    49.       ChildLayer childLayer = new ChildLayer();
    50.       childLayer.print();
    51.       //测试第二个内部类
    52.       OfficePerson officePerson = new OfficePerson();
    53.       officePerson.setName("abner chai");
    54.       //注意此处,必须用对象.new 出来对象的子类对象
    55.       //而不是Person.new Email(...)
    56.       //也不是new Person.Email(...)
    57.       officePerson.setEmail(officePerson.new Email("josserchai","yahoo.com"));
    58.        officePerson.show();
    59.     }
    60.      public static void main(String[] args) {
    61.       Layer layer = new Layer();
    62.       layer.testFunction();
    63.      }
    64. }
    复制代码
      



      
      
       
       

         
       

         
       
      



    源码下载:http://file.javaxxz.com/2014/10/1/140104500.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-5 01:46 , Processed in 0.323084 second(s), 38 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表