Java内部类

内部类详解  

  对于内部类我们平时工作中可能不会刻意地去使用它,但是诸如匿名内部类这样的使用方式,我们也在有意无意地在使用,今天跟大家来深入探讨一下内部类相关的知识,下面是本文目录结构

一、内部类分类详解

  • 成员内部类
  • 局部内部类
  • 静态内部类
  • 匿名内部类

二、内部类的使用场景和好处

本文参考的博客如下,感谢相关作者的辛勤付出

https://www.cnblogs.com/dolphin0520/p/3811445.html

https://www.cnblogs.com/chenssy/p/3388487.html

一、内部类分类详解

  内部类是编译时的概念,一旦编译成功,会成为完全不同的两个类,并且会生成两个class文件outer.class和outer$inner.class

  内部类可以是静态的,可用public、private、protected(默认)修饰,而外部类只能用public或protected(默认)

  内部类主要分为4种:成员内部类、局部内部类(方法内部类)、静态内部类、匿名内部类,下面分别来看一下:

1、成员内部类

  成员内部类所在的位置可以看做外部类的一个成员的位置。成员内部类中不能定义静态成员,它刻意访问外部类的所有成员,外部类访问成员内部类的成员有两种情况:

  1)外部类的非静态方法访问成员内部类:可以直接new一个内部类的对象,通过对象调用内部类的成员

Inner inner = new Inner();
inner.成员

  2)外部类的静态方法访问成员内部类:需要通过外部类的对象来new一个内部类的对象,通过对象调用内部类的成员

Outer outer = new Outer();
Inner inner = outer.new Inner();
inner.成员

代码演示:

package com.majiwei.javase.innerclass;

import lombok.Data;

/**
 * 成员内部类演示
 */
@Data
public class Outer1
{
    private String name = "outerName";

    private int age = 20;

    class Inner{

        private String name = "innerName";

        private int age = 10;

//        private static int age = 10; // 报错,不能定义静态成员

        public void print()
        {
            System.out.println("name:" + name + "   age:" + age);
            Outer1 outer = new Outer1();
            System.out.println("name:" + outer.getName() + "   age:" + outer.getAge());

        }
    }

    //外部类的普通方法访问成员内部类
    public void common_method()
    {
        Inner inner = new Inner();
        inner.print();
    }

    //外部类的静态方法访问成员内部类
    public static void static_method()
    {
//        Inner inner = new Inner(); // 报错
        Inner inner = new Outer1().new Inner(); //通过外部类的对象来创建内部类的对象
        inner.print();
    }

    public static void main(String[] args)
    {
        Outer1 outer = new Outer1();
        outer.common_method();
        System.out.println("============================");
        Outer1.static_method();
    }
}
View Code

运行结果:

 

2、方法内部类

  方法内部类所在的位置在外部内的方法内部。需要注意的是方法内部类不能有访问修饰符,它可以访问外部类的所有成员以及当前方法的常量(final修饰的)。方法内部类典型实现应用为获取内部类所实现接口的实现,详见后面的代码演示。

代码演示:

package com.majiwei.javase.innerclass;

import lombok.Data;

/**
 * 方法内部类演示
 */
@Data
public class Outer2
{
    private String name = "outerName";

    private int age = 20;

    public IMethodInner getMethodInner()
    {
        String methodName1 = "methodName1";
        final String methodName2 = "methodName2";

        //不能有访问修饰符
        class Inner implements IMethodInner{

            @Override
            public void print()
            {
                // 只能访问此方法的final变量和外部类的所有成员
                System.out.println("name:" + name + "   age" + age);
                Outer1 outer = new Outer1();
                System.out.println("name:" + outer.getName() + "   age" + outer.getAge());

//                System.out.println("methodName:" + methodName1); // 报错
                System.out.println("methodName:" + methodName2);
            }
        }

        return new Inner();
    }

    public static void main(String[] args)
    {
        Outer2 outer3 = new Outer2();
        IMethodInner inner = outer3.getMethodInner();
        inner.print();
    }
}
View Code

 运行结果:

3、静态内部类

  静态内部类和成员内部类类似,只是需要加上static关键字,这也造成使用上的区别。静态内部类中只能访问外部类的静态成员,而不能访问外部类的非静态成员。而外部类访问静态内部类的成员需要通过内部类对象来访问,当然对于内部类的静态成员可以直接通过静态内部类的类名直接访问。

代码演示:

package com.majiwei.javase.innerclass;

import lombok.Data;

/**
 * 静态内部类演示
 */
@Data
public class Outer3
{
    private String name = "outerName";

    private int age = 20;

    private static String outerCountry = "中国";

    @Data
    static class Inner{

        private String innerName = "innerName";

        private int innerAge = 10;

        private static String innerCountry = "美国";

        public void print()
        {
            System.out.println("name:" + innerName + "   age:" + innerAge);
//            System.out.println("name:" + name + "   age" + age); // 报错,不能访问外部类的非静态成员
            System.out.println("outer country:" + outerCountry); // 只能访问外部类的静态成员

        }
    }

    public void print()
    {
        //创建内部类对象不需要通过外部类来创建
        Inner inner = new Inner();
        inner.print();

        // 外部类访问内部类的静态成员直接用
        System.out.println("inner country:" + Inner.innerCountry);
        // 外部类访问内部类的非静态成员通过内部类的对象调用
        System.out.println("inner name:" + new Inner().getInnerName());
    }


    public static void main(String[] args)
    {
        Outer3 outer = new Outer3();
        outer.print();
    }
}
View Code

运行结果:

4、匿名内部类

  匿名内部类是没有名字的内部类,它没有访问修饰符和构造方法。在多线程、swing见到匿名内部类的情况会比较多

代码演示:

 1 package com.majiwei.javase.innerclass;
 2 
 3 /**
 4  * 匿名内部类演示
 5  */
 6 public class Outer4
 7 {
 8     public static void main(String[] args)
 9     {
10         new Thread(() -> {
11             System.out.println("线程启动...");
12         }).start();
13     }
14 }
View Code

运行结果

 二、内部类的使用场景和好处

  我们都知道Java是单继承的,但是可以实现多个接口。每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整,我认为这是使用内部类最大的一个好处,对于这一点。其次他还可以提高代码的封装性,隐藏不愿意对外开放的代码,在多线程、事件驱动的场景下也会有用武之地。

posted @ 2018-09-29 17:27  天马行空~_~  阅读(784)  评论(0)    收藏  举报