内部类的基本语法
类的组成永远只有两点:成员(Field)、方法(Method),但是几乎所有的程序里面都不会对嵌套有任何的限定。所以内部类指的是在一个类的内部可以继续嵌套其他类结构的一种形式代码,并且从理论上来讲可以一直嵌套下去。
范例:观察内部类代码
class Outer{//外部类
private String info="Hello World";
class Inner{//内部类
public void print(){
System.out.println(info);//输出info属性内容,这样写的好处是万一内部类和外部类定义了同样的内容时不会引起歧义Hello World
}
}
public void fun(){
Inner in=new Inner();//实例化内部类对象
in.print();//调用内部类方法
}
}
public class Hello {
public static void main(String args[]){
Outer out=new Outer();
out.fun();
}
}
类的核心组成就应该是属性和方法,但是如果引用了内部类,就相当于破坏了这样的程序结构。所以内部类所带来的最为严重的问题就在于程序结构的破坏,既然破坏了,那么也应该有一些收益。那么内部类的好处在哪里?
为了观察出内部类的好处,那么下面将内部类拿出来,变为两个类。
范例:内部类拿出来
class Outer{//外部类
private String info="Hello World";
public void fun(){
//将当前对象传递到内部类之中
Inner in=new Inner(this);//实例化内部类对象
in.print();//调用内部类方法
}
public String getInfo(){
return info;
}
}
class Inner{//内部类
private Outer temp;
public Inner(Outer temp){
this.temp=temp;
}
public void print(){
//相当于外部的out.getInfo()
System.out.println(this.temp.getInfo());//输出info属性内容Hello World
}
}
public class Hello {
public static void main(String args[]){
Outer out=new Outer();
out.fun();
}
}
可以发现内部类的最大好处在于可以直接进行外部类中私有属性的直接访问。
清楚了内部类的基本定义后,实际上又会存在以下几个问题 。
- 在编写代码中一直强调:只要是属性的访问,一定要加上“this”,这个时候由于属性是外部类中的,所以要想操作this,那么就必须使用“外部类.this.属性”
class Outer{//外部类
private String info="Hello World";
class Inner{//内部类
public void print(){
System.out.println(Outer.this.info);//输出info属性内容,这样写的好处是万一内部类和外部类定义了同样的内容时不会引起歧义Hello World
}
}
public void fun(){
Inner in=new Inner();//实例化内部类对象
in.print();//调用内部类方法
}
}
public class Hello {
public static void main(String args[]){
Outer out=new Outer();
out.fun();
}
}
- 通过以上代码可以发现内部类可以方便的访问外部类的私有属性,同时发现外部类的fun()方法里面也占着内部类的对象,那么内部类的私有属性外部类也可以直接利用对象访问。
class Outer{//外部类
private String info="Hello World";
class Inner{//内部类
private String msg="世界,和平!";
public void print(){
System.out.println(Outer.this.info);//输出info属性内容,这样写的好处是万一内部类和外部类定义了同样的内容时不会引起歧义Hello World
}
}
public void fun(){
Inner in=new Inner();//实例化内部类对象
in.print();//调用内部类方法
System.out.println(in.msg);//内部类对象直接调用属性
}
}
public class Hello {
public static void main(String args[]){
Outer out=new Outer();
out.fun();
}
}
内部类与外部类之间的私有属性都是可以直接互相进行访问的,这比分为两个类要更加的方便。
- 实例化内部类的对象操作都是在外部类的fun()方法中完成的。那么如果现在不希望通过内部类的方法操作内部类,那么也可以根据以下的语法,直接在其他类中实例化内部类对象,语法结构:
外部类名称.内部类名称 对象名称=new 外部类().new 内部类()。
为了解释此语法,首先来看一下程序编译后的结果。
现在通过程序的执行可以发现,在类中存在有一个“Outer.$Inner”的程序类,这个就属于Inner类的文件,内部类的标准名称应该是“外部类.内部类”,只不过“.”不可能直接出现在文件中。所以Java将其进行了转换,在文件名称中使用“ $”来代替“.”。
class Outer{//外部类
private String info="Hello World";
class Inner{//内部类
public void print(){
System.out.println(Outer.this.info);//输出info属性内容
}
}
}
public class Hello {
public static void main(String args[]){
Outer.Inner in = new Outer().new Inner();
in.print();
}
}
- 内部类可以利用private定义私有内部类:
class Outer{//外部类
private String info="Hello World";
private class Inner{//内部类
public void print(){
System.out.println(Outer.this.info);//输出info属性内容,这样写的好处是万一内部类和外部类定义了同样的内容时不会引起歧义Hello World
}
}
}
对于内部类的概念及其结构有个先期的认识即可。
利用static方法定义内部类
利用static定义的属性或者是方法,是不受类的控制的,也就是说相当于是一个局部外的结构。所以如果内部类使用了static定义,那么就表示此内部类变为了一个外部类,但是需要注意的是,如果它使用了static定义,那么只能够访问外部类中的static属性。
范例:利用static定义内部类
class Outer{//外部类
private static String info="Hello World";
static class Inner{//static内部类=外部类
public void print(){
System.out.println(info);//输出info属性内容
}
}
}
那么既然现在static的内部类变为了外部类,外部类就可以被其他类直接进行操作。但是这个时候实例化对象格式:
外部类名称.内部类名称 对象名称=new 外部类.new 内部类()。
加上static之后,那么实际上也就表示这个内部类的名字变成了“外部类.内部类”
范例:实例化内部类对象
public class Hello {
public static void main(String args[]){
Outer.Inner oi=new Outer.Inner();
oi.print();
}
}
以后见到程序类库中出现有“Xxxx.Xxxx”就表示内部类。
方法中定义内部类
理论上内部类可以在任何位置上定义,包括代码块中,类中,方法中,所以有时候在编程中可能直接在方法中使用内部类。
范例:观察方法中定义内部类
class Outer{//外部类
private String info="Hello World";
public void fun(int temp){//方法中的参数
double sal = 9000.0;//方法中定义的普通变量
class Inner{//内部类,方法中定义
public void print(){
System.out.println("Outer类中的info属性="+Outer.this.info);
System.out.println("fun()方法中的参数,temp="+temp);
System.out.println("fun()方法中定义的临时变量,sal="+sal);
}
}
new Inner().print();//实例化内部类对象,调用方法输出
}
}
public class Hello {
public static void main(String args[]){
Outer out=new Outer();//实例化Outer类对象
out.fun(100);
}
}
注意:现在使用的是JDK1.8版本
这个版本的好处是避免了一些复杂的细节,之所以避免是为了整体的设计考虑的,而以上的代码在JDK1.7时就会出现问题。因为在DK1.8以前有一个约定,如果一个方法中定义了内部类,那么这个内部类要想访问方法的参数或定义的变量,则参数或变量前必须加上final。
class Outer{//外部类
private String info="Hello World";
public void fun(final int temp){//方法中的参数
final double sal = 9000.0;//方法中定义的普通变量
class Inner{//内部类,方法中定义
public void print(){
System.out.println("Outer类中的info属性="+Outer.this.info);
System.out.println("fun()方法中的参数,temp="+temp);
System.out.println("fun()方法中定义的临时变量,sal="+sal);
}
}
new Inner().print();//实例化内部类对象,调用方法输出
}
}
public class Hello {
public static void main(String args[]){
Outer out=new Outer();//实例化Outer类对象
out.fun(100);
}
}
之所以可以不加final了那个Lamda与方法引用一起出现所造成的新局面。
总结
- 不要考虑怎么用,一般的开发很少会用到,但是会使用;
- 内部类先看明白它的语法形式。