美文网首页
毕向东Java基础教程-内部类

毕向东Java基础教程-内部类

作者: Lois_Huang | 来源:发表于2019-12-17 19:00 被阅读0次

    内部类

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

    访问特点

    • 内部类可以直接访问外部类中的成员,包括私有成员。
    • 而外部类要访问内部类中的成员必须要建立内部类的对象。

    用法
    一般用于类的设计。分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这时就将里面的事物定义成内部类。

    细节

    Example 1:为什么内部类能直接访问外部类的成员呢?是因为内部持有了外部类的引用-->外部类.this

    class Outer
    {
        int num = 3;
        class Inner
        {
            int num = 4;
            void show()
            {
                int num = 5;
                System.out.println(num); //打印5
                System.out.println(this.num); //打印4,或者可写为Inner.this.num
                System.out.println(Outer.this.num); //打印3
            }
        }
        public void method()
        {
            new Inner().show();
        }
    }
    class Demo
    {
        public static void main(String[] args)
        {
            new Outer().method();
        }
    }
    

    成员内部类

    定义:内部类定义在成员位置上。

    特点:

    • 可以被private static成员修饰符修饰。
    • 被static修饰的内部类只能访问外部类中的静态成员。

    Example 1:内部类和其成员都是非静态的

    class Outer
    {
        private int num = 3;
        class Inner
        {
            void show()
            {
                System.out.println("show run..."+num);
            }
        }
        public void method()
        {
            Inner in = new Inner();
            in.show();
        }
    }
    class Demo
    {
        public static void main(String[] args)
        {
            //直接访问外部类中的内部类中的成员
            Outer.Inner in = new Outer().new Inner(); //不常用,因为一般都将内部类封装了
            in.show();
        }
    }
    

    Example 2:内部类为静态,其成员为非静态的

    class Outer
    {
        private static int num = 3;
        static class Inner
        {
            void show()
            {
                System.out.println("show run..."+num);
            }
        }
        public void method()
        {
            Inner in = new Inner();
            in.show();
        }
    }
    class Demo
    {
        public static void main(String[] args)
        {
            //如果内部类是静态的,相当于一个外部类
            Outer.Inner in = new Outer.Inner();//不需要再创建Outer对象
            in.show();
        }
    }
    

    Example 3:内部类和其成员都为静态

    class Outer
    {
        private static int num = 3;
        static class Inner
        {
            static void show()
            {
                System.out.println("show run..."+num);
            }
        }
        public void method()
        {
            Inner.show();
        }
    }
    class Demo
    {
        public static void main(String[] args)
        {
            Outer.Inner.show();//不需要再创建Outer和Inner对象
        }
    }
    

    如果内部类中定义了静态成员,则该内部类也必须是静态的。
    如果类中的静态函数想访问内部类,则该内部类必须是静态的。

    局部内部类

    定义:内部类定义在局部位置上。

    特点:

    • 也可以直接访问外部类中的成员。
    • 同时可以访问所在局部中的局部变量,但必须是被final修饰的。

    Example 1:示例

    class Outer
    {
        int num = 3;
        void method()
        {
            int x = 9;
            final int y = 8;
            class Inner
            {       
                void show()
                {
                    System.out.println("show..."+num);//可以直接访问外部类中的成员。
                    System.out.println("show..."+x); //编译错误,从内部类中访问所在局部中的局部变量x,需要被声明为最终类型
                    System.out.println("show..."+y); //可以访问所在局部中的局部变量,但必须是被final修饰的。
                }
            }
            Inner in = new Inner();
            in.show();
        }
        //method()方法外不能访问Inner
    }
    class Demo
    {
        public static void main(String[] args)
        {
            new Outer().method();
        }
    }
    

    Example 2:为什么局部变量需要被final修饰,局部内部类才可访问?

    class Outer
    {
        int num = 3;
        Object method()//若method函数有参数int y,如果想在内部类Inner中访问,也需要写为final int y
        {
            int x = 9;
            class Inner
            {
                void show()
                {
                    System.out.println("show..."+x);
                }         
            }
            Object in = new Inner();
            return in;
        }
    }
    class Demo
    {
        public static void main(String[] args)
        {
            Outer out = new Outer();
            Object obj = out.method();
        }
    }
    

    method函数执行完就出栈了,x便不存在了,而obj对象仍然存在,于是访问不了x,因此需把x声明为常量。

    实质上是,java把局部内部类对象要访问的final型局部变量,复制过来变成该内部类对象中的一个成员变量,这样即使栈中局部变量(含final)已死亡,但由于它是final的,其值是不会发生改变的,因而内部类对象在局部变量死亡后,照样可以访问自己内部维护的一个值跟局部变量一样的成员变量,从而解决这个问题。

    注意:java8中匿名/局部内部类访问局部变量时,局部变量已经可以不用加final了,但其实这个局部变量还是final的(表现为对该值初始化后不能再赋值了),只不过不用显式的加上而已,推测可能是编译机制发生了改变。

    匿名内部类

    定义:局部内部类的简化写法。

    前提:内部类必须继承或实现一个外部类或者接口。

    格式new 外部类名或者接口名(){覆盖类或者接口中的代码,也可以自定义内容}

    简单理解:就是建立一个带内容的外部类或者接口的子类匿名对象。

    Example 1:匿名类中重写一个函数

    abstract class Demo
    {
        abstract void show();
    }
    class Outer
    {
        int num = 4;
        /*
        class Inner extends Demo
        {
            void show()
            {
                System.out.println("show..."+num);
            }
        }
        */
        public void method()
        {
            //new Inner().show();
            new Demo()//new了Demo类的子类对象
            {
                void show()
                {
                    System.out.println("show..."+num);
                }
            }.show();
        }
    }
    class Demo
    {
        public static void main(String[] args)
        {
            new Outer().method();
        }
    }
    

    Example 2:匿名类中重写两个函数

    interface Demo
    {
        void show1();
        void show1();
    }
    class Outer
    {
        int num = 4;
        public void method()
        {     
            Demo demo = new Demo() //类似于多态,父类引用指向了子类对象
            {
                public void show1()
                {
                    System.out.println("show1..."+num);
                }
                public void show2()
                {
                    System.out.println("show2..."+num);
                }
            }
            demo.show1();
            demo.show2();
        }
    }
    

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

    /*---以前的写法----*/
    interface Inter
    {
        void show1();
        void show2();
    }
    class InterImpl implements Inter
    {
        public void show1(){}
        public void show2(){}
    }
    class Demo
    {
        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 Demo
    {
        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();
        }
    }
    

    细节

    class Outer
    {
        void method()
        {
            new Object()
            {
                public void show()
                {
                    System.out.println("show run");
                }
            }.show();//创建的Object的子类对象,调用的子类对象的方法
            /*
            Object obj = new Object(){
                public void show()
                {
                    System.out.println("show run");
                }
            };
            obj.show(); //编译错误,在java.lang.Object里找不到show()方法,因为匿名内部类这个子类对象已经被向上转型为了Object类型,这样就不能使用子类特有的方法了,只能调用父类或接口中存在的方法。
            */
        }
    }
    class Demo
    {
        public static void main(String[] args)
        {
            new Outer().method();
        }    
    }
    

    相关文章

      网友评论

          本文标题:毕向东Java基础教程-内部类

          本文链接:https://www.haomeiwen.com/subject/kpdenctx.html