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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值