什么是内部类?
在java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类,与之对应,包含内部类的类被称之为外部类。
内部类在外部使用的时候,无法直接实例化。需要借由外部类信息才能完成实例化,因此,定义内部类可以更好地隐藏内部类的信息。
内部类大致可以分为三类:成员内部类(又叫普通内部类)、方法内部类(又叫局部内部类)、静态内部类。
匿名内部类在本文不提及,将另写一篇文章
成员内部类对象实例化
这里以成员内部类为例,介绍在外部需要定义内部类对象时,可以使用的三种方案。并以属性为例,测试当外部类成员与内部类成员重名时,对象优先调用情况。
首先,定义一个类-Older,定义成员变量age。在外部类里定义一个成员内部类-Younger,在内部类里,定义一个返回age值的nowAge方法,在方法里定义与外部类中age重名的属性,用来实验内部类实例化时调取的属性来源。代码如下:
//外部类
public class Older {
public int age; //注意这行代码,之后会添加static修饰符
//成员内部类
class Younger{
public String nowAge(){
int age=18;//这里为内部类age属性
return "今年"+age+"了"; //注意这行代码,之后会添加Older.this.
}
}
//这里定义一个获取内部类的方法,只用于方案三
public Younger getYounger(){
return new Younger();
}
}
新创建一个测试类,定义一个Older类对象,将其age赋值为60,这个age为外部类属性
Older KD=new Older();
KD.age=60;
利用三种方案定义内部类对象KDage,调用内部类方法输出。
方案一:new 外部类().new 内部类()
Older.Younger KDage=new Older().new Younger();
System.out.println(KDage.nowAge());
输出结果如下:
测试发现调用的是内部类age属性。
将内部类return中的age加上Older.this.,尝试调用外部类属性,修改后代码如下:
return "今年"+Older.this.age+"了";
输出结果如下:
测试发现调用失败了,返回的是int类型的默认值
保留Older.this.,修改外部类age属性,加上静态修饰符static,修改后代码如下:
public static int age;
输出结果:
测试发现,外部类属性调用成功。
保留static,删掉Older.this.
输出结果:
测试结果显示:
当内部类属性没有调用Older.this.方法时,无论外部类属性是静态或非静态,都会优先调用内部类的age属性。
当内部类属性调用Older.this.方法时,如果外部类age为静态成员,则会调用外部类属性,如果为非静态成员,则调用失败,返回默认值。
Older.this.+static | 外部类属性 |
---|---|
Older.this. | 默认值 |
static | 内部类属性 |
内部类属性 |
方案二: 外部类对象.new 内部类()
Older.Younger KDage=KD.new Younger();
System.out.println(KDage.nowAge());
测试发现返回为内部类属性。
将内部类return中的age加上Older.this.,尝试调用外部类属性。
测试发现,外部类属性调用成功。
保留Older.this.,将外部类属性修改为静态static类型。
测试结果依旧返回外部类属性。
保留static,删掉Older.this.
测试结果返回内部属性
实验结果显示:
当内部类属性调用Older.this.方法时,无论外部属性为静态或非静态,都会优先调用外部属性。
反之,当内部类没有调用Older.this.方法时,无论外部属性静态或非静态,都会优先调用内部属性。
Older.this.+static | 外部类属性 |
---|---|
Older.this. | 外部类属性 |
static | 内部类属性 |
内部类属性 |
方案三: 外部类对象.获取方法
方案三需要在外部类中定义一个返回内部类的方法,代码如下:
public Younger getYounger(){
return new Younger();
}
Older.Younger KDage=KD.getYounger();
System.out.println(KDage.nowAge());
输出结果:
方案三尝试调用外部类属性的实验结果和方案二相同。
静态内部类
静态内部类的创建
public static class Younger{
public static void say() {
}
public String nowAge() {
int age=18;
//new Older().这里是外部类方法名();
return "今年"+age+"了";
}
}
定义静态内部类的对象可以不依赖于外部类对象,直接创建。new 外部类.内部类()
Older.Younger KDage=new Older.Younger();
System.out.println(KDage.nowAge());
静态内部类对象调用外部类成员测试:
当外部类属性为静态时,既可以通过外部类.age的方式调用,也可以通过对象实例化new 外部类().age的方式调用,代码如下:
return "今年"+Older.age+"了";
//return "今年"+new Older().age+"了";
若外部类属性为非静态成员,则只能通过对象实例化new 外部类().age的方式调用。
调用静态类中的静态方法时,可以直接使用外部类.内部类.静态方法名() 的方式。代码如下:
Older.Younger.say();
注意:在静态内部类中,如果想要调用外部类成员(属性、方法)时,不需要加this.
方法内部类
方法内部类定义在方法内,作用范围也在方法内。
方法内部类一般利用带返回值的方式使用,可以将外部方法定义为成Object类型,然后返回new 内部类().内部类方法()
方法内部类的创建:
public Object getAge(){
class Younger{
public String nowAge(){
int age=18;
return "今年"+age+"了";
}
}
return new Younger().nowAge();
}
在使用方法内部类时,直接用对象名调用外部方法即可,代码如下:
System.out.println(KD.getAge());
方法内部类调用外部类成员的方式和成员内部类一样
方法内部类使用注意事项:
1.和方法内部成员使用规则一样,class不可以添加public,private,protected,static
2.类中不能包含静态成员,最终型fina成员可以
3.可以使用抽象类方法,但是返回时会报错,所以不推荐这样使用
其他小知识
1.内部类的访问修饰符和正常类的访问修饰符作用相同
2.内部类可以直接使用外部类的常量和方法
3.内部类编译后.class文件命名:外部类&内部类.class
4.方法中成员的使用规则:
1).方法内定义的局部变量只能在方法里使用
2).方法内不能定义静态成员
3).不能使用public private protected这些访问修饰符