1、本次的预计讲解的知识
1、内部类的基本定义结构;
2、使用static定义内部类;
3、在方法中定义内部类。
2、具体内容
如果从开发的角度,内部类能少用就少用。优先考虑的还是普通类。
3.1、基本概念
所谓的内部类值得失在一个类的内部继续定义了其它内部结构类的情况。
范例:观察内部类的基本形式
class Outer{ //外部类 private String msg = "Hello World !" ; class Inner{//定义了一个内部类 public void print () { System.out.println(msg) ; } } public void fun () { //实例化内部类对象,并且调用print()方法 new Inner().print() ; } } public class TextDemo { public static void main(String[] args) { Outer out = new Outer();//实例化外部类对象 out.fun();//调用外部类方法 } } |
以上的代码并不麻烦,但是最大感受,结构上好像有点不是很合理。
因为从类的结构本身就意味着,属性与方法的组成,可是一个类里面又定义了另外一个类。这个时候牺牲了程序的结构,但是至少达到了一个很重要的目的?
为了更好的发现出内部类的一个特点,下面将内部类拿到外面来,并且要求实现与之完全一样的功能。
范例:内部类拿到外面
class Outer{ //外部类 private String msg = "Hello World !" ; public void fun () { //实例化内部类对象,并且调用print()方法 new Inner().print() ; } } class Inner{ //定义了一个内部类 public void print () { System.out.println(msg) ; } } public class TextDemo { public static void main(String[] args) { Outer out = new Outer();//实例化外部类对象 out.fun();//调用外部类方法 } } |
1、内部类需要访问msg属性,但是此属性属于Outer类中,而在Outer类里面此属性使用private进行封装,所以来讲要得到此属性的内容需要定义一个getter方法。
public String getMsg() { return msg; } |
2、此时Outer类的getMsg()是一个普通方法,那么所有类中的普通方法必须通过类的实例化对象进行调用,如果实例化一个新的Outer类对象,实际上并不能使用,因为原始只有一个Outer类对象,现在不能变为两个,那么最好的做法是将主方法中的Outer类对象传递给Inner类。
class Outer{ //外部类 private String msg = "Hello World !" ; public void fun () { //实例化内部类对象,并且调用print()方法 new Inner(this).print() ; } public String getMsg() { return msg; } } class Inner{ //定义了一个内部类 private Outer out; public Inner (Outer out) { this.out = out ; } public void print () { System.out.println(this.out.getMsg()) ; } } public class TextDemo { public static void main(String[] args) { Outer out = new Outer();//实例化外部类对象 out.fun();//调用外部类方法 } } |
实际上折腾半天你的代码,最终的目的只有一个:让内部类可以访问外部类中定义的一个私有的msg属性内容。
内部类有一个最大的有点:可以方便的访问外部类的私有操作。
但是需要注意是,虽然内部类可以方便的访问外部类的私有属性,反之,外部类也可以通过内部类对象轻松的访问内部类的私有属性。
范例:访问内部类的私有属性
class Outer{ //外部类 private String msg = "Hello World !" ; class Inner{ //定义了一个内部类 private String info = "世界 你好!" ; public void print () { System.out.println(msg) ; } } public void fun () { Inner in = new Inner() ; //内部类对象 //直接用内部类对象访问了内部类中定义的私有属性 System.out.println(in.info) ; } } public class TextDemo { public static void main(String[] args) { Outer out = new Outer();//实例化外部类对象 out.fun();//调用外部类方法 } } |
一旦使用内部类之后,私有属性的访问就变得非常的简单了。
一直要求过,如果要访问属性前面一定要加上this,但是如果直接在print()方法里面加上this表示的是查找本类的属性,但是此时要访问的实际上是外部类的属性,你那么应该使用“外部类 . this . 属性”。
class Outer{ //外部类 private String msg = "Hello World !" ; class Inner{ //定义了一个内部类 public void print () { //外部类.this = 外部类的当前对象 System.out.println(Outer.this.msg) ; } } public void fun () { new Inner().print() ; } } public class TextDemo { public static void main(String[] args) { Outer out = new Outer();//实例化外部类对象 out.fun();//调用外部类方法 } } |
以上的所有的代码都有一个特点:通过外部类的一个fun()方法访问了内部类的操作。内部类能不能像普通对象那样直接在外部直接产生实例化对象调用呢?
如果要想解决此类问题,那么必须通过内部类的文件形式来观察。发现内部类的class文件的形式是:Outer$Inner.class。所有的“$”是在文件中的命名,如果换回到了程序里面就变为了“.”,也就是说内部类的名称就是“外部类 . 内部类”,此时可以给出内部类的实例化语法:
外部类 . 内部类 = new 外部类() . new 内部类() ; |
范例:实例化内部类对象
class Outer{ //外部类 private String msg = "Hello World !" ; class Inner{ //定义了一个内部类 public void print () { //外部类.this = 外部类的当前对象 System.out.println(Outer.this.msg) ; } } } public class TextDemo { public static void main(String[] args) { Outer.Inner in = new Outer().new Inner() ; in.print() ; } } |
内部类不可能离开外壁垒的实例化对象,所以一定要先实例化外部类对象后才可以使用内部类对象。如果真的使用到了内部类,也基本上不会像以上的操作那样进行的。一定是通过外部类访问内部类。
如果先在一个内部类希望被一个外部类访问,不能够被外部类掉用,那么可以使用private进行定义。
class Outer{ //外部类 private String msg = "Hello World !" ; private class Inner{ //定义了一个内部类 public void print () { //外部类.this = 外部类的当前对象 System.out.println(Outer.this.msg) ; } } } |
此时的内部类是不尅能在外部类进行对象实例化的。
2.2、使用static定义内部类
使用static定义的属性和方法是不受到实例化对象控制的,所以如果使用了static定义内部类,它一定不受外部类实例化对象的控制。
如果一个内部类使用了static定义的话,那么这个内部类就变边为了的一个外部类,并且只能够访问外部类中定义的static操作。
class Outer{ //外部类 private static String msg = "Hello World !" ; static class Inner{ //定义了一个内部类 public void print () { //外部类.this = 外部类的当前对象 System.out.println(msg) ; } } } |
但是此时如果想要取得内部类的实例化对象,使用的语法如下:
外部类 . 内部类 = new 外部类 . 内部类() ; |
此时不再需要先产生外部类对象,再产生内部类对象,仿佛就变成了独立的类。
class Outer{ //外部类 private static String msg = "Hello World !" ; static class Inner{ //定义了一个内部类 public void print () { //外部类.this = 外部类的当前对象 System.out.println(msg) ; } } } public class TextDemo { public static void main(String[] args) { Outer.Inner in = new Outer.Inner() ; in.print(); } } |
如果可以直接实例化“类.类”的时候一定要知道这是一个使用了static定义的内部类。
2.3、在方法中定义内部类(常用形式)
内部类可以在任何位置上定义,包括:类中,代码块里、方法里面,其中方法中定义内部类是比较常见的形式,如果后期要使用,也会使用到此类形式。
范例:在方法里面定义内部类
class Outer{ //外部类 private String msg = "Hello World !" ; public void fun () { class Inner {//方法中定义的内部类 public void print () { System.out.println(Outer.this.msg); } } new Inner().print(); } } public class TextDemo { public static void main(String[] args) { new Outer().fun(); } } |
但是方法里面会接收参数,方法里面会定义变量。
范例:访问方法中定义的参数或者是变量
class Outer{ //外部类 private String msg = "Hello World !" ; public void fun (int num) { //方法参数 double score = 90.9 ; //方法变量 class Inner {//方法中定义的内部类 public void print () { System.out.println("属性:" + Outer.this.msg); System.out.println("方法参数:" + num) ; System.out.println("方法变量:" + score) ; } } new Inner().print(); } } public class TextDemo { public static void main(String[] args) { new Outer().fun(100); } } |
此时返发现没有加入任何修饰,方法中的内部类可以访问方法的参数以及定义的变量,但是这种操作只适合与JDK 1.8之后的版本。如果在JDK1.7以及之前的版本有一个严格要求:方法中定义的内部类如果要想访问方法的参数或者是方法定义的变量,那么参数和变量前一定要加上“final”标记。
范例:正规代码
class Outer{ //外部类 private String msg = "Hello World !" ; public void fun (final int num) { //方法参数 final double score = 90.9 ; //方法变量 class Inner {//方法中定义的内部类 public void print () { System.out.println("属性:" + Outer.this.msg); System.out.println("方法参数:" + num) ; System.out.println("方法变量:" + score) ; } } new Inner().print(); } } public class TextDemo { public static void main(String[] args) { new Outer().fun(100); } } |
虽然有新特性,但是代码还要写完整。
3、总结
1、内部类只是阐述了基本定义形式,但是没有讲解如何去使用的;
2、内部类可以与外部类之间方法进行私有属性的访问;
3、内部类可以使用private声明,声明值后之后无法再外部类实例化内部类对象;
·语法:外部类.内部类 内部类对象 = new 外部类().new 内部类() ;
4、使用static定义的内部类就相当于是一个外部类:
·语法:外部类.内部类 内部类对象 = new 外部类.内部类() ;
5、内部类可以在方法中定义。