目录
  1. 1. 内部类概述
    1. 1.1. 成员内部类
      1. 1.1.1. 思考
        1. 1.1.1.1.
        2. 1.1.1.2.
    2. 1.2. 局部内部类
      1. 1.2.1. 思考
        1. 1.2.1.1.
        2. 1.2.1.2.
    3. 1.3. 匿名内部类
      1. 1.3.1. 前提
      2. 1.3.2. 格式
      3. 1.3.3. 本质
      4. 1.3.4. 调用
      5. 1.3.5. 思考
        1. 1.3.5.1.
        2. 1.3.5.2.
      6. 1.3.6. 思考
        1. 1.3.6.1.
        2. 1.3.6.2.
内部类学着累不累

内部类概述

在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

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

成员内部类

如何直接访问内部类的成员。
外部类名.内部类名 对象名 = 外部类对象.内部类对象;


class Outer {
private int num = 10;
class Inner {
public void show() {
System.out.println(num);
}
}
}

class InnerClassDemo {
public static void main(String[] args) {
// 访问Inner类的show()方法

//格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}

而成员内部类的使用,一般来说,在实际开发中是不会这样直接使用的,因为一般内部类就是为了不让外界直接访问的

因此,对Innershow()方法进行保护,使用private为了保证数据的安全性


class Outer {
private int num = 10;
class Inner {
private void show() {
System.out.println(num);
}
}
public void GetShow() {
Inner i = new Inner();
i.show();
}
}

class InnerClassDemo {
public static void main(String[] args) {
// 访问Inner类的show()方法
Outer o = new Outer();
o.GetShow();
}
}

使用static修饰让数据访问更加方便

  • 被静态修饰的成员内部类只能访问外部类的静态成员
  • 内部类被静态修饰后方法
    • 静态方法
    • 非静态方法

class Outer {
private int num = 10;
private static int num2 = 100;

//内部类用静态修饰是因为内部类可以看出是外部类的成员
public static class Inner {
public void show() {
System.out.println(num2);
}

public static void show2() {
System.out.println(num2);
}
}
}

class InnerClassDemo {
public static void main(String[] args) {
Outer.Inner oi = new Outer.Inner();
oi.show();
oi.show2();
System.out.println("----------");
//show2()的另一种调用方式
Outer.Inner.show2();
}
}

思考

填空,要求分别输出30,20,10

class Outer {
public int num = 10;
class Inner {
public int num = 20;
public viod show() {
int num = 30;
System.out.println(?);
System.out.println(?);
System.out.println(?);
}
}
}

class Outer {
public int num = 10;
class Inner {
public int num = 20;
public viod show() {
int num = 30;
System.out.println(num);
System.out.println(this.num);
System.out.println(Outer.this.num);
}
}
}
class InnerClassDemo4 {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}

注意:

  • 内部类和外部类没有继承关系
  • 通过外部类名限定this对象,(Outer.this

局部内部类

  • 可以直接访问外部类的成员

  • 在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

class Outer {
private int num = 10;

public void method() {
class Inner {
public void show() {
System.out.println(num);
}
}
// 创建内部类对象
Inner i = new Inner();
i.show();
}
}

class InnerClassDemo4 {
public static void main(String[] args) {
// 创建外部类对象,调用method()方法
Outer o = new Outer();
o.method();
}
}

思考

局部内部类如何访问局部变量?

class Outer {
private int num = 10;

public void method() {
final int num = 20;
class Inner {
public void show() {
// 从内部类中访问本地变量num; 需要被声明为最终类型
System.out.println(num);
}
}
Inner i = new Inner();
i.show();
}
}

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

局部内部类访问局部变量必须用final修饰

  • 局部变量是随着方法的调用而调用,随着调用完毕而消失。
  • 而堆内存的内容并不会立即消失。所以,我们加final修饰。
  • 加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
  • 在内存中存储的是数据20,所以,我还是有数据在使用。

匿名内部类

匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类

前提

存在一个类或者接口
这里的类可以是具体类也可以是抽象类。

格式

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

本质

是一个继承了该类或者实现了该接口的子类匿名对象。

interface Inter {
public abstract void show();
}

class Outer {
public void method() {
// new 类名或者接口名(){}
new Inter() {
// 重写方法
public void show() {
System.out.println("show");
}
};
}
}

调用

因此既然new Inter(){};这一坨是一个对象,那么对象调用show()方法还不简单?

// 接口
interface Inter {
public abstract void show();
}

class Outer {
public void method() {
// new 类名或者接口名(){}
new Inter() {
// 重写方法
public void show() {
System.out.println("show");
}
}.show();
}
}

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

如果Inter接口有两个方法,那如何调用?

interface Inter {
public abstract void show();
public abstract void show2();
}

class Outer {
public void method() {


//二个方法的时候
// 编译看左边,运行看右边
Inter i = new Inter() { //多态
public void show() {
System.out.println("show");
}

public void show2() {
System.out.println("show2");
}
};

i.show();
i.show2();
}
}

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

思考

如何使用PersonDemo调用study()方法?

interface Person {
public abstract void study();
}

class PersonDemo {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
public void method(Person p) {
p.study();
}
}

看到此,一般会想到使用具体类来实现接口,在实现类中重写study()方法即可

//实现类
class Student implements Person {
public void study() {
System.out.println("好好学习,天天向上");
}
}

class InnerClassTest {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
}
}

这种方然固然可行,那么采用匿名内部类的方式来实现:

class InnerClassTest {
public static void main(String[] args) {
// 测试
PersonDemo pd = new PersonDemo();
// 匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(new Person(){
public void study() {
System.out.println("好好学习,天天向上");
}
});
}
}

这种方式占内存较少,占用内存即可及时回收,一般在Android中使用的比较多,因为只使用一次,匿名回收,使用结束即回收

思考

按照要求,补齐代码
interface Inter {
void show();
}
class Outer {
//补齐代码
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”

  1. 首先从Outer.method()直接通过类名访问方法,可以判断出是一个静态方法
  2. Outer.method().show()后面还跟着调用show()方法,即可知道Outer.method()返回值是一个对象,对象为Inter
   interface Inter { 
void show();
}
class Outer {
// 返回对象为Inter的静态方法
public static Inter method(){
// 返回接口对象
return new Inter(){
public void show(){
System.out.println("HelloWorld");
}
}
}
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}

你学废了吗?

文章作者: Jachie Xie
文章链接: https://xjc5772.github.io/2020-08/14/%E5%AD%A6%E4%B9%A0/%E5%90%8E%E7%AB%AF%E5%AD%A6%E4%B9%A0/JAVA/%E5%86%85%E9%83%A8%E7%B1%BB%E5%AD%A6%E7%9D%80%E7%B4%AF%E4%B8%8D%E7%B4%AF/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 XJC&Blog
打赏
  • 微信
  • 支付宝

评论