Java之内部类


毫无疑问, 内部类是定义在类内部的。也就是说, 它既是一个类, 也是一个类的成员。

为什么使用?

通常我们会在类中定义引用类型变量, 相当于借用其它类的功能来辅助本类的功能实现。 既然我们可以借用它类的实现, 为什么还要在类内部来定义一个类并且实现呢?

(1) 达到隐藏实现的效果, 避免其它实现依赖它(封装)Wait!…在类的定义中, 也可以使用访问控制符来达到隐藏的效果啊, 例如default, protected. 通常我们单独的定义一个类, 是因为其它外部类(many)都要借助它来实现本类的功能.而内部类通常(当使用private修饰时)只是单独为本类(one)服务。

(2) 用于定制适于本类的成员. 通常情况下, 我们希望借助某个类来辅助我们功能的实现, 我们借助于它大部分的实现方法, 但是还要重写某些方法, 以到我们的需求, 也就是说该辅助类只适用于本类.And, 若其它的类继承本类时, 使用private修饰的内部类不会被继承, 我们对内部类的修改是安全的.

(3) 使代码更简洁:).

一、简介

通常我们定义一个类, 可以使用public, default(包访问) 修饰. 但是,
1.现在内部类作为一个类的成员, 可以使用public, protected, default, private修饰。
2.它本身是一个类, 也可以进行类的操作。 例如:继承, 实现接口, 定义新的变量。
3.它可以存在于类内部, 方法内(局部内部类)
3.匿名内部类是特殊的。它没有类名, 因此没有构造器, 也就不涉及类名的修饰问题。

二、分类

非静态内部类
静态内部类
匿名内部类

三、非静态内部类

非静态内部类即不使用static修饰, 它最大的特点就是能够访问外部类的成员, 包括private。原因在于它持有外部对象的引用, So,在使用内部类的对象之前, 要先创建一个外部类的对象。
它是与实例相关的。

定义
访问控制符 类名(){
}
示例

例子1——定义与访问对象的变量

public class MyInner {

    private int num = 5;

    class Inner1 {

        Inner1() {
            System.out.println("I am inner 1");
            //访问外部实例变量
            System.out.println("outer class num param:" + num);
        }
    }

    public static void main(String[] args) {
        new MyInner().new Inner1(); //注意调用方式
    }
}

// 输出:
I am inner 1
outer class num param:5

例子2——继承抽象类并实现方法

public class MyInner {

    private int num = 5;

    private abstract class changeNum {
        void chang() {
        }
    }

    private class ChangeSub extends changeNum {
        void change() {
            num = 100;
            System.out.println("num is change:" + num);
        }
    }

    public static void main(String[] args) {
        new MyInner().new ChangeSub().change();
    }
}

输出://
num is change:100

例子3——继承一个内部类

class Outer {
    public Outer() {

    }

    class Inner {
        void fun() {
        }
    }
}

public class MyInner {

    private class Sub extends Outer.Inner {
        public Sub(Outer outer) {
            outer.super();——关键
        }

        public void fun() {
            System.out.println("I am sub");
        }
    }

    public static void main(String[] args) {

        MyInner mi = new MyInner();
        Sub sub = mi.new Sub(new Outer());
        sub.fun();
    }
}

虽然还没想到为何要继承一个内部类, 但是可以先通过该例子加深印象。
1. 注意声明的方式class Sub extends Outer.Inner
2. 注意public Sub(Outer outer) { outer.super(); }这行代码。请记住, 生成一个非静态内部类对象需要依靠它的外部类对象

调用父类的构造方法一般使用super().但是Sub的父类是Outer的内部类, 因此需要通过Outer的对象outer来调用这个构造器outer.super();.

四、静态内部类

静态内部类使用static修饰, 并不与实例相关, 不必通过外部类实例来调用本身的构造器.使用静态内部类也就意味着: 我不需要访问外部类的非static成员.

示例——注意与非静态内部类调用区别
public class MyInner {

    private int num = 5;

    private static int num2 = 50;

    private static class StatiClass {
        void change() {
            System.out.println("num is not change:" + num2); // 假如改为num编译会报错
        }
    }

    public static void main(String[] args) {
        new StatiClass().change();
    }
}

五、匿名内部类

匿名内部类不能直接在类里面定义(它都没名字!!!), 它存在于方法内或在代码行直接定义它没有类名, 所以没有构造器, 可以在代码块进行初始化, 成员变量也可以在定义时就初始化。

定义——

new className(){
 {
   // initialize
 }
  methos and params
};
示例

例子1——实现接口或抽象类

// 定义接口和抽象类
interface Hi {
    void sayHi();
}

abstract class Hello {
    abstract void sayHello();
}

public class MyInner {
    
   public static void main(String[] args) {

        Hello hello1 = new Hello(){
            public void sayHello(){
                System.out.println("I smile and say hello");
            }
        };

        hello1.sayHello();

        Hi hi = new Hi() {
            public void sayHi() {
                System.out.println("I jump and say hi");
            }
        };

       	hi.sayHi();
    }
}

例子2——获取普通类实例并且…

// 假设这个是调用方法, 且list只使用一次
private static void init(List list) {

    }

普通版——

//before
        ArrayList list = new ArrayList();
        list.add("param1");
        list.add("param2");
        init(list);

升级版——

//now
        init(new ArrayList() {
                 {
                     add("param1");
                     add("param2");
                 }
             }
        );

在这里插入图片描述

六、总结

何时使用内部类?

(1) 当这个类不被其它对象使用, 只服务于当前类.
(2) 在复杂业务的情况下, 可以通过多重继承(并非一次继承多个类)或者实现多个接口来满足要求。

使用何种内部类?

1.静态内部类或者非静态内部类?
(1) 考虑定义的内部类是对象相关还是类相关.
(2) 需要访问外部类的非静态成员时, 使用非静态内部类,。
(3) 在使用静态内部类和非静态内部类的都可以的情况下, 选非静态内部类。因为非静态内部类不持有外部类对象引用, 避免内存泄漏.

2.何时使用匿名内部类?
匿名内部类有些像是一次性餐具。 假如某个类作为参数只使用一次(只构建这一个对象), 后面都不会再使用了, 那么我们可以把它定义为匿名内部类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值