欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > Java的内部类

Java的内部类

2026/5/26 18:22:54 来源:https://blog.csdn.net/2302_81034736/article/details/143493332  浏览:    关键词:Java的内部类

Java内部类

什么是内部类?

  • 类的五大成员:属性、方法、构造方法、代码块、内部类
  • 在一个类的里面,再定义一个类
public class Outer { // 外部类class Inner { // 内部类}
}
public class Test { // 外部其他类public static void main(String[] args) {}
}
  • 内部类表示的事物是外部类的一部分

  • 内部类单独出现没有任何意义

内部类的访问特点:

  1. 内部类可以直接访问外部类的成员,包括私有
  2. 外部类要访问内部类的成员,必须创建对象

内部类的分类

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

1、成员内部类

  • 写在成员位置的,属于外部类的成员
  • 成员内部类可以被一些修饰符所修饰,比如:private,默认,protectedpublicstatic
  • 在成员内部的类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量
1.1获取成员内部类对象的两种方法:
  1. 在外部类的编写方法,对外提供内部类的对象
  2. 直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;

示例

public class Outer { // 外部类String name;int a;class Inner { // 内部类int a = 10;}private class Iner { // (私密)内部类int a = 10;public void sj() {System.out.println("我是私密的内部类");}}public Iner getIner() { // 获取私密内部类的方法return new Iner();}public void getmessageIner() { // 获取私密内部类中内容的方法Iner in = getIner();System.out.println(in.a); // 输出: 10in.sj(); // 输出: 我是私密的内部类}
}
package com.inner.a01innerclassdemo01;public class Test { // 测试类public static void main(String[] args) {// 默认访问修饰符  直接创建内部类Outer.Inner oi = new Outer().new Inner();System.out.println(oi.a); // 输出: 10// 如果加上私有的private修饰符// 要么改变访问修饰符,要么在外部类编写方法,对外提供内部类对象Outer o = new Outer();Object iner = o.getIner();// 但也只能通过它的父类Object获取它(多态),但并不能使用它(因为父类是Object)// 如果要想使用它内部的成员变量和方法,只能在外部类中创建公共方法o.getmessageIner();}
}
1.2当外部类变量重名时:

外部类成员变量和内部类成员变量重名时,使用外部类名.this.变量名

public class Outer {private int a = 10;class Inner {private int a = 20;public void show() {int a = 30;System.out.println(Outer.this.a); // 输出: 10System.out.println(this.a); // 输出: 20System.out.println(a); // 输出: 30}}
}
1.3成员内部类的内存图:

在这里插入图片描述

  1. 测试类的字节码文件加载到内存,虚拟机会自动调用main方法,main方法会加载进栈
  2. 第一行代码,发现用到了OuterInner,所以就会把外部类和内部类的字节码文件加载到方法区(两个独立的字节码文件)。等号左边,在栈区开辟一个空间用来记录Inner对象的地址值;等号右边,分为两个部分,第一部分new Outer()会在堆区开辟一个新空间存放外部类对象,第二部分new Inner()会在堆区再次开辟一个空间存放内部类对象,同时Java还会给内部类的对象,去加一个隐藏的成员变量this——用在记录外部类成员对象的地址值,并将内部类对象的地址值返回给栈区的oi变量
  3. 第二行代码,调用oishow方法,此时show方法会被加载建栈,此时的调用者的地址值是002,第一条输出语句,就近原则;第二条输出语句,打印调用者里面的变量;第三条输出语句,有Outer前缀,会先从内部类对象中找到外部类对象的地址001,在打印外部类里面的变量

2、静态内部类

​ 静态内部类是一种特殊的成员内部类

​ 静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。

public class Outer { // 外部类static class Inner { // 静态内部类}
}
2.1创建静态内部类的格式:
  • 外部类名.内部类名 对象名 = new 外部类名.内部类名();
  • 调用非静态方法的格式:先创建对象,用对象调用
  • 调用静态方法的格式:外部类名.内部类名.方法名();

示例

public class Outer { // 外部类// 静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象int a = 10;static int b = 20;// 静态内部类static class Inner {public void show01() {// 会报错
//            System.out.println(a);// 若想要访问外部类中的对象 则需要创建对象Outer o = new Outer();System.out.println(o.a);	// 输出: 10System.out.println(b);		// 输出: 20System.out.println("非静态的方法被调用了");}public static void show02() {// 报错
//            System.out.println(a);Outer o = new Outer();System.out.println(o.a);	// 输出: 10System.out.println(b);		// 输出: 20System.out.println("静态的方法被调用了");}}
}
public class Test {public static void main(String[] args) {// 创建静态内部类的对象// 只要是静态的东西,都可以用类名.直接调用Outer.Inner oi = new Outer.Inner();oi.show01();// 若想要调用静态方法oi.show02();// 这种方法可以,但不提倡// 可以通过类名直接调用静态方法Outer.Inner.show02();}
}

3、局部内部类

  1. 将内部类的定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。(不能使用四大权限修饰符,可以使用final等)
  2. 外界是无法直接使用,需要在方法内部创建对象并使用。
  3. 该类可以直接访问外部类的成员,也可以访问方法内的局部变量。

示例

public class Outer { // 外部类int a = 10;public void show() {int b = 20;// 局部内部类class Inner {String name;// 该类可以直接访问外部类的成员int age = a;public void method01() {System.out.println(a);  // 输出: 10System.out.println(b);  // 输出: 20System.out.println("局部内部类中的method01方法");}public static void method02() {System.out.println("局部内部类中的method02方法");}}// 要想访问,必须在方法内部创建对象并使用Inner i = new Inner();System.out.println(i.name); // 输出: nullSystem.out.println(i.age);  // 输出: 10i.method01();Inner.method02();}
}
public class Test { // 测试类public static void main(String[] args) {Outer o = new Outer();o.show();}
}

4、匿名内部类

  • 匿名内部类的本质上就是隐藏了名字的内部类。(只是自己没写名字,编译java会自己生成相应的class文件——Test$1.class数字依次累加)

  • 隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置。

4.1使用场景:
  • 当方法的参数是接口或者类时,以接口为例,可以传递这个接口的实现类对象,如果实现类对象只要使用一次,就可以用匿名内部类简化代码
4.2匿名内部类的格式:
new 类名或者接口名() {重写方法;
};
4.3格式的细节:
  • 包含了继承或实现,方法重写,创建对象。整体就是一个类的子类对象或者接口的实现对象

示例

public interface Swim { // Swim接口public abstract void swim();
}
public abstract class Animal { // Animal抽象类public abstract void show();
}
public class Test { // 测试类public static void main(String[] args) {use(new Swim() {@Overridepublic void swim() {System.out.println("打印重写的游泳接口");}});use(new Animal() {@Overridepublic void show() {System.out.println("打印重写的动物类");}});// 也可以直接使用new Animal() {@Overridepublic void show() {System.out.println("重写了动物这个类中的方法");}}.show(); // 重写了动物这个类中的方法Swim s = new Swim() {@Overridepublic void swim() {System.out.println("重写了游泳的接口");}};s.swim(); // 重写了游泳的接口}// 使用匿名内部类public static void use(Swim s) {// 相当于Swim s = new Swim(){};s.swim(); // 打印重写的游泳接口}public static void use(Animal a) {// 相当于Animal a = new Animal(){};a.show(); // 打印重写的动物类}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com