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>
这里即静态内部类的典型用法
业务思想
在工作中,内部类的使用很方便,而最常见的尤为是匿名的内部类。当大家分工合作,敲着不同的模块,需要调用同事的类时,我们经常使用匿名的内部类,以更为高效地搞定。
合作双赢,思想无界。内部类的使用,使得我们工作起来更为轻松,也颇为舒心。