美文网首页
毕向东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基础教程-内部类

    内部类 定义:将一个类定义在另一个类的里面,里面那个类就称为内部类(内置类,嵌套类)。 访问特点: 内部类可以直接...

  • 毕向东Java基础教程 | Java概述

    基础常识 1、软件 一系列按照特定顺序组织的计算机数据和指令的集合; 分为系统软件和应用软件。 2、人机交互 软件...

  • 毕向东Java基础教程-继承【上】

    概述 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承单独...

  • 毕向东Java基础教程-继承【下】

    抽象类 概述 抽象定义抽象就是从多个事物中将共性的、本质的内容抽取出来。例如:狼和狗共性都是犬科,犬科就是抽象出来...

  • 毕向东Java基础教程-面向对象

    面向对象的概念 举例:大象装进冰箱。 面向过程步骤:打开冰箱--存储大象--关上冰箱。对于面向过程思想,强调的是过...

  • 毕向东java

    https://pan.baidu.com/s/1l3HRR9EtCsRAei0qHuWVeg

  • 毕向东Java基础教程-Java基础语法【下】

    本篇为Java基础语法【下】,包含程序流程控制、函数、数组这三部分内容。 程序流程控制 顺序结构 判断结构 三种格...

  • 毕向东Java基础教程-Java基础语法【上】

    本篇为Java基础语法【上】,包含关键字、标识符、注释、原码反码补码、常量与变量、运算符这六部分内容。 关键字 定...

  • Java 中的方法内部类

    Java 中的方法内部类 方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内...

  • PHP转JAVA的记录

    Java 数组 内部类 内部类的创建:内部类可以对包内其他类隐藏想实现一个接口时, 不想新建类文件 内部类可以访问...

网友评论

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

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