Java基础-内部类
成员内部类
定义:最常见的内部类,位于另一个类内部,以成员方式存在
特点:
1.Inner类可以使用任意访问修饰符,如public,private,protected等
2.定义成员内部类之后,必须使用外部类对象来创建内部类对象,而不能直接去new一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类()
3.内部类定义的方法可以访问外部类中的数据,不受访问控制符影响
4.如果外部类和内部类具有相同的成员变量或方法,内部类可以直接访问内部类的成员变量或方法,但如果内部类访问外部类的成员变量或者方法时,需要使用this关键字
public class Outer {
public int age = 1;
public Outer() {
System.out.println("Outer");
}
//成员内部类
public class Inner {
public int age = 2;
public Inner() {
int age = 3;
System.out.println(age);//输出:3
System.out.println(this.age);//输出:2
System.out.println(Outer.this.age);//输出:1
System.out.println("Inner");
}
}
public static void main(String[] args) {
Outer outer = new Outer();
//创建内部类的两种方式
Inner inner = outer.new Inner();
Inner in = new Outer().new Inner();
}
}
静态内部类
定义:static是不能用来修饰类的,但是成员内部类可以看做外部类中的一个成员,所以可以用static修饰,这种用static修饰的内部类我们称作静态内部类,也称作嵌套内部类.
特点:
1.静态内部类不能直接访问外部类的非静态成员,但可以通过new 外部类().成员的方式访问;
2.如果外部类的静态成员与内部类的静态成员相同, 可以通过"类名.静态成员"来访问外部类的静态成员;如果不同,可以直接调用外部类的静态成员名
3.创建静态内部类的对象时,不需要外部类的对象,可以直接创建(非静态内部类编译后会默认的保存一个指向外部类的引用,而静态类却没有)
public class OuterTwo {
public int age = 1;
public static int age2 = 20;
public OuterTwo() {
System.out.println("Outer");
}
public static class Inner {
public Inner() {
System.out.println("Inner");
}
public void method() {
System.out.println(new OuterTwo().age);//1
//System.out.println(age);//报错
System.out.println(age2);//20
}
}
public static void main(String[] args) {
OuterTwo.Inner inner = new OuterTwo.Inner();
inner.method();
}
}
方法内部类(局部内部类)
定义:局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
特点:
1.主要是作用域发生了变化,只能在自身所在方法和属性中被使用
2.不能使用访问修饰符
为什么使用final修饰内部类访问的变量?
1.new 出来的对象存储在堆内存中
2.局部变量跟着方法存储在栈内存中
3.方法运行结束后,立即出栈,局部变量就会立即消失
4.但new出来的对象会在堆内存中持续保存,直至垃圾回收消失
5.final修饰的变量叫常量,常量存在常量池中
总之,内部类创建的对象的生命周期会超过局部变量,这就会出现内部类的对象要访问局部变量时访问失败,这个时候,内部类要访问局部变量需要局部变量保存不变
public class OuterThree {
public int age = 1;
public OuterThree() {
System.out.println("Outer");
}
public void method() {
final int age2 = 30;
class Inner {
public void show() {
System.out.println(age);
//从内部类中访问方法内变量age2,需要将变量声明为最终类型。
System.out.println(age2);
}
}
new Inner().show();
}
public static void main(String[] args) {
OuterThree outerThree = new OuterThree();
outerThree.method();
}
}
结果 Outer 1 30
匿名内部类
定义:一个没有名字的类,是内部类的简化写法。本质是,继承该类或者实现接口的子类匿名对象
特点:
1.匿名内部类不能是抽象类,必须实现接口或抽象父类的所有抽象方法
2.匿名内部类不能含有static的变量和方法
//接口
public interface Inner {
public String show();
}
//抽象类
public abstract class Inner1 implements Inner {}
//普通类
public class Inner2 implements Inner {
@Override
public String show() {
return "this is Inner2";
}
}
public static void main(String[] args) {
Outer outer = new Outer();
// 测试1,Inner为接口
outer.method1(new Inner() {
String s1 = "this is s1 in Inner";
public String say() {
// 外部类和匿名函数类中有同名变量s1
return s1;
}
});
// 测试2,Inner1为抽象类
outer.method1(new Inner1() {
String s2 = "this is s2 in Inner1";
public String say() {
// 外部类和匿名函数类中有同名变量s2
return Outer.s2;
}
});
// 测试3,Inner2为普通类
outer.method1(new Inner2() {
public String say() {
// 访问外部类私有变量s3
return s3;
}
});
// 测试4,Inner2为普通类
outer.method1(new Inner2() {
public String say() {
// 访问外部类私有方法method1()
return method2();
}
});
}
}
打印
this is s1 in Inner
this is s2 in Outer
this is s3 in Outer
this is method2 in Outer
理解内部类
1.为什么成员内部类可以无条件访问外部类的成员?
编译器在进行编译的时候,会将成员内部类单独编译成一个字节码文件
编译器会默认为成员内部类添加了一个指向外部类对象的引用
内部类的使用场景和好处?
1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。
2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
3.方便编写事件驱动程序。
4.方便编写线程代码。