一、目录
- 内部类介绍
- 内部类分类
- 局部内部类
- 匿名内部类
- 成员内部类
- 静态内部类
一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是类的第五大成员(属性、方法、代码块、构造器、内部类)。内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类的包含关系。
基本语法:
class Outer{
class Inner{
...
}
...
}
三、内部类的分类
- 定义在外部类局部位置上(比如说方法或代码块内):
- 局部内部类(有类名)
- 匿名内部类(无类名)
- 定义在外部类的成员位置上:
- 成员内部类(没用static修饰)
- 静态内部类(使用static修饰)
局部内部类是定义在外部类的局部位置,比如方法或者代码块中,并且有类名。
- 可以直接访问外部类的所有成员,包含私有的。
- 局部内部类如果要用修饰符,只能使用final修饰。
- 作用域:仅仅在定义它的方法或代码块中。
- 局部内部类如果要访问外部类的成员,可直接访问。
- 外部类如果要访问局部内部类的成员,需要先创建对象再访问,而且必须在作用域内。
- 外部其他类不能访问局部内部类。
- 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用:外部类名.this.成员 的方式去访问。
匿名内部类是定义在外部类的局部位置,比如方法或代码块中,并且没有类名。
- 匿名内部类语法 new 类或接口(参数列表){类体};
匿名内部类的细节:
匿名内部类既是一个类,同时也是一个对象。因此可以用下面两种方式去调用匿名内部类的方法:
new A(){
public void cry(){
....
}
}.cry();
A a = new A(){
public void cry(){
....
}
};
a.cry();
六、成员内部类
成员内部类是定义在外部类的成员位置,并且没有static修饰。
- 成员内部类可以直接访问外部类的所有成员,包括私有。
- 可以添加任意的访问修饰符。
class Outer{
private n = 100;
class Innter{
public void say(){...}
}
}
- 作用域,和外部类的其他成员一样。
- 成员内部类访问外部类,可直接访问。
- 外部类访问成员内部类,需要先创建对象,再访问。
- 外部其他类访问成员内部类有两种方法。
package com.innerclass;
public class MemberInnerClass {
public static void main(String[] args) {
//1. 外部其他类调用成员内部类的第一种方法
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.eat();
}
}
class OuterClass{
private int n = 100;
public void say(){
System.out.println("Hello, Inner Class");
}
class InnerClass{
public void eat(){
System.out.println(n);
}
}
}
package com.innerclass;
public class MemberInnerClass {
public static void main(String[] args) {
//2. 外部其他类调用成员内部类的第二种方法
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.UseInnerClass();
innerClass.eat();
}
}
class OuterClass{
private int n = 100;
public void say(){
System.out.println("Hello, Inner Class");
}
class InnerClass{
public void eat(){
System.out.println(n);
}
}
public InnerClass UseInnerClass(){
return new InnerClass();
}
}
- 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用 外部类名.this.成员 去访问。
package com.innerclass;
public class MemberInnerClass {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.eat();
}
}
class OuterClass{
private int n = 100;
public void say(){
System.out.println("Hello, Inner Class");
}
class InnerClass{
private int n = 900;
public void eat(){
System.out.println(n);
System.out.println(OuterClass.this.n);
}
}
}
//900
//100
七、静态内部类
静态内部类是定义在外部类的成员位置,并且有static修饰。
- 可以直接访问外部类的所有静态成员,包括私有的,但不能直接访问非静态成员。
- 可以添加任意访问修饰符。
- 作用域和其他成员一样,整个类体。
- 静态内部类访问外部类的静态成员,可直接访问。
- 外部类访问静态内部类,需要先创建对象再访问。
- 外部其他类访问静态内部类有两种方法。
package com.innerclass;
public class StaticInnerClass {
public static void main(String[] args) {
//外部其他类访问静态内部类的第一种方式
//因为是静态内部类,所以可以通过外部类.静态内部类的方式创建对象
OuterClassA.InnerClassA innerClassA = new OuterClassA.InnerClassA();
innerClassA.say();
}
}
class OuterClassA{
private static int n = 100;
private String name = "Mike";
static class InnerClassA{
public void say(){
System.out.println(n);
}
}
}
package com.innerclass;
public class StaticInnerClass {
public static void main(String[] args) {
//外部其他类访问静态内部类的第二种方式
//调用一个返回静态内部类的方法,来获取这个静态内部类的对象
OuterClassA outclassa = new OuterClassA();
OuterClassA.InnerClassA innerClass = outclassa.getInnerClass();
innerClass.say();
}
}
class OuterClassA{
private static int n = 100;
private String name = "Mike";
static class InnerClassA{
public void say(){
System.out.println(n);
}
}
public InnerClassA getInnerClass(){
return new InnerClassA();
}
}
如果我们创建的这个getInnerClass()方法是一个静态方法的话,那么就产生了第三种调用静态内部类的方法,也就是通过类名直接访问这个访问,直接跳过了创建对象。
package com.innerclass;
public class StaticInnerClass {
public static void main(String[] args) {
//外部其他类访问静态内部类的第三种方式
OuterClassA.InnerClassA innerClass = OuterClassA.getInnerClass();
innerClass.say();
}
}
class OuterClassA{
private static int n = 100;
private String name = "Mike";
static class InnerClassA{
public void say(){
System.out.println(n);
}
}
public static InnerClassA getInnerClass(){
return new InnerClassA();
}
}
- 如果外部类和静态内部类的成员重名时,静态内部类访问的时候,默认遵循就近原则,如果想访问外部类的成员,则可以使用 外部类名.成员 去访问。