前言:
将一个类定义在另一个类里面或者一个方法中,该类称之为内部类
一、作用:
- 提供更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类,如A类只能在B类中使用。
- 内部类成员可以直接访问外部类的私有数据,但是外部类不能访问内部类的实现细节,比如内部类的成员变量。
- 匿名内部类适用于创建那些仅需要一次使用的类。
二、四种修饰符的访问权限:
权限 | 类内 | 同包 | 不同包子类 | 不同包非子类 |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
内部类和外部类的访问权限就不一样,内部类的可以多用三个修饰符private,protected,static。
解释: 外部类的上一级是包,只有两个作用域:同一个包和任何位置。故对应的省略访问控制,public访问控制,内部类上一级是外部类,那么就具有4个作用域。
三、关系图:
四、非静态内部类:
- 内部类中不能拥有任何static的变量和方法。
- 其创建依赖于外部类,故只有先创建了外部类才能创建内部类。
- 非静态内部类的成员可以访问外部类的private成员,但反过来就不成立了。
- 外部类不能直接访问非静态内部类的实例变量,如果访问,则必须显示创建内部类对象。
- 其内部的方法中访问某个变量,顺序是方法的局部变量,内部类的成员变量,外部类的成员变量。调用方法是this、外部类名.this来依次调用
一般的,使用getxxx方法来获取非静态内部类,尤其是其内部类的构造函数无参时。
public class OuterClass {
private String str;
public void outerDisplay(){
System.out.println("outerClass...");
}
public class InnerClass{
public void innerDisplay(){
//使用外围类的属性
str = "chenssy...";
System.out.println(str);
//使用外围类的方法
outerDisplay();
}
}
/*推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 */
public InnerClass getInnerClass(){
return new InnerClass();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.getInnerClass();
inner.innerDisplay();
}
}
--------------------
chenssy...
outerClass...
五、静态内部类:
- 它的创建是不需要依赖外部类的。
- 它不能使用任何外部类的非static成员变量和方法。
- 属于外部类本身,而不是属于外部类的某个对象。
- 无法访问外部类的实例变量,只能访问外部类的类成员
- 内部的实例方法也不能访问外部类的实例属性
- 外部类不能直接访问其成员,要通过其类名来访问
public class OuterClass {
private String sex;
public static String name = "chenssy";
static class InnerClass1{
/* 在静态内部类中可以存在静态成员 */
public static String _name1 = "chenssy_static";
public void display(){
/*
* 静态内部类只能访问外围类的静态成员变量和方法
* 不能访问外围类的非静态成员变量和方法
*/
System.out.println("OutClass name :" + name);
}
}
class InnerClass2{
/* 非静态内部类中不能存在静态成员 */
public String _name2 = "chenssy_inner";
/* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */
public void display(){
System.out.println("OuterClass name:" + name);
}
}
//实例方法
public void display(){
/* 外围类访问静态内部类:内部类. */
System.out.println(InnerClass1._name1);
/* 静态内部类 可以直接创建实例不需要依赖于外围类 */
new InnerClass1().display();
/* 非静态内部的创建需要依赖于外围类 */
OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
/* 方位非静态内部类的成员需要使用非静态内部类的实例 */
System.out.println(inner2._name2);
inner2.display();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.display();
}
}
六、局部内部类(用的很少,几乎没用过):
其作用域是所在方法,所以其他方法永远访问不到该方法的成员变量,故都不能使用访问控制修饰符