内部类总共有 4 种(静态内部类、非静态内部类、局部内部类、匿名内部类)
作用:
一:内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
二:内部类可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问,但是外部类不能访问内部类的实现细节,例如内部类的成员变量。
三:匿名内部类适合用于创建那些只需要创建一次使用的类。
四:内部类比外部类可以多使用三个修饰符:private、protected、static
五:非静态内部类不能拥有静态成员。
1.非静态内部类:
非静态内部类定义在外部类里面
public class Demo {private String name;private Integer age;//定义构造器重载public Demo(){}public Demo(String name, Integer age) {this.name = name;this.age = age;}//定义一个非静态内部类private class InnerDemo {//非静态内部类private double length;private String color;public InnerDemo(){}public InnerDemo(double length, String color) {this.length = length;this.color = color;}// 此处省略 length 的getter 和 setter 方法.....................//非静态内部类实例方法public void info() {System.out.print("名字是:" + name + ": " + "年龄是: " + age +"肤色是: " + color + "身高是: " + length);}}public void test() {var innerDemo = new InnerDemo(180, "黄");innerDemo.info();}public static void main(String[] args) {Demo demo = new Demo("李白", 30);demo.test();}}
当非静态成员内部类的方法访问某个变量的时候,系统优先在该方法内查找是否存在该名字的局部变量,如果存在就使用该变量;如果不存在则查找该方法所在的内部类中是否存在该名字的成员变量, 如果不存在,则到外部类中查找是否存在该名字的成员变量,如果依然不存在,则会报编译错误:提示找不到该变量。
因此,如果外部类成员变量、内部类成员变量与内部类里面的方法同名,则可以通过使用 this、外部类类名.this 作为限定区分。
可以参考如下模板:
public class Demo {private String name = "外部类的成员变量";private class InClass {private String name = "内部类的成员变量";public void info(){var name = "局部变量";System.out.print("外部类的实例变量值:" + Demo.this.name);//通过 this.varName 访问内部类的成员变量System.out.print("内部类的成员变量:" + this.name);//直接访问局部变量System.out.print("局部变量的值:" + name);}}public void test() {var inClass = new InClass();inClass.info();}public static void main(String[] args) {Demo demo = new Demo();demo.test();}}
2. 静态内部类
使用 static 修饰的内部类被称为静态内部类,它属于外部类本身,不属于外部类某个实例对象。
静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。
public class Demo {private String name = "李白";private static int age = 2;static class StaticInnerClass {//静态内部类可以包含静态成员private static String womanName = "李清照";public void info() {//下面代码出现错误,静态内部类不能访问外部类的实例变量System.out.print(name);//下面代码正常System.out.print(age);}}}
静态内部类是外部类的一个成员,因此外部类的所有方法、所有初始化块中可以使用静态内部类来定义变量、创建对象等
public class Demo {static class StaticInnerClass {private static int age = 10;private String name = "李白";}public void info() {//System.out.print(age)//上面代码出现错误,应改为如下格式//通过类名访问静态内部类的类成员System.out.print(StaticInnerClass.age);//System.out.print(name);//上面代码出现错误,应改为如下格式//通过实例访问静态内部类的实例成员System.out.print(new StaticInnerClass().name);}}
Java 还允许在接口里定义内部类,接口里定义的内部类默认使用 public static 修饰,也就是说接口内部类只能是静态内部类。