Java内部类(成员内部类、静态内部类、局部内部类、局部内部类)

简介: Java内部类(成员内部类、静态内部类、局部内部类、局部内部类)

前言: 什么是内部类?

类的五大成员:

属性、方法、构造方法、代码块、内部类

在一个类里面,再定义一个类就是内部类。

  • 内部类表示的事物是外部类的一部分
  • 内部类单独出现没有任何意义
  • 内部类的访问特点:
  • 内部类可以直接访问外部类的成员,包括私有
  • 外部类要访问内部类的成员,必须创建对象
public class Car {
    private String carName;
    private int carAge;
    private String carColor;
    public void show() {
        System.out.println(carName);
        System.out.println(engineName); // 报错
        //创建内部类对象
        Engine engine = new Engine();
        System.out.println(engine.engineName);
    }
    class Engine {
        String engineName;
        int engineAge;
        public void show() {
            System.out.println(engineName);
            System.out.println(carName);
        }
    }
}

一、成员内部类

1.1 成员内部类的代码如何书写

  • 写在成员位置的,属于外部类的成员。
  • 成员内部类可以被一些修饰符所修饰,比如:private,默认,protected,public,static等
  • 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。
public class Car {
    private String carName;
    private int carAge;
    private String carColor;
    public void show() {
      System.out.println("外部类方法");
    }
    private class Engine {  //成员内部类,可添加修饰符
        String engineName;
        int engineAge;
        public void show() {
            System.out.println("内部类方法");
        }
    }
}

1.2 如何创建成员内部类的对象

  • 方式一:
  • 在外部类中编写方法,对外提供内部类的对象。
public class Outer {
    String name;
    class Inner {
    }
    public Inner getInstance() {
        return new Inner();
    }
}
public class Test {
    public static void main(String[] args) {
        System.out.println(new Outer().getInstance());
    }
}
  • 方式二:
  • 直接创建格式:外部类名.内部类名对象名=外部类对象.内部类对象;
public class Outer {
    String name;
    class Inner {
        
    }
}
public class Test {
    public static void main(String[] args) {
        Outer.Inner oi = new Outer().new Inner();
    }
}

1.3 成员内部类如何获取外部类的成员变量

public class Outer {
    private int a = 10;
    
    class Inner {
        private int a = 20;
        public void show() {
            int a = 30;
            System.out.println(a); // 30
            System.out.println(this.a); // 20
            System.out.println(Outer.this.a); // 10
        }
    }
}
public class Test {
    public static void main(String[] args) {
        //创建内部类对象,并调用show方法
        Outer.Inner oi = new Outer().new Inner();
        oi.show();
    }
}

代码分析:

在执行代码时,首先调用main方法,此时在栈内存中添加main方法,并记录Outer.Inner oi的地址,

方法区中有Test.class的字节码文件,以及其中的main方法、Outer.class和Inner.class的字节码文件以及他们各自的所有成员变量和成员方法

堆内存中分别记录了外部类对象和内部类对象

注意:在内部类对象中还隐含了外部类对象的地址。


二、静态内部类

  • 静态内部类也是成员内部类中的一种
  • 静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象
  • 创建静态内部类对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
  • 调用非静态方法的格式:先创建对象,用对象调用
  • 调用静态方法的格式:外部类名内部类名.方法名();
public class Outer {
    int a = 10;
    static int b = 20;
    static class Inner {
        public void method1 () {
            //报错
            //System.out.println(a);
        }
        public void method2() {
            System.out.println(b);
        }
    }
}
public class Outer {
    int a = 10;
    static int b = 20;
    static class Inner {
        public void method1 () {
            System.out.println("非静态方法被调用了");
        }
        public static void method2() {
            System.out.println("静态方法被调用了");
            System.out.println(b);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Outer.Inner oi = new Outer.Inner();
        oi.method1();
        Outer.Inner.method2();
    }
}

三、局部内部类

  • 1.将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。
  • 2.外界是无法直接使用,需要在方法内部创建对象并使用。
  • 3.该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
public class Outer {
    public void show() {
        final int a = 10;
        //局部内部类
        class Inner {
            String name;
            int age;
            
            public void method1() {
                System.out.println("局部内部类中的method1方法");
            }
            public void method2() {
                System.out.println("局部内部类中的method2方法");
            }
        }
        //创建局部内部类对象
        Inner i = new Inner();
        System.out.println(i.name);
        System.out.println(i.age);
        i.method1();
        i.method2();
    }
}

四、 匿名内部类

  • 1.继承/实现关系
  • 2.方法的重写
  • 3.创建对象

接口

public interface Swim {
    public void swim();
}

抽象类

public abstract class Animal {
    public abstract void cat();
}

匿名内部类创建

public class Test {
    public static void main(String[] args) {
        new Swim() {
            @Override
            public void swim() {
                System.out.println("实现了Swim中的方法");
            }
        };
        new Animal() {
            @Override
            public void cat() {
                System.out.println("继承Animal后实现cat方法");
            }
        };
    }
}


相关文章
|
1天前
|
设计模式 Java 编译器
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
|
19天前
|
Java 编译器
24. 【Java教程】内部类
24. 【Java教程】内部类
14 2
|
22天前
|
Java 程序员
Java的内部类与匿名类的技术性文章
Java的内部类与匿名类的技术性文章
16 1
|
10天前
|
Java 编译器 程序员
Java基础9-深入理解Java内部类及其实现原理
Java基础9-深入理解Java内部类及其实现原理
12 0
|
16天前
|
Java
【Java基础】 内部类 (成员内部类、局部内部类、静态内部类、匿名内部类)
Java内部类 (成员内部类、局部内部类、静态内部类、匿名内部类)
10 0
|
2天前
|
安全 Java
JAVA多线程通信新解:wait()、notify()、notifyAll()的实用技巧
【6月更文挑战第20天】Java多线程中,`wait()`, `notify()`和`notifyAll()`用于线程通信。在生产者-消费者模型示例中,它们确保线程同步。`synchronized`保证安全,`wait()`在循环内防止虚假唤醒,`notifyAll()`避免唤醒单一线程问题。关键技巧包括:循环内调用`wait()`,优先使用`notifyAll()`以保证可靠性,以及确保线程安全和正确处理`InterruptedException`。
|
2天前
|
安全 Java
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
【6月更文挑战第20天】JAVA多线程中,wait(), notify(), notifyAll()是Object类的关键同步机制。wait()让线程等待并释放锁,直到被notify()或notifyAll()唤醒或超时。它们必须在同步块中使用,持有锁的线程调用。notify()唤醒一个等待线程,notifyAll()唤醒所有。最佳实践包括:与synchronized结合,循环检查条件,避免循环内notify(),通常优先使用notifyAll()。
|
2天前
|
Java 程序员
从菜鸟到大神:JAVA多线程通信的wait()、notify()、notifyAll()之旅
【6月更文挑战第21天】Java多线程核心在于wait(), notify(), notifyAll(),它们用于线程间通信与同步,确保数据一致性。wait()让线程释放锁并等待,notify()唤醒一个等待线程,notifyAll()唤醒所有线程。这些方法在解决生产者-消费者问题等场景中扮演关键角色,是程序员从新手到专家进阶的必经之路。通过学习和实践,每个程序员都能在多线程编程的挑战中成长。
|
1天前
|
安全 Java 程序员
Java多线程详解
Java多线程详解
|
1天前
|
缓存 安全 Java
Java线程面试题含答案
Java线程面试题含答案