Java 内部类
内部类介绍

- 内部类可以使用 public、private、protected、default、static 修饰符修饰,而外部顶级类只能使用 public、default 修饰符修饰
- 内部类只是一个编译时的概念,编译成功后,就会成为两个不同的类,内部类会成为外部类的成员,并且会生成一个外部类对象,通过外部类对象调用内部类对象
- 对于一个名为 Outer 的外部类和其内部定义的内部类 Inner,编译后,会生成两个类,一个是 Outter.class,一个是 Outter$Inner.class
内部类的作用
- 内部类通过了更好的封装,只能让外部类直接访问,不允许同一个包中的其他其他类直接访问
- 内部类可以直接访问外部类的私有属性,内部了被当成其外部类的成员,但外部了不能访问内部类的属性和方法
非静态内部类
- 非静态内部类必须寄存在一个外部类中,并且内部类不能声明为 static
- 因此,如果有一个非静态内部类对象,那么一定存在对应的外部类对象,非静态内部类对象单独属于外部类对象,并且只能通过外部类对象访问
- 非静态内部类可以直接访问外部类的成员,但外部类不能直接访问非静态内部类的成员
- 非静态内部类不能有静态成员变量、静态方法和静态代码块
- 内部类访问成员变量要点:
- 访问外部类成员变量:外部类.this.成员变量名
- 访问外部类成员方法:外部类.this.成员方法名()
- 访问内部类成员变量:this.成员变量名
- 例:
/**
* 内部类测试
* @author The Mutens
*
*/
//外部类
public class Outter {
private int value=100;
public void show(){
Inner inner2=new Inner(); //在外部类方法中创建内部类对象
System.out.println("我是外部类的方法!");
inner2.showInner();
}
public class Inner{
private String str1="内部类属性";
private int value=20;
public void showInner(){
System.out.println("我是内部类方法!");
System.out.println(str1);
System.out.println(value);
System.out.println(Outter.this.value);//通过Outter.this.value调用与内部类同名的外部类属性
//show(); //内部类可以直接调用外部类的成员属性和成员方法
}
}
public static void main(String args[]){
Outter.Inner inner1=new Outter().new Inner();//第一种创建内部类对象的方式
inner1.showInner();
Outter outter1=new Outter();
Outter.Inner inner3=outter1.new Inner(); //第二种创建内部类的方式
outter1.show();
inner3.showInner();
}
}
静态内部类
- 静态内部类必须声明为 static
- 静态内部类不能访问外部类的非静态成员变量和方法,可以访问外部类的静态成员变量和方法
- 静态内部类可以看做外部类的一个静态成员
- 例:
/**
*测试静态内部类
* @author TheMutents
*
*/
public class Outter_1 {//外部类
private int value1=100;
private static int value2=200;
static String str="外部类字符串";
static void outter(){
System.out.println(new Outter_1().value1);
}
static class Inner1{//静态内部类
private int value=300;
public void test(){
//System.out.println(value);静态内部类不能访问外部类的非静态成员
outter();
System.out.println(value2);
System.out.println(str);//静态内部类可以直接调用外部类的静态成员
}
public static void test1(){
System.out.println(new Inner1().value);
}
}
public static void main(String args[]){
new Outter_1.Inner1().test();//创建静态内部类对象调用静态内部类实例方法
Outter_1.Inner1.test1();//用类名来调用静态内部类的静态方法
}
}
匿名内部类
- 匿名内部类只能使用一次,不能重复使用
- 适合场景:键盘监听操作等, 在安卓开发中、awt、swing 开发中常见
- 例:
/**
* 测试匿名内部类
* @author TheMutents
*
*/
public class AnonymousClass {
public void test(A11 a){
a.run();
}
public static void main(String args[]){
new AnonymousClass().test(new B11());//1.创建B11类的对象作为test()方法的实参
new AnonymousClass().test(new A11(){//匿名内部类,一次性使用
@Override
public void run() {
System.out.println("匿名内部类实现接口A的run()方法");
}});
}
}
//接口A11
interface A11{
void run();
}
//实现接口A11的类,可以反复使用
class B11 implements A11{
@Override
public void run() {
System.out.println("普通类实现接口A的run()方法");
}
} - 注意:
- 匿名内部类没有访问修饰符
- 匿名内部类没有名字,因此没有构造函数
局部内部类
- 定义在方法中,作用域只限于方法内,称为局部内部类
- 局部内部类的使用主要是用来解决比较复杂的问题
- 比如:想创建一个类来辅助我们解决问题,但是这个类只在方法中用到,因此我们希望这个类只在方法中创建,而不是在类中创建
- 局部内部类和成员一样被编译,只是它的作用域发生了改变,只能在方法内部使用
- 局部内部类在实际开发中应用很少
- 例:
/**
* 测试局部内部类
* @author TheMutents
*
*/
public class LocalInnerClass {
public void test(){
class LocalInnerClass_1{//局部内部类作用域限于方法内部
public void show(){
System.out.println("局部内部类");
}
}
new LocalInnerClass_1().show();
}
public static void main(String args[]){
new LocalInnerClass().test();//调用test()方法
}
}