• 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();
    }
    }
  • 相关阅读:
    yii2 gii 命令行自动生成控制器和模型
    控制器中的方法命名规范
    Vue Property or method "" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based
    IDEA插件:GsonFormat
    Spring Boot : Access denied for user ''@'localhost' (using password: NO)
    Typora添加主题
    Git基础命令图解
    Java Joda-Time 处理时间工具类(JDK1.7以上)
    Java日期工具类(基于JDK1.7版本)
    Oracle SQL Developer 连接Oracle出现【 状态: 失败 -测试失败: ORA-01017: invalid username/password; logon denied】
  • 原文地址:https://www.cnblogs.com/geore/p/7157782.html
Copyright © 2020-2023  润新知