zoukankan      html  css  js  c++  java
  • java中的内部类

    概述

    将一个类定义在另一个类的里面,里面的那个类就称为内部类(内置类,嵌套类)

    分析事物A时,发现该事物A描述中还有事物B,而且这个事物B还在访问被描述事物A的内容,将事物B定义成内部类来描述。

    特点

    1. 内部类可以直接访问外部类中的成员;
    2. 外部类要访问内部类,必须建立内部类的对象;

    举例:

    package innerdemo;
    
    public class InnerDemo1 {
        public static void main(String[] args) {
            Outer.Inner in = new Outer().new Inner(); // 直接访问内部类的方法
            in.show();
    
            Outer o = new Outer();//
            o.method();
        }
    }
    class Outer{
    
        private int num = 3;
        // 内部类
        class Inner{
            void show(){
                num = 100;
                System.out.println("内部类run..."+num);
            }
        }
    
        public void method(){
            Inner in = new Inner(); //外部类要访问内部类,必须建立内部类的对象;
            in.show();
        }
    }
    

    修饰符

    1. 直接访问外部类中的内部类中的成员:(不多见)

      外部类名.内部类名 变量名 = new 外部类名(). new 内部类名();

      Outer.Inner in = new Outer().new Inner();

      in.show();

    2. 内部类是静态的类,相当于一个外部类。外部类只要一加载,内部类就存在了,所以直接new一个内部类对象出来;

      Outer.Inner in1 = new Outer.Inner();

      public class InnerClassDemo {
          public static void main(String[] args) {
              // 内部类是静态的。相当于一个外部类
              Outer.Inner in1 = new Outer.Inner();
              in1.show();
          }
      }
      class Outer{
          private static int num = 3;
          // 内部类
          static class Inner{
              void show(){
                  System.out.println("内部类run..."+num);
              }
          }
      }
      
    3. 如果内部类是静态的,成员是静态的,就不需要对象了。如果内部类中定义了静态成员,该内部类也必须是静态的。

      package java_demo_2;
      
      public class InnerClassDemo {
          public static void main(String[] args) {
              Outer.Inner.function();
          }
      }
      class Outer{
          private static int num = 3;
          // 内部类
          static class Inner{
              void show(){
                  System.out.println("内部类run..."+num);
              }
              public static void function(){
                  System.out.println("内部类是静态的,成员也是静态的,不需要创建对象"+num);
              }
          }
      }
      

    细节

    package java_demo_2;
    
    public class InnerClassDemo {
        public static void main(String[] args) {
            new Outer().method();
        }
    
    class Outer{
        int num = 3;
        // 内部类
        class Inner{
            int num = 4;
            void show(){
                int num = 5;
                System.out.println(num); // num 5
                System.out.println(this.num); // 4 局部和成员变量重名
                System.out.println(Outer.this.num); // 3
            }
        }
        void method(){
            new Inner().show();
        }
    }
    

    为什么内部类能直接访问外部类中成员呢?

    那是因为内部类持有了外部类的引用。外部类名.this

    局部内部类

    内部类可以存放在局部位置上,可以放在方法中,放在代码块中。

    class Outer1{
    
        int num = 3;
    
        void method(){
            // 内部类在方法中
    
            class Inner{
                void show(){
                    System.out.println("方法中的内部类:"+num);
                }
            }
            // 创建对象
            Inner in = new Inner();
            in.show();
        }
    
        {
            // 内部类在代码块中
            class Inner2{
                void show(){
                    System.out.println("代码块中的内部类:" + num);
                }
            }
            Inner2 in2 = new Inner2();
            in2.show();
        }
    }
    

    内部类在局部位置上只能访问局部中被final修饰的局部变量;

    class Outer{
        int num = 3;
        void method(){
    
            final int x  = 9; // 这个好像都行 int x = 9 不报错;
            class Inner{
                void show(){
                    System.out.println("show..."+x); // 内部类在局部位置上只能访问局部中被final修饰的局部变量;
                }
            }
            // 创建对象
            Inner in = new Inner();
            in.show();
        }
    }
    

    匿名内部类

    概述

    内部类的简写格式。要简写,必须和外部类有关系。必须有前提:内部类必须继承或者实现一个外部类或者接口。

    格式: new 父类or接口(){子类内容};

    匿名内部类,其实就是一个匿名子类对象;这个对象比较胖。

    按道理要先继承父类,重构方法,再创建对象调用方法如:

    class Inner extends InnerDemo{
        void show() {
            System.out.println("内部类run..." + num);
        }
    }
    public void method() {
       new Inner().show();
    }
    

    现在直接在方法里,进行new 父类(){重构方法;}

    new InnerDemo(){ // 匿名内部类,new 他爹(){把方法重写;}
        void show(){
            System.out.println("show..."+num);
        }
    }
    

    具体代码如下:

    public class InnerClassDemo {
        public static void main(String[] args) {
            new Outer().method();
        }
    }
    
    // 抽象类
    abstract class InnerDemo{
        abstract void show();
    }
    class Outer {
    
        private int num = 3;
    
        // 内部类
    //    class Inner {
    //        void show() {
    //            System.out.println("内部类run..." + num);
    //        }
    //
    //    }
    
        public void method() {
    //        new Inner().show();
            new InnerDemo(){ // 匿名内部类,new 他爹(){把方法重写;}
                void show(){
                    System.out.println("show..."+num);
                }
            }.show();
        }
    }
    

    应用

    注释部分:普通内部类继承外部接口时代码:

    interface Inter{
        void show1();
        void show2();
    }
    class Outer {
        private int num = 3;
    
        // 内部类
        /*
        class Inner implements Inter {
            public void show1(){
    
            }
            public void show2(){
    
            }
        }
        */
        public void method(){
    
    //        Inner in = new Inner();
    //        in.show1();
    //        in.show2();
            Inter in = new Inter(){
                public void show1(){
    
                }
                public void show2(){
    
                }
    
            };
            in.show1();
            in.show2();
        }
    }
    

    通常的使用场景之一:当函数参数是接口类型时,而且接口中的方法不超过三个,可以用匿名内部类作为实际参数进行传递。

    // 正常写
    public class InnerClassDemo {
        public static void main(String[] args) {
        
        show(new InterImpl());
    }
        public static void show(Inter in){
            in.show1();
            in.show2();
        }
    }
    interface Inter{
        void show1();
        void show2();
    }
    
    class InterImpl implements Inter{
        public void show1(){}
        public void show2(){}
    }
    
    // 简写,将匿名内作为实际参数传递
    public class InnerClassDemo {
        public static void main(String[] args) {
        
        show(new Inter(){
            public void show1(){}
            public void show2(){}
        });
    }   
        public static void show(Inter in){
            in.show1();
            in.show2();
        }
    }
    //接口
    interface Inter{
        void show1();
        void show2();
    }
    

    分类

    • 成员内部类(静态内部类和非静态内部类)
    • 局部内部类
    • 匿名内部类

    成员内部类

    • 静态内部类:直接通过外部类调用静态内部类的构造器
    • 非静态内部类:先创建外部类的对象,再通过外部类的对象调用内部类的构造器或者
      外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
    package innerdemo;
    
    /**
     * @ClassName: InnerClassDemo
     * @author: benjamin
     * @version: 1.0
     * @description: TODO
     * @createTime: 2019/06/11/10:11
     */
    
    public class InnerClassDemo {
        public static void main(String[] args) {
            // 创建静态内部类的对象
            Person.Dog d = new Person.Dog();// 直接通过外部类调用静态内部类的构造器
            //创建非静态内部类的对象
    //        Person.Bird b = new Person().new Bird();
            Person p = new Person();
            Person.Bird b = p.new Bird();// 通过外部类的对象调用内部类的构造器
            b.info();
    
        }
    }
    
    class Person{
    
        String name;
        int age;
    
        // 非静态成员内部类
        class Bird{
            String name;
            int id;
            public Bird(){
    
            }
    
            public void setName(String name){
                this.name = name;
            }
            public void info(){
                show();
            }
        }
    
        // 静态成员内部类
        static class Dog{
            String name;
            int id;
            public Dog(){
    
            }
    
            public void setName(String name){
                this.name = name;
            }
            public void info(){
    
            }
        }
    
    
        // 外部类的成员方法
        public void show(){
            System.out.println("我是外部类的show()方法");
        }
    }
    

    局部内部类:常常使用一个方法,使其返回值为某个类或接口的对象,而这个类或接口在方法内部创建。举例:

    匿名内部类:

    举例:

    class OuterJu{
    
        // 局部内部类的使用
        public Comparable getComparable(){
            //1.创建一个实现Comparable接口的类:局部内部类
            class MyComparable implements Comparable{
                @Override
                public int compareTo(Object o) {
                    return 0;
                }
            }
            // 2. 返回一个实现类的对象
            return new MyComparable();
        }
    
        // 匿名内部类的使用
        public Comparable getComparable1(){
            //返回一个实现Comparable接口的匿名内部类的对象
            return new Comparable() {
                @Override
                public int compareTo(Object o) {
                    return 0;
                }
            };
        }
    }
    

    细节

    细节1

    主函数会报错,因为无法访问非静态类,而且由于是静态不能采用this.new Inner()

    方法:需要将Inner定义成静态类;

    package java_demo_2;
    
    /**
     * @ClassName: InnerClassDemo5
     * @author: benjamin
     * @version: 1.0
     * @description: TODO
     * @createTime: 2019/04/13/22:28
     */
    
    public class InnerClassDemo5 {
        class Inner{// 如果不定义成静态,主函数会报错;
    
        }
    
        public static void main(String[] args) {
    
            new Inner(); //无法从静态上下文中引用非静态 变量 this
            // 因为主函数是静态的;
        }
    
        public void method(){
            
            new Inner(); // 正确
        }
    
        public static void show(Inter in){
            in.show1();
            in.show2();
        }
    }
    
    interface Inter{
        void show1();
        void show2();
    }
    

    细节2:

    // 正确的
    package java_demo_2;
    
    public class InnerClassDemo6 {
        public static void main(String[] args) {
    
            new Outer6().method();
        }
    
    }
    
    class Outer6{
    
        // 创建的匿名内部类相当于
    //    class Inner6 extends Object{
    //        public void show(){
    //            System.out.println("show run");
    //        }
    //    }
    //    new Inner6.show();
        void method(){
    
            new Object(){
                public void show(){
                    System.out.println("show run");
                }
            }.show();
        }
    }
    

    编译看左边

    package java_demo_2;
    
    public class InnerClassDemo6 {
        public static void main(String[] args) {
    
            new Outer6().method();
        }
    }
    
    class Outer6{
    
        void method(){
    
             Object obj = new Object(){
                public void show(){
                    System.out.println("show run");
                }
             };
             obj.show();
    //         Error:(35, 13) java: 找不到符号
            // 因为匿名内部类这个子类对象被向上转型为Object类型,
            // 这样就不再使用子类特有的方法了;
        }
    }
    
  • 相关阅读:
    14.18 InnoDB Backup and Recovery 备份和恢复:
    14.18 InnoDB Backup and Recovery 备份和恢复:
    php使用 _before_index() 来实现访问页面前,判断登录
    php使用 _before_index() 来实现访问页面前,判断登录
    查询方式实例演示
    查询方式实例演示
    haproxy timeout server 46000 后台超时时间
    haproxy timeout server 46000 后台超时时间
    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE
    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE
  • 原文地址:https://www.cnblogs.com/benjieqiang/p/11512813.html
Copyright © 2011-2022 走看看