内部类
- 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。
- 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
成员内部类
- 成员内部类是最普通的内部类,它的定义为位于另一个类的内部,类似于外部类的成员,所以叫成员内部类
- 成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
- 不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
- 成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,必须要创建外部类的对象
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner();
- 内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。
- 成员内部类demo
public class OuterClass1 {
private String name = "OuterClass1:name";
private String age = "OuterClass1:age";
private String sex = "OuterClass1:sex";
private InnerClass1 innerClass1;
public InnerClass1 getInnerClass1() {
/*return this.new InnerClass1();*/
return new InnerClass1();
}
class InnerClass1 {
String name = "InnerClass1:name";
void show() {
//访问内部类的name
System.out.println(name);
//访问外部类的age
System.out.println(age);
//访问外部类的sex
System.out.println(sex);
//访问外部类的name
System.out.println(OuterClass1.this.name);
}
}
public void show() {
InnerClass1 innerClass11 = getInnerClass1();
String name1 = innerClass11.name;
System.out.println(name1);
}
}
@Test
public void test01(){
OuterClass1 outerClass1 = new OuterClass1();
OuterClass1.InnerClass1 innerClass1 = outerClass1.new InnerClass1();
innerClass1.show();
}
@Test
public void test02(){
OuterClass1 outerClass1 = new OuterClass1();
outerClass1.show();
}
局部内部类
局部内部类是定义在外部类的局部位置,且一定要有类名
- 可以直接访问外部类的所有成员,包括私有的
- 局部内部类的地位相当于一个局部变量,因此不能添加访问修饰符
- 作用域:仅仅在定义它的方法或代码块中有效
- 局部内部类访问外部类的成员:直接访问即可
- 外部类 访问 局部内部类的成员 : 创建对象 -> 通过对象进行访问,注意 : 需要在局部内部类的作用域中才可以
- 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果就是想访问外部类的成员时,使用 【外部类名.this.成员】 的方式
- 局部内部类demo
public class OuterClass2 {
private String name = "OuterClass2:name";
private String age = "OuterClass2:age";
private String sex = "OuterClass2:sex";
public void show() {
String name = "OuterClass2:show:name"; //如果变量名称在局部内部类中存在,在成员变量中存在,在作用域也存在,无法访问作用域中的变量
String name1 = "OuterClass2:show:name1";
class InnerClass2 {
String name = "InnerClass2:name";
void show() {
System.out.println(name);
System.out.println(age);
System.out.println(sex);
System.out.println(name1);
System.out.println(OuterClass2.this.name);
}
}
InnerClass2 innerClass2 = new InnerClass2();
innerClass2.show();
}
}
@Test
public void show() {
OuterClass2 outerClass2 = new OuterClass2();
outerClass2.show();
}
静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
public class OuterClass3 {
private String memberField1 = "OuterClass3:memberField1";
private String memberField2 = "OuterClass3:memberField2";
private String memberField3 = "OuterClass3:memberField3";
private static String staticField1 = "OuterClass3:staticField1";
private static String staticField2 = "OuterClass3:staticField2";
private static String staticField3 = "OuterClass3:staticField3";
static class InnerClass3 {
private String memberField1 = "InnerClass3:memberField1";
private String memberField2 = "InnerClass3:memberField2";
private static String staticField1 = "InnerClass3:staticField1";
private static String staticField2 = "InnerClass3:staticField2";
public void show(){
System.out.println(memberField1);
System.out.println(memberField2);
// System.out.println(memberField3); //无法访问
System.out.println(staticField1);
System.out.println(staticField2);
System.out.println(OuterClass3.staticField2);
System.out.println(staticField3);
}
}
}
@Test
public void test01(){
OuterClass3.InnerClass3 innerClass3 = new OuterClass3.InnerClass3();
innerClass3.show();
}
匿名内部类
- 匿名内部类,就是没有名字的一种嵌套类。它是Java对类的定义方式之一。
- 在实际开发中,我们常常遇到这样的情况:一个接口/类的方法的某个实现方式在程序中只会执行一次,但为了使用它,我们需要创建它的实现类/子类去实现/重写。此时可以使用匿名内部类的方式,可以无需创建新的类,减少代码冗余。
- 匿名内部类demo
public class OuterClass4 {
private String memberField1 = "OuterClass3:memberField1";
private String memberField2 = "OuterClass3:memberField2";
private String memberField3 = "OuterClass3:memberField3";
public void show(){
String memberField3 = "OuterClass3:show:memberField1";
// 匿名内部类
new InnerClass4() {
@Override
public void show() {
String memberField1 = "memberField1";
System.out.println(memberField1);
System.out.println(memberField3);
System.out.println(OuterClass4.this.memberField2);
}
};
}
}
interface InnerClass4 {
void show();
}