揭秘内部类

情景
A类中的内容要被B类直接访问,而A类还需要创建B的对象访问B的内容时,
这时,可以将B类定义到A类的内部,这样访问更为便捷。

将B称之为内部类(内置类,嵌套类)

访问方式
内部类可以直接访问外部类中的所有成员,包括私有的。
而外部类要想访问内部类的成员,必须创建内部类的对象。

应用
当描述事物时,事物的内部还有事物,这个内部的事物还在访问外部事物中的内容。
这时就将这个事物通过内部类来描述。

【内部类被访问的方式】
情况一:内部类在成员位置上的被访问的方式。
成员时可以被指定的修饰符所修饰的。
public:不多见,因为更多的时候,内部类已经被封装到了外部类中,不直接对外提供。
static:详见下面代码体现。

代码

class Outer/*A类即外部类*/
{
    private static int num =5;

    public class Inner/*B类即内部类*/
    {
        void show()
        {
            System.out.println("num="+num);
        }
//      static void show1(){}
        //非静态内部类中不允许定义静态成员,仅允许在非静态内部类中定义 静态常量 static final.
        //如果想要在内部类中定义静态成员,必须内部类也要被静态修饰
    }
    /* 
    内部类被静态修饰后,随着Outer的加载而加载,可以把一个静态内部类理解为就是一个外部类。
    */
    static class Inner2
    {
        void show2()
        {
            System.out.println("Inner2 show2 run..."+num);
        }
        static void staticShow()
        {
            System.out.println("Inner2 staticshow run...");
        }


    }
    void method()
    {
        /*Outer.*/Inner in =new /*Outer.*/Inner();
        in.show();
    }
}

class InnerClassDemo
{
    public static void main(String[] args)
    {
/*      Outer out=new Outer();
        out.method(); */
        //情况一:直接访问Outer中的Inner内部类的非静态成员
        //创建内部类的对象即可。--内部类作为成员,应该先有外部类对象,再有内部类对象。
/*      Outer.Inner in=new Outer().new Inner();
        in.show();
*/      
        //情况二:对静态内部类中的非静态成员进行调用。
        //因为内部类是静态,所以不需要创建Outer的对象,直接创建内部类对象即可。
/*      Outer.Inner2 in=new Outer.Inner2();
        in.show2(); */
        //如果静态内部类有静态成员,该如何访问呢?既然惊涛内部类已随外部类加载,而且静态成员随着类的加载而加载。
        //就不需要对象,直接类名调用即可。
        // Outer.Inner2.staticShow();
    }
}

问题1
为什么内部类就能直接访问外部类中的成员呢?

那是因为内部类其实持有外部类的引用 ->外部类.this
对于静态内部类不持有 外部类.this 而是直接使用 外部类名.

class Outer
{
    int num=3;
    class Inner 
    {
        int num=4;
        void show()
        {
            int num = 5;
            System.out.println("num ="+num);
            System.out.println("num ="+this.num);
            System.out.println("num ="+Outer.this.num);
        }
    }
    void method()
    {
        // System.out.println(num);
        new Inner().show();
    }
}

class InnerClassDemo2
{
    public static void main(String[] args)
    {
        Outer out =new Outer();
        out.method();
    }
}

输出结果为:

num =5
num =4
num =3

内部类其实也可以定义外部类的局部位置上。

内部类定义在局部时,只能访问被final修饰的局部变量
为什么呢?
分析内存,可以知道如果访问的局部变量不是常量,其生命周期太短,导致访问失败。

class Outer
{
    int num=3;

    void method()
    {
        final int x = 5;//局部变量
        int y=2;
        class Inner //局部内部类。不能被成员修饰符修饰
        {
            void show()
            {
                System.out.println("y ="y);//访问失败,y的生命周期太短了。
                System.out.println("x ="x);
                System.out.println("num ="+num);
            }
        }
        new Inner().show();
    }
}
class Outer2
{
    Object obj;
    public void method()
    {
        int y=9;
        class Inner
        {
            public String toString()
            {
                return "toString"+y;
            }
        }
        obj =new Inner();//给obj赋一个Inner对象。

    }
    public void fun()
    {
        System.out.println(obj.toString());
    }
}
class InnerClassDemo3
{
    public static void main(String[] args)
    {
        Outer2 out =new Outer2();
        out.method();
    }
}

看API中发现类名或者接口名称中有(.)说明内部类,或者内部接口。

内部类的延伸
内部类是可以继承或者实现外部类其他的或者接口的。

好处:通过内部类的方式对类进行继承重写,或者接口的方式。
通过公共的方式对其内部类对象进行访问,因为通常内部类很有可能被外部类封装其中。
我们可以通过父类或者接口的方式访问到内部类对象。

abstract class AbsDemo
{
    abstract void show();
}
class Outer
{
    int num=3;
    private class Inner extends AbsDemo
    {
        //重写抽象方法show().
        void show()
        {
            System.out.println("num ="+num);
        }
    }
    //获取内部类的对象
    public  AbsDemo getObject()
    {
        return new Inner();
    }
    void method()
    {
        new Inner().show();
    }

}

class InnerClassDemo4
{
    public static void main(String[] args)
    {
        Outer out =new Outer();
//      out.method();
/*      Outer.Inner in =out.getObject();
        in.show(); */
        //如果Inner被private .可以通过父类型获取。
        AbsDemo a=new Outer.getObject();// 多态
        a.show();

    }
}

对代码进行简化
匿名内部类,其实就是一个带有内容的子类对象
格式:new 父类or接口(){子类的内容}
匿名内部类就是内部类的简化形式。
匿名内部类是有前提,内部类必须要继承父类或者实现接口

abstract class AbsDemo
{
    abstract void show();
}
class Outer
{
    int num=3;
/*  class Inner extends AbsDemo
    {
        void show()
        {
            System.out.println("num ="+num);
        }
    } */
    void method()
    {
//      new Inner().show();
        /*
        不想创建具体的子类型,还想创建AbsDemo的子类对象。
        怎么实现呢?没有子类型,直接使用父类型。
        在该例子中是抽象类,怎么可以new对象呢?
        抽象类之所以不能new对象是因为抽象方法没重写,直接重写即可。
        */
        new AbsDemo()//这个是一个AbsDemo的子类对象,只不过这个对象有点胖-这是一个带着内容的子类对象。
        {           //这就是:匿名内部类
            //重写抽象的show方法。
            void show()
            {
                System.out.println("num ====="+num);
            }
        }.show();
    }

}

class InnerClassDemo5
{
    public static void main(String[] args)
    {
        Outer out =new Outer();
        out.method();       
    }
}

匿名内部类的使用:

interface Inter
{
    void show1();
    void show2();
}
class Outer
{
    int num =4;
    //在一个类使用一个接口的对象,可以通过内部类来实现。
/*  class Inner implements Inner
    {
        public void show1()
        {}
        public void show2()
        {}
    } */
    public void method()
    {
/*      Inner in =new Inner();
        in.show1();
        in.show2(); 
*/
//      进行简化,写出匿名内部类的方式
        Inter in =new Inter()
        {
            public void show1()
            {}
            public void show2()
            {}
        }
        in.show1();
        in.show2();
    }
}


class InnerClassDemo6
{
    public static void main(String[] args)
    {
        Outer out =new Outer();
        out.method();       
    }
}

匿名内部类的练习:

//匿名内部类练习。
interface Inter
{
    public void show();
}
class Outer
{
    //代码补足,要求使用匿名内部类
/*  public static Inter method()
    {
        return new Inter()
        {
            public void show(){
                System.out.println("hello");
            }
        };
    } 
*/
    //还原成内部类,当静态方法访问内部类时,内部类必须是静态的。
/*  static class Inner implements Inter
    {
        public void show(){}
    } 
*/
}
//面试题。
class Outer2
{
    public Object()
    {
        public void show(){}
    }.show();//可以编译通过。
    Object obj =new Object()
    {
        public void sho1(){}
    };
    obj.show();//编译失败,因为匿名内部类时子类对象,
               //当被Object指向时,就被提升为Object类型,而Object中没有show()方法,编译失败。
}
class InnerClassDemo7
{
    public static void main(String[] args)
    {
        Outer.method().show();  
        /*
        Outer.method():Outer类中有一个method的方法,这个方法是静态的。
        Outer.method().show():
        能调用show()的必然是对象,
        说明method方法运算完应该返回一个对象,而且能调用Inner中的show方法,说明这个这个对象的类型是:Inter
        */
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值