JAVA内部类:定义在另一个类内部的类,内部类分为静态类、匿名类、成员类、局部类。当描述事物时,事物的内部还有事物,该事物用内部类来描述。
不使用内部类来实现
- class Outer
- {
- int x = 2;
- }
- class Inner
- {
- void method()
- {
- System.out.println("method="+new Outer().x);
- }
- }
- class InnerClassDemo5
- {
- public static void main(String[] args)
- {
- new Inner().method();
- }
- }
在上例中没有使用内部类,Inner如果要调用Outer的成员,则需要先创建对方的对象,而使用内部类的好处就是内部类可以直接访问外部类中的成员(包括私有),而不用建立外部类的对象。
注: 外部类要访问内部类时,仍须建立内部类对象。
成员内部类
- class Outer
- {
- Private int x = 3;
- class Inner //内部类在外部类成员位置时可以被private、static修饰
- {
- void method()
- {
- System.out.println("method"+x);
- }
- }
- void function()
- {
- new Inner().method();
- }
- }
- class InnerClassDemo4
- {
- public static void main(String[] args)
- {
- Outer.Inner in = new Outer().new Inner();
- in.method();
- // new Outer().function();
- }
- }
Outer.Inner in = new Outer().new Inner(); 可以用来生成内部类的对象,格式为:
外部类名.内部类名变量名 =外部类对象.内部类对象;
此方法较少用到,因为我们一般将内部类private封装,并提供一个方法供外部其他类调用内部类的成员。
注意:必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量。
程序编译过后会产生两个.class文件,分别是Outer.class和Outer$Inner.class,所以内部类的成员变量/方法名可以和外部类的相同。
内部类中的变量访问形式
- <span style="font-size:12px;">class Outer
- {
- private int x = 3;
- private class Inner
- {
- int x = 4;
- void method()
- {
- int x = 5;
- System.out.println("局部变量:"+x);
- System.out.println("内部类变量:"+this.x);
- System.out.println("外部类变量:"+Outer.this.x);
- }
- }
- void function()
- {
- new Inner().method();
- }
- }
- class InnerClassDemo9
- {
- public static void main(String[] args)
- {
- new Outer().function();
- }
- }
- </span>
运行结果:
局部变量:5
内部类变量:4
外部类变量:3
内部类在没有同名成员变量和局部变量的情况下,内部类会直接访问外部类的成员变量,这是因为省略了Out.this.属性名,否则,内部类中的局部变量会覆盖外部类的成员变量;
访问内部类本身的成员变量可用this.属性名,访问外部类的成员变量需要使用Out.this.属性名。
静态内部类
静态类作为类的静态成员存在于某个类中,定义静态类只需在类的定义中加入关键字static。
- class Outer
- {
- Private static int x = 3;
- static class Inner
- {
- void method()
- {
- System.out.println("method"+x);
- }
- }
- }
- class InnerClassDemo5
- {
- public static void main(String[] args)
- {
- Outer.Inner in = new Outer.Inner(); // Outer.Inner()为直接通过外部类类名调用的内部类
- in.method();
- }
- }
在类Outer中定义了静态类Inner后,可将静态类Inner看成类Outer的static成员。
当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。
因为内部类被静态化,Static成员可以在不创建外部类Outer对象的情况下,直接new出内部类Inner的对象。
在外部其他类中,直接访问static内部类的非静态成员
new Outer.Inner().method ();
在外部其他类中,直接访问static内部类的静态成员,即method()前也被static修饰。
new Outer.Inner.method ();
注意:当内部类中定义了静态成员,该内部类必须是static的;当外部类中的静态方法访问内部类时,内部类也必须是static的。
局部内部类
局部类和局部变量一样,是指在方法内部定义的类。
- class Outer
- {
- int x = 3;
- void function() //类Outer的成员方法function()
- {
- class Inner //成员方法中定义局部类Inner
- {
- void method() //局部类中的成员方法method()
- {
- System.out.println(Outer.this.x);
- }
- }
- new Inner().method(); //需生成局部类的对象,调用method()
- }
- }
- class InnerClassDemo7
- {
- public static void main(String[] args)
- {
- Outer out = new Outer(); //生成类Outer的对象
- out.function();
- }
- }
注意:从内部类中访问局部变量,需要被声明为最终类型final。
例如在类Outer的成员方法function()中增加一局部变量,应为final int y = 7。
匿名内部类
匿名内部类其实就是内部类的简写,使用匿名内部类的前提条件:必须继承一个父类或实现一个接口。
不使用匿名内部类来实现抽象方法:
- abstract class Anonymous
- {
- abstract void method();
- }
- class Outer
- {
- private int x = 23;
- private class Inner extends Anonymous
- {
- void method()
- {
- System.out.println("method="+x);
- }
- }
- public void function()
- {
- new Inner().method();
- }
- }
- class InnerClassDemo8
- {
- public static void main(String[] args)
- {
- new Outer().function();
- }
- }
如果此处的Inner类只使用一次,可以不用将其编写为一个独立的类,可写为如下代码:
- abstract class Anonymous{
- abstract void method();
- }
- class Outer{
- private int x = 23;
- public void function(){
- new Anonymous(){
- void method(){
- System.out.println("method="+x);
- }
- }.method();
- }
- }
- class InnerClassDemo10{
- public static void main(String[] args){
- new Outer().function();
- }
- }
匿名内部类的格式: new父类或者接口(){定义子类的内容}
- class Outer{
- private int x = 23;
- public void function(){
- new Anonymous(){
- void method(){
- System.out.println("method="+x);
- }
- void show(){
- System.out.println("show");
- }
- }.method();
- new Anonymous(){
- void method(){
- System.out.println("method="+x);
- }
- void show(){
- System.out.println("show");
- }
- }.show();
- }
- }
- class InnerClassDemo10{
- public static void main(String[] args){
- new Outer().function();
- }
- }
匿名对象对方法只能调用一次,如需调用多个方法,需要建立多个匿名对象。