Java内部类详解

来源:互联网 发布:visi是什么软件 编辑:程序博客网 时间:2024/06/14 15:10

http://www.cnblogs.com/dolphin0520/p/3811445.html


在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。下面就先来了解一下这四种内部类的用法。
1.成员内部类
成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:

class Circle {    double radius = 0;         public Circle(double radius) {        this.radius = radius;    }         class Draw {     //内部类        public void drawSahpe() {            System.out.println("drawshape");        }    }}
这样看起来,类Draw像是类Circle的一个成员,Circle称为外部类。成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
class Circle {    private double radius = 0;    public static int count =1;    public Circle(double radius) {        this.radius = radius;    }         class Draw {     //内部类        public void drawSahpe() {            System.out.println(radius);  //外部类的private成员            System.out.println(count);   //外部类的静态成员        }    }}
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:
class Circle {    private double radius = 0;     public Circle(double radius) {        this.radius = radius;        getDrawInstance().drawSahpe();   //必须先创建成员内部类的对象,再进行访问    }         private Draw getDrawInstance() {        return new Draw();    }         class Draw {     //内部类        public void drawSahpe() {            System.out.println(radius);  //外部类的private成员        }    }}
成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。创建成员内部类对象的一般方式如下:
public class Test {    public static void main(String[] args)  {        //第一种方式:        Outter outter = new Outter();        Outter.Inner inner = outter.new Inner();  //必须通过Outter对象来创建                 //第二种方式:        Outter.Inner inner1 = outter.getInnerInstance();    }} class Outter {    private Inner inner = null;    public Outter() {             }         public Inner getInnerInstance() {        if(inner == null)            inner = new Inner();        return inner;    }          class Inner {        public Inner() {                     }    }}
内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。


2.局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
class People{    public People() {             }} class Man{    public Man(){             }         public People getWoman(){        class Woman extends People{   //局部内部类            int age =0;        }        return new Woman();    }}
注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。


3.匿名内部类
匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。下面这段代码是一段Android事件监听代码:
scan_bt.setOnClickListener(new OnClickListener() {                         @Override            public void onClick(View v) {                // TODO Auto-generated method stub                             }        });                 history_bt.setOnClickListener(new OnClickListener() {                         @Override            public void onClick(View v) {                // TODO Auto-generated method stub                             }        });
这段代码为两个按钮设置监听器,这里面就使用了匿名内部类。这段代码中的:
new OnClickListener() {                         @Override            public void onClick(View v) {                // TODO Auto-generated method stub                             }        }
就是匿名内部类的使用。代码中需要给按钮设置监听器对象,使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用。当然像下面这种写法也是可以的,跟上面使用匿名内部类达到效果相同。
private void setListener(){    scan_bt.setOnClickListener(new Listener1());           history_bt.setOnClickListener(new Listener2());} class Listener1 implements View.OnClickListener{    @Override    public void onClick(View v) {    // TODO Auto-generated method stub                 }} class Listener2 implements View.OnClickListener{    @Override    public void onClick(View v) {    // TODO Auto-generated method stub                 }}
这种写法虽然能达到一样的效果,但是既冗长又难以维护,所以一般使用匿名内部类的方法来编写事件监听代码。
同样的,匿名内部类也是不能有访问修饰符和static修饰符的。
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。
匿名内部类在编译的时候由系统自动起名为Outter$1.class。
一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。


4.静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。
静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,
因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,
因为外部类的非static成员必须依附于具体的对象。
public class Test {    public static void main(String[] args)  {        Outter.Inner inner = new Outter.Inner();    }} class Outter {    public Outter() {             }         static class Inner {        public Inner() {                     }    }}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 尿素液烧的太慢了怎么办 天堂鸟肥料施多了黄叶了怎么办 死水塘养的鱼每天在死怎么办 北京的阿姆斯肥把苗都烧死了怎么办 纱窗被老鼠咬了个洞 怎么办 低电量模式下动态墙纸不能用怎么办 吃的包装袋执行标准错了怎么办 退换东西的时候外包装坏了怎么办 闲鱼买家以与描述不符退货怎么办 闲鱼买家申请退款又签收了怎么办 店铺买的手机是拆开过的怎么办 卖家以包装破损拒收快递怎么办 车辆迁出落户信封被自己拆开怎么办 快递签收了发现物品坏了怎么办 快递签收后发现货坏了怎么办 闲鱼退货有破损卖家要求赔偿怎么办 邮政快递收货后发现快递破损怎么办 中通把包裹发到别的省份去了怎么办 寄快递没拿单子但东西破损了怎么办 快递签收以后发现东西少了怎么办 淘宝时收到的货破损我该怎么办 淘宝买的冰箱七天无理由退货怎么办 截图放进ai中变得很模糊怎么办 买房子的贷款合同丢了怎么办 索尼9000e挂墙后面借口怎么办 想把木头锯成小块的怎么办 第一天上班交接完工作想辞职怎么办 POS机刷卡成功没打出单子怎么办 建行买的理财保险单子丢了怎么办 退休老师饭卡的钱突然少了怎么办 背驼得厉害头低的厉害怎么办 被别人举报自己碰瓷了怎么办 苹果平板微信屏幕不是全屏怎么办 大冒险告白被接受了怎么办在线阅读 手机屏锁图案密码忘了怎么办 opp手机锁屏密码忘了怎么办 宝宝的玩具里面脏了洗不到怎么办 早上起来眼睛被眼屎粘住了怎么办 魔兽世界神器满级任务放弃了怎么办 魔兽世界神器满级任务没接到怎么办 情侣空间上的照片删了怎么办