内部类的概念
一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是我们类的第五大成员【属性、方法、构造器、代码块、内部类】,内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系
内部类的分类
定义在外部类局部位置上(比如方法内):
- 局部内部类(有类名)
- 匿名内部类(没有类名,重点)
定义在外部类的成员位置上:
- 成员内部类(没用static修饰)
- 静态内部类(使用static修饰)
成员内部类
说明:成员内部类是定义在外部类的成员位置,并且没有static修饰。
- 可以直接访问外部类的所有成员,包含私有的
class Outer01{ //外部类
private int n1 = 10;
public String name =“张三";
class lnntero1{
public void sayoi
System.out.println("Outer01的n1= " +n1 + " outer01的name = " + name );
}
}
- 可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
- 作用域和外部类的其他成员一样,为整个类体(在外部类的成员方法中创建成员内部类对象,再调用方法)
- 成员内部类—访问---->外部类(比如:属性)
访问方式:直接访问 - 外部类—访问------>内部类
访问方式:创建对象,再访问 - 外部其他类—访问---->成员内部类
//其它外部类访问内部类
//方式1
Outer01 outer01 = new Outer01();
lnnter01 innter01 = outer01.new Innter01();
//方式2:
InnterO1 innter012 = new Outer01().new lhnter010;
//方式3:使用一个方法来获取,更加简洁(在外部类编写getlnnter01Instance()方法)
Innter01 innter01Instance = new OuterO1().getlnnter01Instance();
- 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
静态内部类
说明:静态内部类是定义在外部类的成员位置,并且有static修饰
-
可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
-
可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员
-
作用域:同其他的成员,为整个类体
-
静态内部类—访问---->外部类(比如:静态属性)
访问方式:直接访问所有静态成员 -
外部类—访问------>静态内部类
访问方式:创建对象,再访问 -
外部其他类—访问---->静态内部类
//外部其他类使用静态内部类
//方式1
//因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
Outer10.Inner10 inner10 = new Outer10.Inner10();
inner10.say();
//方式2
//编写一个方法,可以返回静态内部类的对象实例.
outer10.Inner10 inner101 = outer10.getInner10();
- 如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问
局部内部类
说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。
-
可以直接访问外部类的所有成员,包含私有的
-
不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
-
作用域:仅仅在定义它的方法或代码块中。
-
局部内部类—访问---->外部类的成员
[访问方式:直接访问] -
外部类—访问---->局部内部类的成员
访问方式:创建对象,再访问(注意:必须在作用域内)
记住:
(1)局部内部类定义在方法中/代码块
(2)作用域在方法体或者代码块中
(3)本质仍然是一个类
- 外部其他类—不能访问----->局部内部类(因为局部内部类地位是一个局部变量)
- 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
private int n1 = 10;
private void m2() { //私有方法
System.out.println("A的私有方法");
}
public void m1() {//方法
//1.局部内部类是定义在外部类的局部位置,通常在方法
//3.不能添加访问修饰符,但是可以使用final修饰
//4.作用域︰仅仅在定义它的方法或代码块中
final class Inner02 {//局部内部类(本质仍然是一个类)
//2.可以直接访问外部类的所有成员,包含私有的
public void f1() {
//5.局部内部类可以直接访问外部类的成员,比如下面外部类n1 和 m2()
System.out.println("n1=" + n1);
m2();
}
}
//6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
}
}
匿名内部类
(1)本质是类
(2)内部类
(3)该类没有名字
(4)同时还是一个对象
说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
- 匿名内部类的基本语法
new 类或接口(参数列表){
类体
};
基于接口
的匿名内部类
接口式的匿名内部类:创建的匿名类部类对象实现了 new 后面的接口
public class test3 {
public static void main(String[] args) {
I1 i1 = new I1() { //创建的匿名类部类实现了I1接口
@Override
public void run() {
System.out.println("跑....");
}
};
i1.run();
}
}
interface I1{
public void run();
}
基于类
的匿名类部类
继承式的匿名内部类:创建的匿名类部类对象 继承了 new 后面的类
public class test3 {
public static void main(String[] args) {
new C1(){ //创建的匿名类部类对象为C1的子类
@Override
public void eat() {
System.out.println("吃香蕉");
}
}.eat(); //也可直接调用方法
}
}
abstract class C1 {
public void eat() {
}
}
基于参数
的匿名类部类
参数式的匿名内部类:将 实现了接口/继承了类
的匿名类部类作为方法参数传递
public class test3 {
public static void main(String[] args) {
A(new Animal(){ //作为参数传递
@Override
public void run() {
System. out.println("小狗跑...");
}
});
}
public static void A(Animal Dog){
Dog.run () ;
}
}
interface Animal {
void run() ;
}
-
匿名内部类的语法比较奇特,请大家注意,因为匿名内部类既是一个类的定义同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。
-
可以直接访问外部类的所有成员,包含私有的
-
不能添加访问修饰符,因为它的地位就是一个局部变量
-
作用域:仅仅在定义它的方法或代码块中。
-
匿名内部类—访问---->外部类成员
[访问方式:直接访问] -
外部其他类—不能访问----->匿名内部类(因为匿名内部类地位是一个局部变量)
-
如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
匿名内部类例子
t1.A(t1
包下的A.java文件)
无参的构造方法是受保护的(只有同类、子类、同包)可以访问
public class A<T> {
protected A() {
System.out.println("A的protected A()被调用...");
}
}
t2.test(t2
包下的test.java文件)
如果直接创建 A 对象,是会报错的
但是写成匿名类部类就没问题
这个匿名类部类对象相当于继承了A对象(是A对象的子类),当我们写成new A(){};
,相当于调用了匿名类部类对象的无参构造方法-->
无参构造默认前面是有super()-->
因此又会去调用A的无参构造(protected类型 子类是可以访问的),因此可以创建成功
内部类的分类
内部类的概念
成员内部类
外部其他类访问
使用内部类,必须先创建外部类
当然也可以一步到位
重复属性名,先访问内部类属性
重复属性名,在内部类访问外部类重复名的属性
外部类名.this.属性名
内部类不能创建静态属性
但可以创建静态常量
静态内部类
局部内部类
但就这样执行是不会有任何结果的
想要使用局部内部类,就要在方法里,创建局部内部类对象,然后调用
访问局部变量
一点注意
匿名内部类
基于接口的匿名类部类
基于类的匿名类部类
基于抽象类的匿名构造器
匿名内部类使用细节