黑马程序员_java内部类

------- android培训java培训、期待与您交流! ----------

概述:
    将类定义在一个类的内部,这个定义在其他类内部的类称为内部类,包含内部类的类称为外部类。
    Java从JDK1.1开始引入内部类。
格式举例:
    public class Outer{
        private class Inner{}
    }
内部类的作用:
    1、内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类
    2、内部类成员可以直接访问外部类的成员,包括私有数据,因为内部类被当成其外部类成员,
       同一个类的成员之间可以相互访问。但外部类不能访问内部类的实现细节
    3、匿名内部类适合用于创建那些仅需一次使用的类
访问特点:
    1、内部类可以直接访问外部类的成员,包括私有成员
      2、外部类要访问内部类中的成员必须创建内部类对象
内部类的分类:
    内部类又分为成员内部类和局部内部类。
    成员内部类是一种和属性、方法、构造器和初始化块的类成员,局部内部类和匿名内部类不是类成员。
    成员内部类又分为两种:静态内部类和非静态内部类,使用static修饰的成员内部类是静态内部类。
非静态内部类:
        非静态内部类作为外部类,所以可以使用任意访问修饰符如public、private、protect等修饰。
    因为此类型内部类的上一程序单元是外部类,它就具有4个作用域:同一个类,同一个包,父子类和
    任何位置,因此可以使用4中访问修饰符。
      非静态内部类里可以直接访问外部类的成员,包括私有成员,当在非静态内部类访问某个变量时,
    优先级从内而外:内部类方法的局部变量>内部类的成员变量>外部类的成员变量。
        因此,如果外部类的成员变量、内部类的成员变量、内部类方法里的局部变量同名,则可以通过
        使用外部类类名.this.、this作为限定来区分。而如果在外部类想要访问内部类则必须在外部类中
        创建非静态内部类对象,根据静态不能访问非静态成员的原则,不允许在外部类的静态成员中直接
        使用非静态内部类。
        演示:
            public class OuterClass {
                String str = "这是外部类中的属性";
                private class InnerClass
                {
                    String str = "这是内部类中的属性";
                    /**
                     * 打印外部类成员和内部类成员的方法
                     */
                    public void showField()
                    {
                        String str = "这是局部变量";
                        System.out.println("访问外部类成员:"
                            + OuterClass.this.str);
                        System.out.println("访问内部类成员:" + this.str);
                        System.out.println("访问内部类方法中的局部变量:"
                            + str);
                    }
                }
                /**
                 * 创建访问内部类的方法
                 */
                public void visitInnerClass() //如果加上static修饰,编译不通过
                {
                    //创建内部类对象
                    InnerClass in = new InnerClass();
                    //调用打印方法
                    in.showField();
                }
                public static void main(String[] args) {
                    //创建外部类对象
                    OuterClass oc = new OuterClass();
                    oc.visitInnerClass();
                }
            }
        编译上面程序,看到在文件所在路径生成了两个class文件,一个是OuterClass.class,
        另一个是OuterClass$InnerClass.class,前者是外部类的文件,后者是内部类文件,
        即成员内部类(包括静态和非静态)的class文件形式:外部类名$内部类名.class。
    Java不允许在非静态内部类里定义静态成员,否则编译出错。
        演示说明:
            public class Outer{
                private class Inner{
                    //下面三个静态声明都将引发编译错误
                    static{}
                    private static int a;
                    private static void show(){}
                }
            }
    在外部类以外使用非静态内部类,则非静态内部类不能使用private修饰。语法如下:
        外部类名.内部类名 标识符 = new 外部类名().new 内部类名();
        演示:
            public class Outer {
                public class Inner
                {
                    public void show()
                    {
                        System.out.println("这是内部类");
                    }
                }
            }
            public class Test{
                public static void main(String[] args) {
                    //在外部类以外创建内部类对象
                    Outer.Inner in = new Outer().new Inner();
                    in.show();
                }
            }
静态内部类:
    使用static来修饰的成员内部类称为静态内部类。根据静态成员不能访问非静态的成员的规则,
    静态内部类不能访问外部类的实例成员,只能访问外部类的类成员(static修饰)。
    即使是在静态内部类的实例方法也不能访问外部类的实例成员。
        演示:
            public class Outer{
                private  int age = 0;
                private static class Inner{
                    public void show()
                    {
                        System.out.println(age); //编译出错
                    }
                }
            }
    静态内部类里也可以直接访问外部类的静态成员,当在静态内部类访问某个静态属性时,
    优先级也是从内而外:内部类的静态成员变量>外部类的静态成员变量。
    因此,如果外部类的静态成员变量、内部类的静态成员变量同名,则可以通过使用
    外部类类名.变量名、内部类名.变量名作为限定来区分。
        演示:
            public class Outer {
                static String str = "这是外部类中的属性";
                private static class Inner
                {
                    private static String str = "这是内部类中的属性";
                    /**
                     * 打印外部类成员和内部类成员的方法
                     */
                    public void showField()
                    {
                        //System.out.println(age);
                         String str = "这是局部变量";
                        System.out.println("访问外部类成员:" + Outer.str);
                        System.out.println("访问内部类成员:" + Inner.str);
                        System.out.println("访问内部类方法中的局部变量:"
                            + str);
                    }
                }
                /**
                 * 创建访问内部类的方法
                 */
                public static void visitInnerClass()
                {
                    //创建内部类对象
                    Inner in = new Inner();
                    //调用打印方法
                    in.showField();
                }
                public static void main(String[] args) {
                    //创建外部类对象
                    Outer oc = new Outer();
                    oc.visitInnerClass();
                }
            }
    在外部类以外使用静态内部类,内部类也不能用private修饰,语法如下:
        外部类名.内部类名 标识符 = new 外部类名.内部类名();
        演示:
            public class Outer {
                public static class Inner
                {
                    public void show()
                    {
                        System.out.println("这是内部类");
                    }
                }
            }
            public class Test{
                public static void main(String[] args) {
                    Outer.Inner in = new Outer.Inner();
                    in.show();
                }
            }
局部内部类:
    如果把一个内部类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类仅在该方法里有效。
    因此局部内部类不能使用任何修饰符,如果需要使用局部内部类定义变量、创建实例或派生子类,
    那么都只能在局部内部类所在的方法内进行。
        演示:
            Public class Outer{
                  public static void main(String[] args){
                      Class Inner{
                          Int a;
                    }
                      Class InnerSub extends Inner{
                          Int b;
                      }
                      Inner i = new InnerSub();
                      i.a = 8;
                  }
              }
    编译上面程序,生成了三个class文件:Outer.class、Outer$1Inner.class、Outer$1InnerSub.class。
    局部内部类的class文件比成员内部类的class文件多了一个数字,这是因为同一个类里不可能有两个
    同名的成员内部类,而同一个类里则可能有一个以上同名的局部内部类(处于不同的方法中),
    所以java为局部内部类的class文件名中增加了一个数字,作为区分。
匿名内部类:
    匿名内部类适合创建只需一次使用的类,定义匿名内部类的格式如下:
        new 父类构造器(实参列表) 或者 实现接口()
        {
            //实体部分
        }
         从定义格式可以看出,匿名内部类必须继承一个父类,或实现一个接口,有且继承或实现一个。
    关于内部类的两条规则:
        1:匿名内部类不能是抽象类,因为在创建匿名内部类的同时,会立即创建匿名内部类的对象,
           因此不允许将匿名内部类定义成抽象类
        2:匿名内部类不能定义构造器。因为匿名内部类没有类名。但可以定义实例初始化块。
    匿名内部类最常见的创建方式是定义在接口中,
        演示:
            public class FileTest {
                  public static void main(String[] args) {
                      File file = new File("h:");
                      String[] strArr = file.list(new FilenameFilter()
                      {
                          public boolean accept(File dir, String name) {
                              return new File(dir, name).isFile() &&
                                name.endsWith(".java");
                          }
                      });
                      for(String item : strArr)
                      {
                          System.out.println(item);
                      }
                  }
            }
    注意事项:
        当创建匿名内部类是,必须实现接口或抽象父类里的所有抽象方法。如果匿名内部类和
        局部内部类里需要访问外部类的局部变量,则必须使用final修饰符来修饰外部类的局部变量。
        演示:
            public class OuterClass {
                public static void main(String[] args)
                {
                    final int a = 20;
                    class InnerClass
                    {
                        public void show()
                        {
                            //如果不加final,此处报错
                            System.out.println(a);
                        }
                    }
                }
            }   

------- android培训java培训、期待与您交流! ----------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值