java中的内部类

一、成员内部类

package cd.itcast.test;
/*
 *  1、Inner 类中定义的 test() 方法可以直接访问 Outer 类中的数据,
 *      而不受访问控制符的影响,如直接访问 Outer 类中的私有属性a。
 *  2、定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能
 *      直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( )。
 *  3、编译上面的程序后,会发现产生了两个 .class 文件:Outer.class和Outer$Inner.class文件
 *  注意:
 *  1、外部类不能直接使用内部类的成员和方法。如果使用可创建内部类的对象来访问。
 *  2、外部类和内部类具有相同的成员变量或方法。内部类默认访问自己的变量或方法。
 */
public class Outer {
    private int a = 99;
    private int b = 55;
    //内部类
    public class Inner{
        int b = 88;
        public void test() {
            //内部类可以直接访问外部成员变量
            System.out.println("外部类变量a:"+ a);
            //2、外部类和内部类具有相同的成员变量或方法。内部类默认访问自己的变量或方法。
            System.out.println("访问外部同名的变量b:"+ Outer.this.b);
            System.out.println("内部类变量b:"+ b);
        }
    }
    public static void main(String[] args) {
        Outer o = new Outer();
        //注意内部类的创建方式
        Inner i= o.new Inner();
        i.test();
    }
}

二、静态内部类

package cd.itcast.test;
/*
 * 1、 静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问 
 * 2、 如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;
 *         如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员
 * 3、 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();
 */
public class SOuter {
    //外部私有变量
    private int a = 99;
    //外部静态变量
    static int b = 55;
    public static class SInner{
        int b = 66;
        public void test() {
            System.out.println("访问外部同名成员b:"+SOuter.b);
            System.out.println("访问内部类中的b:"+ b);
        }
    }
    
    public static void main(String[] args) {
        //静态内部类,直接创建
        SInner siInner=new SInner();
        siInner.test();
    }
}

三、方法内部类:就是在外部类的方法中定义内部类;只在该方法中可以使用。

package cd.itcast.test;
/*
 * 
 */
public class FOuter {
    private void show() {
        final int a = 25;//常量
        int b= 13;
        /*方法内部类:由于方法内部类不能在外部类的方法以外的地方使用,因此方法
        内部类不能使用访问控制符和 static 修饰符。*/
        class FInner{
            int c = 2;
            public void test() {
                System.out.println("访问外部类方法中的常量a:"+ a);
                System.out.println("访问内部类的变量c"+ c);
            }
        }
        //创建该类的对象:只能在本方法中创建
        FInner fi = new FInner();
        fi.test();
    }
    
    public static void main(String[] args) {
        FOuter fo = new FOuter();
        fo.show();
    }
}

 四、匿名内部类

  匿名内部类也就是没有名字的内部类

  正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

  但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口。

实例1:不使用匿名内部类来实现抽象方法

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

运行结果:eat something

  可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用

但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?这个时候就引入了匿名内部类

实例2:匿名内部类的基本实现

abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

运行结果:eat something

  可以看到,我们直接将抽象类Person中的方法在大括号中实现了

  这样便可以省略一个类的书写

  并且,匿名内部类还能用于接口上

实例3:在接口上使用匿名内部类

interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

运行结果:eat something

  由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现

  最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

实例4:Thread类的匿名内部类实现

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}

运行结果:1 2 3 4 5

posted on 2016-12-03 14:58  hgfs瑞  阅读(147)  评论(0编辑  收藏  举报

导航