java内部类详解

本文详细介绍了Java内部类的概念、用途及其四种类型:成员内部类、方法内部类、匿名内部类和静态内部类(嵌套类)。通过示例代码解释了如何在实际编程中运用这些内部类,并探讨了它们与外部类之间的交互。

内部类定义: 将一个类的定义放在另一个类的内部

为什么要内部类?

1.内部类提供通向外部类的窗口;

2.内部类中定义了和外部类相关的内容,利于维护;

3.每个内部类自身都能单独的继承基类或实现接口,而不受外部类的约束;

4.围绕第三点来看,内部类从一定程度上解决了java中单继承的限制;

内部类经常被使用,例如很多API的json返回值就会使用内部类:

public class SportVipResult implements Serializable {

    private static final long serialVersionUID = -6457159130973170095L;

    private String errorcode;
    private String message;
    private List<SportVipData> result;
    
     ……setter/getter……

    @Setter
    @Getter
    public class SportVipData {    //内部类
        private String orderid;
        private String orderitemid;
        private String mobile;
        private String createtime;
    }
}

我们暂且把 SportVipResult类称为OutClass,SportVipData类称为InnerClass。使用时,如果在OutClass类的内部使用,则可以直接使用InnerClass,若从外部类中使用则应该 OutClass.InnerClass 的方式。


关联外部类

当你创建了内部类后,它就和外部类有了某种联系,确切的说就是内部类可以直接访问外部类的所有元素,包括方法、属性等,反之是不成立的,也就是说,外部类不可以直接访问内部类元素

public class OutterClass {

    private  String URL = "http://www.baidu.com";
    List<String> list;

    public static void record() {
        //TODO ……
        System.out.println("this is outterclass method");
    }

    public class InnerClass {
        public int getSize() {
            record();
            list.add("a");
            System.out.println(URL);
            return list.size();
        }
    }
}

我们可以使用 .this 来获得外部类的引用,使用 .new 内部类自身的引用

public class OutterClass {

    public class InnerClass {
        public OutterClass getOutterClass() {
            return OutterClass.this;  // 使用 .this 获取OutterClass实例
        }
    }

    public static void main(String[] args) {
        OutterClass outterClass = new OutterClass();
        InnerClass innerClass = outterClass.new InnerClass();  //使用 .new 获取InnerClass实例
    }

}

内部类分类

1、成员内部类

成员内部类是最普通、常见的内部类,它被当做是外部类的一个普通成员,上面举例说明的都是成员内部类,它可以无限制的访问外部类的所有元素

使用成员内部类要注意以下两点:

  1. 成员内部类的元素(方法和变量)不能用static修饰;

  2. 成员内部类依赖于外部类,也就是说只有创建了外部类才能创建内部类;

public class OutterClass {

    public class InnerClass{
        public void method1(){
            System.out.println("inner method");
        }
    }

    public static void main(String[] args) {
        OutterClass outterClass = new OutterClass();
        InnerClass innerClass = outterClass.new InnerClass();
        innerClass.method1();
    }
}

2、方法内部类

当你实现了某类型的接口,于是可以方便的穿件并返回对接口实例的引用;或者你需要创建一个类来辅助你解决一个复杂的问题时,同时又不希望这个内部类是公用的,这时方法内部类就派上用场了。

注意:

  1. 方法内部类不能有访问修饰符;

  2. 方法内部类中的元素不能用static修饰;

//方法内部类
public class OutterClass {

    public BaseClass out() {
        class InnerClass implements BaseClass {
            private String name;

            public InnerClass(String name) {
                this.name = name;
            }

            public void inner() {
                //TODO
            }
        }
        return new InnerClass("");
    }

    public static void main(String[] args) {
        OutterClass outterClass = new OutterClass();
        BaseClass out = outterClass.out();
    }

}

interface BaseClass {

}

3、匿名内部类

匿名内部类是一个没有名字的方法内部类,故方法内部类的使用注意事项也同样适用于匿名内部类,此外还要注意:

  1. 匿名内部类没有构造器,因为类名都没有;

  2. 匿名内部类必须实现一个接口或抽象类;

public class OutterClass {

    public BaseClass out() {
        return new BaseClass() {  //看起来是不是怪怪的……
            private int id = 15;

            public void test() {
                System.out.println(id);
            }
        };
    }
    
    public static void main(String[] args) {
        OutterClass outterClass = new OutterClass();
        outterClass.out();
    }
}

interface BaseClass {

}

4、静态内部类(嵌套类)

成员内部类加上static修饰久病成了静态内部类,静态内部类与非静态内部类最大的区别是,非静态内部类在代码编译后就会包含一个指向它的外部类的引用,但是静态内部类是没有的。

注意:

  1. 静态内部类不可以使用外部类的非static元素(变量、方法);

  2. 静态内部类可以直接创建,不需要依赖于外部类的创建;

public class OutterClass {

    private static int code;
    private String name;

    public static class InnerClass{
        /*  静态内部类的内部可以存在static元素  */
        private static String messge;

        public static void method1(){

            /*  静态内部类可以访问外部类的所有元素,自然包括static元素  */
            System.out.println(code);

            /*  静态内部类不可以访问外部类的非static元素  */
            //  System.out.println(name);
        }
    }
}
public class BaseClass {
    public static void main(String[] args) {
        /*  静态内部类不用依赖于外部类的创建  */
        OutterClass.InnerClass innerClass = new OutterClass.InnerClass();
        innerClass.method1();
    }
}

静态内部类常常用于单例模式的实现,感兴趣的小伙伴可以移步至: 单例模式详解 一文

内部类的实例化

/*  外部类的内部实例化内部类  */
public static void main(String[] args) {
    InnerClass innerClass = new InnerClass();
    innerClass.method1();
}
/*  外部类使用内部类  */
public static void main(String[] args) {
     /* 如果是静态内部类,直接 */
    OutterClass.InnerClass innerClass = new OutterClass.InnerClass();
    innerClass.method1();
     
     /* 如果是普通的内部类,则 */
     OutterClass.InnerClass innerClass = new OutterClass().new InnerClass();
     innerClass.method1();
}

关于内部类

1.内部类可以有多个实例,每个实例都有自己的状态信息,而且与外部类相互独立;

2.一个外部类中可以让多个内部类以不同的方式继承基类或实现接口;

3.内部类的创建并不总是依赖于外部类的创建,这点上面强调过;

4.内部类是一个独立的实体类,我们编译下上面的OutterClass类发现:

javac -encoding UTF-8 OutterClass.java

生成了两个相互独立的class文件:

OutterClass$InnerClass.class
OutterClass.class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值