• java内部类


    内部类在字面意思上理解就是包含在一个类里面的类。Java的官方解释为:内部类是定义在另一个类中的类。

     

    一、为什么要引入内部类?

      引入内部类的原因有以下三点:

    1. 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。(也就是内部类中可以访问外部类的私有成员)
    2. 内部类可以对同一包的其他类隐藏起来
    3. 当想要定义一个回调函数且不想编写大量的代码的时候,使用匿名内部类比较的便捷。(如时间响应机制,线程)

      注意:内部类一般使用在只要一次调用的地方,还有对某些接口和抽象类的实现时,不想创建接口或者抽象类的具体子类的时候,可以使用抽象类,接口和抽象类的内部类的应用返回的是接口和抽象类的子类对象。

      如下代码:

    Runnable runnable = new Runnable() {
    @Override
    public void run() {
    //线程中使用匿名内部类。runnable接受的是Runnable接口的子 类对象
    }
    };
    

     

    二、内部类

    通过代码来分析内部类:

    OuterClass类:                                                             
    
    public class OuterClass {
      private String str1 = "private: 我是外部类的私有成员变量";
      public String str2 = "public: 我是外部类的公有成员变量";
      static String str3 = "static: 我是外部类的静态成员变量";
      public void outerTest1() {
        System.out.println("我是外部类的公有成员方法");
      }
    
      private void outerTest2() {
        System.out.println("我是外部类的私有成员方法");
      }
    
      static void outerTest3() {
        System.out.println("我是外部类的公有成员方法");
      }
    
      // 在外部类调用内部类的方法和变量
      public void test() {
        // 外部类不能直接访问内部类的东西,需要创建对象访问
        InnerClass inner = new InnerClass();
        System.out.println(inner.string1);
        System.out.println(inner.string2);
        inner.innerTest3();
        inner.innerTest4();
      }
    
      class InnerClass{
        private String string1 = "private:我是内部类私有成员变量";
        public String string2 = "public:我是内部类的公有成员变量";
        public void innerTest3() {
        System.out.println("我是内部类的公有成员方法");
      }
    
      private void innerTest4() {
        System.out.println("我是内部类的私有成员方法");
      }
    
      // 在内部类中调用外部类的成员变量
      public void innerTest1() {
        System.out.println(str1);
        System.out.println(OuterClass.this.str2);
        System.out.println(str3);
        System.out.println(str4);
      }
    
    // 在内部类中调用外部类的成员方法
      public void innerTest2() {
        func();
        outerTest1();
        OuterClass.this.outerTest2();
        OuterClass.outerTest3();
      }
      public void show(){
        System.out.println("外围类访问外部类的内部类!!!");
      }
      }
      public String str4 = "public: 定义在内部类后边的外部类变量";
      public void func(){
        System.out.println("定义在内部类的后面的外部类方法");
      }
    }
    
    
    OuterInnerDemo类:                                                           
    public class OuterInnerDemo {
      public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        System.out.println("外部类调用内部类的成员变量及方法: ");
        outer.test();
        System.out.println();
        System.out.println("内部类调用外部类: ");
        // 创建内部类对象的方式1
        OuterClass.InnerClass inner = new OuterClass().new InnerClass();
        inner.innerTest1();
        inner.innerTest2();
        System.out.println();
        System.out.println("外围类调用内部类方法: ");
        // 创建内部类对象的方式2
        OuterClass.InnerClass inner2 = outer.new InnerClass();
        inner.show();
      }
    }

      运行截图:                                                           

       

      常规内部类的特点,有如下:

    • 在内部类中可以访问外部类的任何修饰符修饰的成员变量和方法(包括private,static,fianl,public,protected,默认的.全部测试过)
    • 在内部类中访问外部类的方式有两种:
      • 直接访问,就是直接调用方法名或者变量名。
    System.out.println(str2);
    • 通过下面这个格式访问:外部类名.this.(成员变量or方法)
    System.out.println(OuterClass.this.str2);
    • 外部类也可以访问内部类的任何修饰符修饰的成员变量和方法(全部测试过)
    • 外部类不能直接访问内部类的成员变量和成员方法,在外部类中必须创建内部类的对象,通过内部类的对象去访问内部类的成员方法和变量。
    InnerClass inner = new InnerClass();
    System.out.println(inner.string1);
    • 内部类访问外部类的成员变量和方法,不管它们声明在内部类之后还是之前,只要是外部类的对象,内部类就能访问。
    • 在外围类中访问内部类的方法,同样和普通类一样,通过创建类的对象去访问。
    • 外围类创建内部类对象的方式,如下:
    OuterClassName.InnerClassName  objName =
    new  OuterClassName().new InnerClassName();
    
    OuterClass.InnerClass inner = new OuterClass().new  InnerClass();
    OuterClassName.InnerClassName  objName =
    OuterClassObj.new InnerClassName();
    OuterClass.InnerClass inner2 = outer.new  InnerClass();
    • 为什么要像vii点一样创建对象的分析:

      对于一个类来说,我们创建类的对象是new ClassName(),然后通过创出的对象去调用类的方法。而对于内部类来说,它是外部类的一部分,因此要创建内部类的对象则要通过外部类的对象去调用,然后在按照new ClassName()原则去创建内部类的对象即可。

     

    三、局部内部类

    局部内部类就是定义在方法中的类。

    class AreaInnerClass{
    public void test() {
      final int age = 10;
      class Inner{
        public void addOne(){
          System.out.println(age+1);
        }
    
        private void addTwo(){
          System.out.println(age+2);
        }
      }
        new Inner().addOne();
        new Inner().addTwo();
      }
    }
    
    public class AreaInnerClassDemo{
      public static void main(String[] args) {
        new AreaInnerClass().test();
      }
    } 
    

    局部内部类的特点:

    1. 局部内部类定义的位置在一个方法的内部。
    2. 局部内部类对于外界完全隐藏起来了,即使外部类也不能访问它。
    3. 局部内部类不能用private和public进行修饰,因为局部内部类的作用域被限制在方法块中,及时用private和public进行修饰也毫无意义。
    4. 局部内部类的访问,通过在方法中创建局部内部类的对象来调用内部类的方法。

     

    四、匿名内部类

      匿名内部类其实就是对局部内部类的进一步的深入,假设只是创建一个类的对象,直接new className(){ .... },这样就不需要命名了。这种方式就叫做匿名内部类。

    public class SecretInnerClassDemo {
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    new Object(){
    void show(){
    System.out.println("匿名内部类....");
    }
    }.show();
    }
    }

     

      a) 格式:

    new className(){
    // 写方法
    }.funcName();

      b) 特点:

    1. new后面的className(类)必须是一个存在的类。(也就是说你new一个对象,那么就必须要存在一个具体类才能new)
    2. 存在前提,必须存在一个类,抽象类or接口

      c) 本质:

      是继承该类or接口的子类的匿名对象。(也就是说new className()或者new interfaceName(),返回的不是它们自身对象,返回而是它们的实现子类的对象,这个在匿名抽象类和匿名接口是最好理解,因为要重写接口和抽象类的方法,这个只有它们的子类能做,因此返回的是实现子类的对象)

     

    五、静态内部类

      有时候,使用内部类只是为了把一个隐藏在另一个类的内部,并不需要内部类引用外围类对象。为此,可以将内部类声明为static,来取消产生的引用。

    class StaticInnerClass {
    private static int a1 = 10;
    private static int b1 = 20;
    static class Inner{
    private int a = 10;
    private int b = 20;
    
    public int add(){
    return a+b;
    }
    
    public int add2(){
    return a1+b1;
    }
    }
    
    public void test(){
    System.out.println(new Inner().add());
    }
    }
    
    public class StaticInnerClassDemo{
    public static void main(String[] args) {
    new StaticInnerClass().test();
    }
    }
  • 相关阅读:
    VS2005使用AjaxPro.2
    一步步教你实现富文本编辑器(第三部分)
    Ajax实现在textbox中输入内容,动态从数据库中模糊查询显示到下拉框中
    一步步教你实现跨游览器的JS日历
    2009年中国10大网络公司业绩比较
    Beautiful smile and love
    NGINX 配置404错误页面转向
    wget使用范例
    mcrypt以及mhash扩展的安装!
    linux下常用压缩格式的压缩与解压方法
  • 原文地址:https://www.cnblogs.com/geore/p/7157782.html
Copyright © 2020-2023  润新知