Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类。内部类又分为:常规内部类、局部内部类、匿名内部类和静态嵌套类四种。
常规/局部内部类
包含在一个类的类体中的类。
扩展:外部类的概念:包含了内部类的类。
问:在内部类的方法中,是否可以直接访问外部类的成员?
答: 肯定的。
问:在外部类的方法中,是否可以直接访问内部类的成员?
案: 否定的。
问: 那,如何访问?
答: 先创建内部类的对象,再通过对象去访问。
Demo
<span style="font-size:18px;"><span style="font-size:18px;">public class InnerClassTest { publicstatic void main(String[] args) { //InnerClass iObj = new InnerClass(); } } class OutClass { //外部类 privateString info; //外部类的实例变量 publicOutClass() { } publicOutClass(String info) { this.info= info; } publicvoid setInfo(String info) { this.info= info; } publicString getInfo() { returninfo; } //外部类的功能 publicvoid showInfo(){ System.out.println(info ); //System.out.println("在外部类的方法中直接访问内部类的成员x = " + x ); InnerClassiObj = new InnerClass(10, 20); System.out.println("在外部类的方法中必须通过内部类的对象,才能访问其成员. 如: iObj.x = " + iObj.x ); } publicclass InnerClass{ //内部类 privateint x; privateint y; publicInnerClass() { } publicInnerClass(int x, int y) { this.x= x; this.y= y; } publicvoid setX(int x) { this.x= x; } publicvoid setY(int y) { this.y= y; } publicint getX() { returnx; } publicint getY() { returny; } //内部类的功能方法 publicvoid showXY(){ System.out.println("x = " + x + ", y = " + y ); System.out.println("在内部类的方法中直接访问外部类的成员 info = " + info ); } } }</span></span>
匿名内部类
没有名称的内部类就是匿名的内部类。
从代码形式上看,什么样的类为匿名的内部类?
在创建一个类的对象时,在其构造器的末尾添加一对大括号,在大括号中重写某个方法或某几个方法。
这一段代码构成的整体就是一个匿名的内部类。且这个匿名的内部类属于该类的子类。
Demo
<span style="font-size:18px;"><span style="font-size:18px;">package com.hqg.oop.d39; import com.hqg.oop.d38.a2.MyDate; public class InnerClassTest { publicstatic void main(String[] args) { MyDatemd = new MyDate(2016, 3, 9 ){ //匿名的内部类。 @Override publicint getMonth() { if(super.getMonth() < 10 ){ System.out.print("0"); } returnsuper.getMonth(); } @Override publicint getDay() { if(super.getDay() < 10 ){ System.out.print("0"); } returnsuper.getDay(); } }; System.out.print("md对象表示的日期是:"); intyear = md.getYear(); //intmonth = md.getMonth(); //intday = md.getDay(); System.out.print(year + "年" ); System.out.print(md.getMonth()+ "月" ); System.out.println(md.getDay() + "日。" ); AppDemo ad = new AppDemo(3.36){ //匿名的内部类 @Override publicdouble area() { System.out.print("已知圆的半径 r =" + this.getR() + " 和圆周率 PI = " + PI + ";其面积area = "); returnsuper.area(); } }; doublea1 = ad.area(); System.out.println(a1 ); ADemoobj = new ADemo(){ //匿名的内部类 doubler = 3.5 ; @Override publicint add(int x, int y) { System.out.print(x + " + " + y + " = " ); returnx + y; } @Override publicdouble area() { System.out.print("\n===>>>已知圆的半径 r =" + r + " 和圆周率 PI = " + PI + ";其面积area = "); returnr * r * PI ; } }; a1= obj.area(); System.out.println(a1 ); } } //接口是否可以创建对象(实例化)? 答案: 不可以。 //(关于接口部分的内容,会在后面的总结过程中介绍,这里先不讲解) interface ADemo { publicstatic final double PI = 3.14; publicabstract int add( int x, int y ); publicabstract double area(); } class AppDemo implements ADemo { privatedouble r ; publicAppDemo() { //TODO Auto-generated constructor stub } publicAppDemo(double r) { this.r= r; } publicdouble getR() { returnr; } publicvoid setR(double r) { this.r= r; } @Override publicint add(int x, int y) { returnx + y; } @Override publicdouble area() { returnr * r * PI ; } }</span></span>
静态内部类
1、静态内部类定义
静态内部类,定义在类中,任何方法外,用static定义;静态内部类只能访问外部类的静态成员。
生成(new)一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成:Outer.Inner in=new Outer.Inner();而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类。可以定义私有静态内部类。
2、java实现静态内部类注意事项
将某个内部类定义为静态类,跟将其他类定义为静态类的方法基本相同,引用规则也基本一致。不过其细节方面仍然有很大的不同。具体来说,主要有如下几个地方要引起注意。
1)一般情况下,如果一个内部类不是被定义成静态内部类,那么在定义成员变量或者成员方法的时候,是不能够被定义成静态成员变量与静态成员方法的。也就是说,在非静态内部类中不可以声明静态成员
2)一般非静态外部类可以随意访问其外部类的成员变量以及方法(包括声明为private的方法),但是如果一个内部类被声明为static,则其在访问包括自身的外部类会有诸多的限制。静态内部类不能访问其外部类的非静态成员变量和方法
3)在一个类中创建非静态成员内部类的时候,有一个强制性的规定,即内部类的实例一定要绑定在外部类的实例中。然后要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。即在创建静态类内部对象时,不需要其外部类的对象
Demo
<span style="font-size:18px;"><span style="font-size:18px;">java在实现LinkedList时使用了如下内部类: public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>,Cloneable, java.io.Serializable { ........ private static class Entry<E> { E element; Entry<E> next; Entry<E> previous; Entry(E element, Entry<E> next,Entry<E> previous) { this.element = element; this.next = next; this.previous = previous; } } private Entry<E> addBefore(E e,Entry<E> entry) { Entry<E> newEntry = newEntry<E>(e, entry, entry.previous); newEntry.previous.next = newEntry; newEntry.next.previous = newEntry; size++; modCount++; return newEntry; } ........ }</span></span>
这里即静态内部类的典型用法
业务思想
在工作中,内部类的使用很方便,而最常见的尤为是匿名的内部类。当大家分工合作,敲着不同的模块,需要调用同事的类时,我们经常使用匿名的内部类,以更为高效地搞定。
合作双赢,思想无界。内部类的使用,使得我们工作起来更为轻松,也颇为舒心。