目录
内部类就是定义在类里面的类,它又分为:实例内部类,静态内部类,局部内部类和匿名内部类,下面我们来逐个介绍。
一,实例内部类
实例内部类就是未被 static 修饰的类,例如:
class Out{
public int a;
private int b;
private static int c;
//实例内部类
class In{
public int d;
private int e;
public void print(){
System.out.println("内部类!");
}
}
public void show(){
System.out.println("外部类!");
}
}
1. 定义了一个实例内部类之后,我们如何去实例化一个实例内部类?
记住一句话:先有外部类对象,再有内部类对象。因为实例内部类是在外部类中定义的,所以实例内部类可以看成是外部类的一个成员,因此在实例化一个实例内部类之前,我们要先实例化一个外部类,而实例化对象的类型是 外部类类名 . 内部类类名 ,例如:
public class Test {
public static void main(String[] args) {
//第一种
Out out = new Out();
Out.In in = out.new In();
//第二种
Out.In in1 = new Out().new In();
}
}
2. 实例内部类中不能定义一个由 static 修饰的成员,除非是 static final ,这是为什么?
因为由static修饰的成员是类本身的属性,是不依赖于对象的,也就是说由static修饰的成员是在类加载的时候创建的,而不由static修饰的成员因依赖于对象,则是在实例化对象的时候创建,上面提到过实例内部类因定义在外部类中,被当成是外部类中的普通成员,就是说实例内部类(依赖于对象)要在实例化对象的时候创建,而实例内部类中的static修饰的成员(不依赖于对象)则是在类加载时创建,这两者矛盾,所以不能在实例内部类中定义由static修饰的成员。
因为static final 修饰的是一个常量,它不在类加载时创建,而是在编译时完成,所以可以。
3. 在实例内部类方法中访问同名的成员时,我们访问谁的?如果要访问外部类同名的成员,如何访问?
遵守就近原则,优先访问实例内部类的成员,如果要访问外部类同名的成员,用 外部类类名.this.来访问,因为实例内部类的非静态方法中包含了一个指向外部类对象的引用。如下:
class Out{
public int a = 5;
private int b;
private static int c;
class In{
public int a = 10;
public int d;
private int e;
static final int f = 10;
public void print(){
System.out.println(a);//就近原则,优先访问实例内部类的
System.out.println(Out.this.a);//要访问外部类同名的成员,用 外部类类名.this.来访问
System.out.println("内部类!");
}
}
public void show(){
System.out.println("外部类!");
}
}
4. 我们如何在外部类方法中访问内部类的成员?
先创建一个实例内部类对象,再通过对象去访问,例如:
class Out{
public int a = 5;
class In{
public int a = 10;
public int d = 20;
public void print(){
System.out.println("内部类!");
}
}
public void show(){
In in = new In();//只有在外部类中才可以这样实例化
System.out.println(in.d);
System.out.println("外部类!");
}
}
总结一下:
1. 外部类中的任何成员都可以在实例内部类方法中直接访问
2. 实例内部类可以当成外部类的成员,所以实例内部类也受public,private等访问限定符的限制
3. 创建实力内部类对象必须先创建外部类对象
4. 实例内部类不能定义静态成员(除了static final)
5. 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须使用 外部类类名.this.同名成员 来访问
6. 外部类中不能直接访问内部类中的成员,若要访问,必须先创建实例内部类的对象
二,静态内部类
静态内部类就是被static修饰的类,例如:
class Out{
public int date1 = 1;
private static int date2;
public static void print(){
System.out.println("外部类!");
}
public void print1(){
System.out.println("1232132");
}
//静态内部类
static class In{
public int date3 = 3;
private static int date4 = 4;
public void test(){
System.out.println("内部类!");
}
}
}
1. 如何实例化一个静态内部类?
与实例内部类不同,因为静态内部类是由static修饰的,说明静态内部类是外部类本身的属性,因此创建静态内部类时要 new 外部类类名.静态内部类类名(); 如下:
public class Test {
public static void main(String[] args) {
/*Out.In in1 = new Out().new In();错误写法*/
Out.In in = new Out.In();//创建静态内部类
}
}
2. 静态内部类可以定义由static 修饰的成员(即静态成员)
3. 静态内部类的方法不可以直接访问外部类中的非静态成员,为什么?
因为静态内部类是由static修饰,也就是说它不依赖于对象,是在类加载时创建的,而非静态成员依赖于对象,是在实例化对象的时候创建,也就是说,我们在静态内部类中访问的外部类非静态成员时,它们还没有被创建,也就无法访问。
那么我们如何间接的访问呢?很简单,在方法中实例化一个外部类对象,通过对象的引用去访问。
class Out{
public int date1 = 1;
private static int date2;
public static void print(){
System.out.println("外部类!");
}
public void print1(){
System.out.println("1232132");
}
static class In{
public int date3 = 3;
private static int date4 = 4;
public void test(){
//实例化外部类对象,通过对象访问非静态
Out out = new Out();
System.out.println(out.date1);
out.print1();
//可以直接访问静态的
print();
date2 = 9;
System.out.println("内部类!");
}
}
}
与实例内部类的不同点:
1. 静态内部类对象的创建是直接 new 外部类类名.内部类类名() ,不需要先实例化一个外部类对象
2. 静态内部类中的方法不能直接访问外部类中的静态成员,若硬要访问就必须先实例化一个外部类对象
3. 静态内部类可以定义静态成员
三,局部内部类
局部内部类:定义在外部类方法中的类 - 几乎不使用,了解一下
class Out{
public void print(){
class In{
public int date = 10;
}
In in = new In();
System.out.println(in.date);
}
}
注意:
1. 局部内部类只能在所定义的方法体内部使用
2. 不能被public、static等修饰符修饰
四,匿名内部类
匿名内部类,顾名思义就是没有名字的类,使用起来与上面的都不同,需要与接口一起使用,代码如下:
interface A{
void B();
}
public class Test {
public static void main(String[] args) {
//可以这样理解:有一个类 实现了A接口 并且重写了 B方法
//第一种使用方法
new A(){
@Override
public void B() {
System.out.println("hhhhhh");
}
}.B();
//第二种使用方法
A a = new A() {
@Override
public void B() {
System.out.println("111111");
}
};
a.B();
}
}