乐趣区

什么是Java内部类

内部类

(一) 概述

把类定义在另一个类的内部,该类就被称为内部类。

举例:把类 Inner 定义在类 Outer 中,类 Inner 就被称为内部类。

class Outer {class Inner {}
}

(二) 内部类的访问规则

​ A: 可以直接访问外部类的成员,包括私有

​ B: 外部类要想访问内部类成员,必须创建对象

(三) 内部类的分类

​ A:成员内部类

​ B:局部内部类

​ C:静态内部类

​ D:匿名内部类

(1) 成员内部类

成员内部类——就是位于外部类成员位置的类

特点:可以使用外部类中所有的成员变量和成员方法(包括 private 的)

A:格式
class Outer {
    private int age = 20;
    // 成员位置
    class Inner {public void show() {System.out.println(age);
        }
    }
}

class Test {public static void main(String[] ages) {
        // 成员内部类是非静态的演示
        Outer.Inner oi = new Outer.new Inner();
        oi.show();}
}
B:创建对象时:
// 成员内部类不是静态的:外部类名. 内部类名 对象名 = new 外部类名.new 内部类名();

// 成员内部类是静态的:外部类名. 内部类名 对象名 = new 外部类名. 内部类名();    
C:成员内部类常见修饰符:

A:private

如果我们的内部类不想轻易被任何人访问,可以选择使用 private 修饰内部类,这样我们就无法通过创建对象的方法来访问,想要访问只需要在外部类中定义一个 public 修饰的方法,间接调用。这样做的好处就是,我们可以在这个 public 方法中增加一些判断语句,起到数据安全的作用。

class Outer {
    private class Inner {public void show() {System.out.println(“密码备份文件”);
        }
    }
    
    public void method() {if(你是管理员){Inner i = new Inner();
            i.show();}else {System.out.println(“你没有权限访问”);
        }
       }
}

下面我们给出一个更加规范的写法

class Outer {
    private class Inner {public void show() {System.out.println(“密码备份文件”);
        }
    }
    // 使用 getXxx()获取成员内部类,可以增加校验语句(文中省略)public void getInner() {return new Inner();
       }
    
    public static void main(String[] args) {Outer outer = new Outer();
        Outer.Inner inner = outer.getInner();
        inner.show();}
}
B:static

这种被 static 所修饰的内部类,按位置分,属于成员内部类,但也可以称作静态内部类,也常叫做嵌套内部类。具体内容我们在下面详细讲解。

D:成员内部类经典题(填空)

请在三个 println 后括号中填空使得输出 25,20,18

class Outer {
    public int age = 18;    
    class Inner {
        public int age = 20;    
        public viod showAge() {
            int age  = 25;
            System.out.println(age);// 空 1
            System.out.println(this.age);// 空 2
            System.out.println(Outer.this.age);// 空 3
        }
    }
} 

(2) 局部内部类

局部内部类——就是定义在一个方法或者一个作用域里面的类

特点:主要是作用域发生了变化,只能在自身所在方法和属性中被使用

A 格式:

class Outer {public void method(){class Inner {}
    }
}

B:访问时:

// 在局部位置,可以创建内部类对象,通过对象调用和内部类方法
class Outer {
    private int age = 20;
    public void method() {
        final int age2 = 30;
        class Inner {public void show() {System.out.println(age);
                // 从内部类中访问方法内变量 age2,需要将变量声明为最终类型。System.out.println(age2);
            }
        }
        
        Inner i = new Inner();
        i.show();}
}

C: 为什么局部内部类访问局部变量必须加 final 修饰呢?

因为 局部变量是随着方法的调用而调用 使用完毕就消失 而堆内存的数据并不会立即消失

所以,堆内存还是用该变量,而该变量已经没有了。为了让该值还存在,就加 final 修饰。

原因是,当我们使用 final 修饰变量后,堆内存直接存储的 是值 ,而 不是变量名

(即上例 age2 的位置存储着常量 30 而不是 age2 这个变量名)

(3) 静态内部类

我们所知道 static 是不能用来修饰类的, 但是成员内部类可以看做外部类中的一个成员, 所以可以用 static 修饰, 这种用 static 修饰的内部类我们称作静态内部类, 也称作嵌套内部类.

特点:不能使用外部类的非 static 成员变量和成员方法

解释:非静态内部类编译后会默认的保存一个指向外部类的引用,而静态类却没有。

简单理解

即使没有外部类对象,也可以创建静态内部类对象,而外部类的非 static 成员必须依赖于对象的调用,静态成员则可以直接使用类调用,不必依赖于外部类的对象,所以静态内部类只能访问静态的外部属性和方法。

class Outter {
    int age = 10;
    static age2 = 20;
    public Outter() {}
     
    static class Inner {public method() {System.out.println(age);// 错误
            System.out.println(age2);// 正确
        }
    }
}

public class Test {public static void main(String[] args)  {Outter.Inner inner = new Outter.Inner();
        inner.method();}
}

(4) 匿名内部类

一个没有名字的类,是内部类的简化写法

A 格式:

new 类名或者接口名() {重写方法();
}

本质:其实是继承该类或者实现接口的子类匿名对象

这也就是下例中,可以直接使用 new Inner() {}.show(); 的原因 == 子类 对象.show();

interface Inter {public abstract void show();
}

class Outer {public void method(){new Inner() {public void show() {System.out.println("HelloWorld");
            }
        }.show();}
}

class Test {public static void main(String[] args)  {Outer o = new Outer();
        o.method();}
}    

如果匿名内部类中有多个方法又该如何调用呢?

Inter i = new Inner() {  // 多态,因为 new Inner(){}代表的是接口的子类对象
    public void show() {System.out.println("HelloWorld");
    }
};

B:匿名内部类在开发中的使用

​我们在开发的时候,会看到抽象类,或者接口作为参数。

而这个时候,实际需要的是一个子类对象。

如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。

结尾:

如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家!^_^

如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)

在这里的我们素不相识,却都在为了自己的梦而努力 ❤

一个坚持推送原创 Java 技术的公众号:理想二旬不止

退出移动版