Java内部类总结

来源:互联网 发布:vscode svn插件 编辑:程序博客网 时间:2024/06/05 11:17

内部类是一种编译器现象,与虚拟机无关。编译器将会把内部类翻译成用美元符号$分隔外部类名与内部类名的常规类文件,而虚拟机对此一无所知。编译器为了引用外部类,生成了一个附加的实例域this$0

为什么要用内部类?

  • 内部类可以访问所在类域中的数据(包括私有);
  • 内部类可以在同一包中被隐藏;
  • 匿名内部类在实现回调时非常方便;

特殊语法

  • OuterClass.this表示外部类对象引用,比如Employee.this.id;
  • OuterObject.new InnerClass()显式调用内部对象的构造函数,例如this.new Payroll(10000);
  • OuterClass.InnerClass其它类访问内部类;
  • OuterClass$InnerClass编译器翻译成JVM能够识别的类,内部类对JVM是透明的.

内部类表现形式

  • 简单内部类
  • 局部的内部类
  • 匿名内部类
  • 静态内部类

简单内部类

每个内部类对象都有一个指向外部对象的隐式引用outer;每次外部类对象初始化一个内部类对象时都会把自己的this引用传给内部类对象的隐式的构造函数,以下是模拟的过程:

public class Outer{    //隐式会把this传给内部类对象的构造函数,实际这个过程看不到也不用去写.    public void function(){        Inner inner = new Inner(this);        ....    }    public class Inner{    //内部类有个隐式的构造函数生成外部类对象的引用,实际这个过程看不到也不用去显示调用        private Outer outer;        public Inner(Outer outer){            this.outer = outer;        }    }}

实例如下

public class Employee {    // 实例化对象时,在调用构造函数之前前初始化字段;    private int id; // 实例化对象时初始化为0    private String name; // 实例化对象时初始化为null    public Employee(int id, String name) {        this.id = id;        this.name = name;    }    public void start(){        //局部的内部类        class Computer{            private int seq;            public Computer(int seq){                this.seq = seq;        public void run(){                System.out.println(seq + " computer is run");            }        }        Computer c = new Computer(2015);            c.run();    }    //简单内部类    public class Payroll {        private int pay;        //以下是模拟生成外部类对象的引用        // private Employee outer;        // public Payroll(Employee e) {        // this.outer = e;        // }        public Payroll(int pay) {            this.pay = pay;        }        // 每个内部类对象都有一个指向外部对象的隐式引用outer,可以把id和name想象成outer.id和outer.name        public void printPay() {            //if (id == 1) {                if(Employee.this.id ==1){                System.out.println("name is " + name);                System.out.println("pay is: " + pay);                System.out.println("----------------------------");            } else {                System.out.println("you can not print pay");            }        }    }    public void printPayroll() {        //Payroll p = new Payroll(10000);        Payroll p = this.new Payroll(10000);        p.printPay();    }    public static void main(String[] args) {        Employee e1 = new Employee(1, "a");        Employee e2 = new Employee(2, "b");        e1.printPayroll();        e2.printPayroll();        e1.start();    }}

局部的内部类

在外部类方法中定义的内部类称为局部内部类,局部内部类不能用修饰符(public or private)定义.只能访问局部方法作用域的final变量.

    public void start(){        final int num = 2015;        class Computer{            private int seq;            public Computer(int seq){                this.seq = seq;            }               public void run(){                System.out.println("seq is: " + seq + ", num is: " + num);            }        }           Computer c = new Computer(2015);        c.run();    }

匿名内部类

语法如下,SuperType可是接口也可以是类.匿名内部类不能有构造函数.匿名内部类隐式地继承了一个父类或者实现了一个接口。

new SuperType(construction parameters)
{

inner class method and data

}

或者是
new InterfaceType()
{

inner class method and data

}

实例

new Thread() {            //匿名内部类            @Override            public void run() {                System.out.println("----------------------------");                System.out.println("this is a anonymous class run");            }}.start();

静态内部类

静态内部类与其它内部类相似,不同之处在于静态内部类没有指向外部类的引用.当不需要访问外部对象时,可以考虑使用静态内部类.被编译成一个完全独立的.class文件,名称为OuterClass$InnerClass.class的形式。只可以访问外部类的静态成员和静态方法,包括了私有的静态成员和方法。 注意,声明在接口中的内部类自动成为public和static。
实例

public class StaticInner {    private static int a = 4;    // 静态内部类    public static class Inner {        public void test() {            // 静态内部类可以访问外部类的静态成员            // 并且它只能访问静态的            System.out.println(a);        }    }    public static void main(String[] args) {        StaticInner.Inner inner = new StaticInner.Inner();        inner.test();    }}
0 0
原创粉丝点击