强哥说Java--Java内部类(一)

简介: 强哥说Java--Java内部类(一)

目标



什么是内部类


内部类的分类和作用


内部类如何定义


如何实例化以及各自的特点


要注意区分不同类型内部类的异同


为什么需要内部类


1. 概念



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


与之对应的,包含内部类的类被称为外部类。请阅读下面的代码:


// 外部类 Car
public class Car {
    // 内部类 Engine
    class Engine {
        private String innerName = "发动机内部类";
    }
}


代码中,Engine 就是内部类,而 Sky 就是外部类。

2. 分类



Java 中的内部类可以分为 4 种:


成员内部类


静态内部类


方法内部


匿名内部类


2.1 成员内部类


2.1.1 定义


成员内部类也称为普通内部类,它是最常见的内部类。可以将其看作外部类的一个成员。在成员内部类中无法声明静态成员。


如下代码中声明了一个成员内部类:


// 外部类 Car
public class Car {
    // 内部类 Engine
    private class Engine {
        private void run() {
            System.out.println("发动机启动了!");
        }
    }
}


我们在外部类 Sky 的内部定义了一个成员内部类 Engine,在 Engine 下面有一个 fly() 方法,其功能是打印输出一行字符串:“发动机启动了!”。


另外,需要注意的是,与普通的 Java 类不同,含有内部类的类被编译器编译后,会生成两个独立的字节码文件:


Car$Engine.class
Car.class


内部类 Engine 会另外生成一个字节码文件,其文件名为:外部类类名 $ 内部类类名.class。


2.1.2 实例化


内部类在外部使用时,无法直接实例化,需要借助外部类才能完成实例化操作。关于成员内部类的实例化,有 3 种方法:


我们可以通过 new 外部类().new 内部类() 的方式获取内部类的实例对象:

实例演示


// 外部类 Car
public class Car {
    // 内部类 Engine
    private class Engine {
        private void run() {
            System.out.println("发动机启动了!");
        }
    }
    public static void main(String[] args) {
        // 1.实例化外部类后紧接着实例化内部类
        Engine engine = new Car().new Engine();
        // 2.调用内部类的方法
        engine.run();
    }
}


运行结果:


发动机启动了!


我们可通过先实例化外部类、再实例化内部类的方法获取内部类的对象实例:


public static void main(String[] args) {
    // 1.实例化外部类
    Car car = new Car();
    // 2.通过外部类实例对象再实例化内部类
    Engine engine = car.new Engine();
    // 3.调用内部类的方法
    engine.run();
}


编译执行,成功调用了内部类的 fly () 方法:


$javac Car.java
java Car
发动机启动了!


我们也可以在外部类中定义一个获取内部类的方法 getEngine(),然后通过外部类的实例对象调用这个方法来获取内部类的实例:

实例演示


package com.caq.oop.demo10;
public class Outer {
    private int id = 10;
    public void out(){
        System.out.println("这是外部类的方法");
    }
    //一个java类中可以有多个class类,但只能有一个public class
    public class In {
        public void in() {
            System.out.println("这是内部类的方法");
        }
    }
    public static void main(String[] args) {
        //实例化内部类,调用内部类的方法
        In In = new Outer().new In();
        In.in();
    }
}


运行结果:


这是内部类的方法


这种设计在是非常常见的,同样可以成功调用执行 fly() 方法。


2.1.2.1 成员的访问


成员内部类可以直接访问外部类的成员,例如,可以在内部类的中访问外部类的成员属性:


实例演示


// 外部类 Sky
public class Sky {
    String name;
    public Engine getEngine() {
        return new Engine();
    }
    // 内部类 Engine
    private class Engine {
        // 发动机的起动方法
        private void fly() {
            System.out.println(name + "的发动机启动了!");
        }
    }
    public static void main(String[] args) {
        // 实例化外部类
        Sky Sky = new Sky();
        // 为实例属性赋值
        Sky.name = "张三";
        // 获取内部类实例
        Engine engine = Sky.getEngine();
        // 调用内部类的方法
        engine.fly();
    }
}


观察 Engine 的 fly() 方法,调用了外部类的成员属性 name,我们在主方法实例化 Sky 后,已经为属性 name 赋值。


运行结果:


大奔奔的发动机启动了!


相同的,除了成员属性,成员方法也可以自由访问。这里不再赘述。


还存在一个同名成员的问题:如果内部类中也存在一个同名成员,那么优先访问内部类的成员。可理解为就近原则。


这种情况下如果依然希望访问外部类的属性,可以使用外部类名.this.成员的方式,例如:


实例演示


// 外部类 Sky
public class Sky {
    String name;
    public Engine getEngine() {
        return new Engine();
    }
    // 汽车的跑动方法
    public void fly(String name) {
        System.out.println(name + "跑起来了!");
    }
    // 内部类 Engine
    private class Engine {
        private String name = "引擎";
        // 发动机的起动方法
        private void fly() {
            System.out.println("Engine中的成员属性name=" + name);
            System.out.println(Sky.this.name + "的发动机启动了!");
            Sky.this.fly(Sky.this.name);
        }
    }
    public static void main(String[] args) {
        // 实例化外部类
        Sky Sky = new Sky();
        // 为实例属性赋值
        Sky.name = "张三";
        // 获取内部类实例
        Engine engine = Sky.getEngine();
        // 调用内部类的方法
        engine.fly();
    }
}


运行结果:


Engine中的成员属性name=引擎
张三的发动机启动了!
大奔奔跑起来了!


请观察内部类 fly() 方法中的语句:第一行语句调用了内部类自己的属性 name,而第二行调用了外部类 Sky 的属性 name,第三行调用了外部类的方法 fly(),并将外部类的属性 name 作为方法的参数。



相关文章
|
15天前
|
Java
一篇文章讲明白Java中内部类详解—匿名内部类
一篇文章讲明白Java中内部类详解—匿名内部类
|
23天前
|
设计模式 Java 编译器
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
|
1月前
|
Java 编译器
24. 【Java教程】内部类
24. 【Java教程】内部类
16 2
|
21天前
|
Java
Java内部类相关内容总结和解读
Java内部类相关内容总结和解读
15 0
|
21天前
|
存储 Java
Java 五种内部类演示及底层原理详解
Java 五种内部类演示及底层原理详解
11 0
|
2月前
|
Java 程序员
Java的内部类与匿名类的技术性文章
Java的内部类与匿名类的技术性文章
23 1
|
2月前
|
Java
Java内部类(成员内部类、静态内部类、局部内部类、局部内部类)
Java内部类(成员内部类、静态内部类、局部内部类、局部内部类)
18 3
|
2月前
|
Java
一文搞懂内部类(Java)
Java内部类包括成员内部类、静态内部类、局部内部类和匿名内部类。成员内部类能访问外部类的所有成员,可以通过外部类实例创建。静态内部类与外部类实例无关,可直接访问外部类的静态成员。局部内部类仅限方法内使用,能访问最终变量。匿名内部类无名称,常用于一次性实现接口或抽象类,需外部类成员为final。
15 1
|
2月前
|
存储 Java API
【JAVA学习之路 | 提高篇】[内部类与常见API]String类
【JAVA学习之路 | 提高篇】[内部类与常见API]String类
|
1月前
|
Java 编译器 程序员
Java基础9-深入理解Java内部类及其实现原理
Java基础9-深入理解Java内部类及其实现原理
14 0