Java内部类总结
一. 定义:
将一个类定义在另一个类的局部或者成员位置,成为内部类。
二. 内部类定义规则
1. 一个内部类的成员不能被static所修饰,如果要被static修饰,那么这个内部类也要用static修饰。
2. 当一个内部类定义在外部类的成员位置上时,就可以被成员修饰符修饰,如private、public、static、final。
3. 内部类定义在局部时(成员方法中),不可以被成员修饰符修饰,private、public、static,但是可以被final修饰,局部内部类的成员可以被成员修饰修饰(static除外,因为它一旦声明为static,意味着它所在的内部类也要修饰成static,但是局部内部类不用成员修饰符修饰)
三. 内部类的访问规则
1. 一个非静态内部类(其成员绝对不能是静态),可以访问外部类的任何成员。
而它的外层类的方法则需要通过new 内部类的对象方式进行访问内部类的成员。
格式: Inner in = new Inner();
2. 一个被private修饰内部类(其成员绝对不能是静态),也可以访问外层类类的任何成员,但是一个内部类一旦被private修饰之后,外界就不能直接进行访问,创建对象等操作。
注意: 之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
3. 一个非静态内部类,如果它外层类静态方法要访问内部类的话,就必须使用如下方式创建对象进行访问(或者将内部类修饰为静态内部类):
格式: MyOuter.MyInnerin = newMyOuter().newMyInner();
public classInnerTestDemo
{
public static voidmain(String[] args)
{
MyOuter.myMethod();
}
}
classMyOuter
{
classMyInner
{
int a =23;
public voidshow()
{
System.out.println(a);
}
}
public static voidmyMethod()
{
//不能编译
//new MyInner().show();
//编译成功。因为内部类相当于外层类的成员,因为myMethod()方法存//在时,这些非静态的成员必须建立对象才能在内存中存在,所以要先//创建外层内的对象,再创建内部//类的对象。
MyOuter.MyInner in = newMyOuter().newMyInner();
in.show();
}
}
4. 外部类要访问内部类,必须建立内部类对象。
5. 当内部类定义在外部类成员位置上,而且不是私有,可以被外部类的其他类直接建立对象。
格式:
外部类.内部类 变量名 = 外部类对象.内部类对象;
MyOuter.MyInner in = newMyOuter().newMyInner();
6. 当内部类被static修饰之后,具备static的特性,只能访问外部类的static的成员。
7. 在外层内中如何访问静态内部类的非静态成员?
格式:newInner().show()
classOuter
{
static int x = 0;
int y = 1;
static classInner
{
voidshow()
{
System.out.println(x);
}
}
public static voidfunction()
{
newInner().show();//ok
}
public voidfunction2()
{
newInner().show();//ok
}
}
8. 外层类如何访问静态内部类的静态成员?
格式:Inner.show();
因为都是内部类和内部类的成员都是静态的,外层类就可以直接以类名.静态成员的方法访问。
9. 在外部的其他类中,如何直接访问静态内部类的非静态成员呢?
格式: new Outer.Inner().show();
public classInnerTestDemo2
{
public static voidmain(String[] args)
{
//因为内部类是static的,可以通过外部类.内部类的方法,但是
//静态内部类的show()方法是非静态的,无法在静态main方法中//调用,只能创建Inner内部类的对象来调用。
newOuter.Inner().show();//ok
Outer.function();
}
}
classOuter
{
static int x = 0;
int y = 1;
static classInner
{
voidshow()
{
System.out.println(x);
}
}
public static voidfunction()
{
newInner().show();//ok
}
public voidfunction2()
{
newInner().show();//ok
}
}
10. 在外部其他类中,如何直接访问静态内部类的静态成员呢?
格式:Outer.Inner.show();
public classInnerTestDemo2
{
public static voidmain(String[] args)
{
Outer.Inner.show();//ok
Outer.function();
}
}
classOuter
{
static int x = 0;
int y = 1;
static class Inner
{
static voidshow()
{
System.out.println(x);
}
}
public static voidfunction()
{
Inner.show();
}
public voidfunction2()
{
Inner.show();
}
}
11. 内部类定义在局部时,可以直接访问外层类的的成员,因为还持有外层类类中的引用,但是不可以访问它所在局部中的变量,只能访问被final修饰的局部变量。
public classInnerTestDemo4
{
public static voidmain(String[] args)
{
A a = new A();
a.show();
}
}
class A
{
String s = "hello!";
voidshow()
{
int a= 5;
final int b =6;
classInnerB
{
public int c= 7;
public voidfunction()
{
//局部内部类还可以访问外部类的成员
System.out.println(s);
//编译失败,不能访问局部非final的变量
//System.out.println(a);
//只能访问局部方法中的final修饰的变量
System.out.println(b);
}
}
//如果需要运行外层类的show()方法必须建立局部内部类的对象
//再调用局部内部类的方法或成员,而且对象的创建和调用成员语句
//必须是要放在类的定义后面,因为方法是按照数序执行。
InnerB ib = newInnerB();
ib.function();
System.out.println(ib.c);
}
}
12. 局部内部类访问所在部方法的参数是,参数必须是final修饰的,否则无法访问或编译失败。
public classInnerTestDemo4
{
public static voidmain(String[] args)
{
A a = new A();
//当这个方法调用完毕会释放这两个参数在栈内存中的空间
//并不会影响下一举方法的执行。
a.show(4,5);
a.show(6,7);
}
}
class A
{
voidshow(final int a, final int b)
{
classInnerB
{
public int c= 7;
public voidfunction()
{
//局部内部类要访问局部方法的参数,将参数接收时就必须
//将其修饰为final
System.out.println(a+b);
}
}
InnerB ib = newInnerB();
ib.function();
}
}
13. 对外界完全隐藏,即使此方法所在的类也不可访问,也就是说,除此方法外,无任何方法知道它的存在。
14. 当外部类中的静态方法访问内部类时,内部类也必须是static的。
四. 何时使用内部类
1. 当描述事物时,事物的内部还有事物,则该事物使用内部类来描述,因为内部事物要使用外部事物内容
举例来说:楼房内部还有家庭住户,家庭住户中还有房间,这就可以用内部类描述。(总不能访问一个住户,就建立一个楼房对象吧,那就可真是有钱人的风范了。)
2. 当一个类需要直接访问另一个类中的成员时,则当这个类放入另一个类中,并将内部类封装。
3. 当一个内部类为静态内部类,想去访问外部内的成员时候,它只能访问外部类的静态成员,如果外部类的静态成员相对少的话,定义静态内部类意义不大,只有外部类含有较多静态内部类时候,用是比较方法,比较合适的。
五. 匿名内部类
1. 匿名内部类其实就是内部类的简写格式
2. 定义匿名内部类的前提:内部类必须继承一个类或实现接口。
注意:可以不继承一个类,仍可以定义一个匿名类,那么可以依靠Object类来定一个匿名类,因为任何类都是Object类的子类。
3. 匿名类的格式: new 父类或者接口(){定义子类的内容}
注意:
A. 其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。 可以理解为带内容的对象。
B. 匿名内部类中定义的方法最好不要超过3个。
C. 当创建接口或抽象类的匿名子类对象时,必须全部复写接口中的方法。
D. 当创建一般类的匿名子类对象时,可以不用复写全部方法,只需复写需要的即可。
public classNoNameInnerDemo
{
public static voidmain(String[] args)
{
OuterClass oc = newOuterClass ();
oc.function();
oc.function2();
}
}
classPerson
{
voidshow()
{
System.out.println("父类show");
}
voidsay()
{
System.out.println("父类say");
}
}
interfaceInnerClass
{
public abstract voidtest();
public abstract voidgo();
}
class OuterClass
{
voidfunction()
{
final int a =3;
//当创建一般类的匿名子类对象时,可以不用复写全部方法,
//只需复写需要的即可。
newPerson()
{
voidshow()
{
System.out.println("匿名show:"+a);
}
}.show();
}
voidfunction2()
{
//当创建接口或抽象类的匿名子类对象时,必须全部复写接口中的方法。
InnerClass ic = newInnerClass()
{
public void go()
{
System.out.println("interfacego!");
};
public voidtest()
{
System.out.println("interfacetest!");
}
};
ic.go();
ic.test();
}
}