day10_java多态+内部类+匿名内部类

来源:互联网 发布:windows 64位激活码 编辑:程序博客网 时间:2024/06/07 13:03

面向对象(多态-概述)


多态:

你只要看到父类引用指向子类对象的表现形式,那么它就体现了多态的特点了

 

对象的多态性。

 

class 动物

{}

 

class 猫extends 动物

{}

 

class 狗extends 动物

{}

猫 x = new 猫();

 

动物 x = new 猫();//一个对象,两种形态。

 

猫这类事物即具备者猫的形态,又具备着动物的形态。

这就是对象的多态性。

 

简单说:就是一个对象对应着不同类型.

 

多态在代码中的体现:

    父类或者接口的引用指向其子类的对象。

 

面向对象(多态-好处)

举个例子:

多态的好处:

    提高了代码的扩展性,前期定义的代码可以使用后期的内容。

   这里面的前提可以这么去理解就是:父类里面的内容就是前提,后期就是子类里面的内容,但是这个子类里面的内容必须不是子类所特有了,而是父类继承过来的内容

abstract class Animal

{

    abstract void eat();

}

class Dog extends Animal

{

    void eat()

    {

        System.out.println("啃骨头");

    }

    void lookHome()

    {

        System.out.println("看家");

    }

}

class Cat extends Animal

{

    void eat()

    {

        System.out.println("吃鱼");

    }

    void catchMouse()

    {

        System.out.println("抓老鼠");

    }

}

class Pig extends Animal

{

    void eat()

    {

        System.out.println("饲料");

    }

    void gongDi()

    {

        System.out.println("拱地");

    }

}

class DuoTaiDemo

{

    public static void main(String[] args)

    {

       

//      Cat c = new Cat();

//      c.eat();

 

        /*

        Cat c = new Cat();

 

//      Dog d = new Dog();

 

//      c.eat();

        method(c);

//      method(d);

//      method(new Pig());

        */

 

        method(new  Dog());

 

}

Public static void method(Animal a)

{

A.eat();

}

 

/*

    public static void method(Cat c)

    {

        c.eat();

    }

    public static void method(Dog d)

    {  

       

    }

    */ 

}

 

 

面向对象(多态-弊端&前提)

 

多态的弊端:

    前期定义的内容不能使用(调用)后期子类的特有内容。

 

多态的前提:

    1,必须有关系,继承,实现。

    2,要有覆盖。

 

面向对象(多态-转型

 

//      Cat c = new Cat();

//      c.eat();

//      c.catchMouse();

 

        Animal a = new Cat();//自动类型提升,猫对象提升了动物类型。但是特有功能无法s访问。

                            //作用就是限制对特有功能的访问。

                            //专业讲:向上转型。将子类型隐藏。就不用使用子类的特有方法。

 

 

//      a.eat();

 

        //如果还想用具体动物猫的特有功能。

        //你可以将该对象进行向下转型。

//      Cat c = (Cat)a;//向下转型的目的是为了使用子类中的特有方法。

//      c.eat();

//      c.catchMouse();

 

//      注意:对于转型,自始自终都是子类对象在做着类型的变化。

//      Animal a1 = new Dog();

//      Cat c1 = (Cat)a1;//ClassCastException

 

 

面向对象(多态-转型2)

事例:

/*

毕老师和毕姥爷的故事。

*/

 

class 毕姥爷

{

    void 讲课()

    {

        System.out.println("管理");

    }

    void 钓鱼()

    {

        System.out.println("钓鱼");

    }

}

 

class 毕老师 extends 毕姥爷

{

    void 讲课()

    {

        System.out.println("Java");

    }

    void 看电影()

    {

        System.out.println("看电影");

    }

}

class  DuoTaiDemo2

{

    public static void main(String[] args)

    {

//      毕老师 x =new毕老师();

//      x.讲课();

//      x.看电影();

 

        毕姥爷 x = new 毕老师();

        x.讲课();

        x.钓鱼();

 

    //  毕老师 y = (毕老师)x;//ClassCastException

    //  y.看电影();

    }

}

重点:

容易出错:

结果为

Java

钓鱼

面向对象(多态-类型判断-instanceof)

 

public static void method(Animal a)//Animal a = new Dog();

    {

        a.eat();

 

        if(a instanceof Cat)//instanceof:用于判断对象的具体类型。只能用于引用数据类型判断,这里面的具体类型还可以是接口名称或者是类都是可以的

//                      //通常在向下转型前用于健壮性的判断。

 

        {

            Cat c = (Cat)a;

            c.catchMouse();

        }

        else if(a instanceof Dog)

        {

            Dog d = (Dog)a;

            d.lookHome();

        }

        else

        {

       

        }

       

    }

面向对象(多态-成员变量)

事例:

多态时,

成员的特点:

1,成员变量。

    编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。

    运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。

    简单说:编译和运行都参考等号的左边。哦了。

    作为了解。

 

class Fu{

  

intnum = 3;

voidshow()

{

System.out.println("Fushow");

}

 

}

class zi extends Fu

{

int  num = 4;

void  show()

{

    System.out.println("zi show");

}

}

class DuoTaiDemo3

{

publicstatic void main(String[] args)

{

 Fu f = new Zi();

 System.out.println(f.num);

结果:3

为什么会是3也

原因分析:我就new一个子类对象吧,一创建就是两个num,创建完过后,子类已经提升为父类型了,你用父类型的引用去找这个num的时候,它会找父的,覆盖只发生在函数上

 

另外一个情况:当我注释intnum=3的时候也,再执行语句就会报错

 

F.show();

会打印出什么也是:zi show,因为会存在覆盖

同样把上面的show方法去掉,然后就调用f。Show就会报错,因为父类中没有这个方法吗,所以也会报错

}

}

 

面向对象(多态-成员函数)

面向对象(多态-静态函数)

/*

多态时,

成员的特点:

1,成员变量。

    编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,                                  编译失败。

    运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成           员变量。

    简单说:编译和运行都参考等号的左边。哦了。

    作为了解。

 

2,成员函数(非静态)。

    编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译           失败。

    运行时:参考的是对象所属的类中是否有调用的函数。

    简单说:编译看左边,运行看右边。

 

    因为成员函数存在覆盖特性。

3,静态函数。

        编译时:参考引用型变量所属的类中的是否有调用的静态方法。

        运行时:参考引用型变量所属的类中的是否有调用的静态方法。

        简单说,编译和运行都看左边。

 

        其实对于静态方法,是不需要对象的。直接用类名调用即可。

*/

 

class Fu

{

//  int num = 3;

    void show()

    {

        System.out.println("fu show");

    }

 

    static void method()

    {

        System.out.println("fu static method");

    }

}

 

class Zi extends Fu

{

//  int num = 4;

    void show()

    {

        System.out.println("zi show");

    }

 

    static void method()

    {

        System.out.println("zi static method");

    }

}

class  DuoTaiDemo3

{

    public static void main(String[] args)

    {

        Fu.method();

        Zi.method();

        Fu f = new Zi();//

//      f.method();

//      f.show();

//      System.out.println(f.num);

 

 

//      Zi z = new Zi();

//      System.out.println(z.num);

    }

}


面向对象(内部类-概述)

面向对象(内部类-修饰符)


/*

内部类访问特点:

1,内部类可以直接访问外部类中的成员。

2,外部类要访问内部类,必须建立内部类的对象。

 

 

用于类的设计。

 

分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。

这时就是还有的事物定义成内部类来描述。

 

*/

class Outer

{

    private static int num = 31;

 

    class Inner//内部类。

    {

        void show()

        {

            System.out.println("show run..."+num);

        }

        /*static voidfunction()//如果内部类中定义了静态成员,该内部类也必须是静态的。为什么也,因为如果有静态的也是不是随着类的加载而加载,随着类的消失而消失,我们就不需要再创建对象了吧,所以我们直接用外部类。内部类点上就可以了,可是如果你不弄成静态的话也,你这个类是非静态的,它不加载进来的话也,你这个外部类就不能再是外部类。内部类了

        {

            System.out.println("function run ...."+num);

        }

        */

    }

 

    public void method()

    {

        Inner in = new Inner();

        in.show();

    }

}

 

 

class InnerClassDemo

{

    public static void main(String[] args)

    {

//      Outer out = new Outer();

//      out.method();

        //直接访问外部类中的内部类中的成员。

//      Outer.Inner in = newOuter().new Inner();

//      in.show();

 

        //如果内部类是静态的。 相当于一个外部类

//      Outer.Inner in = newOuter.Inner();

//      in.show();

 

        //如果内部类是静态的,成员是静态的。

//      Outer.Inner.function();

       

    }

}

 

面向对象(内部类- 细节)

/*

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

那是因为内部类持有了外部类的引用。  外部类名.this

 

*/

class Outer

{

    int num = 3;

    class Inner

    {

        int num = 4;

        void show()

        {

            int num = 5;

            System.out.println(Outer.this.num);

        }

    }

    void method()

    {

        new Inner().show();

    }

}

 

 

class InnerClassDemo2

{

    public static void main(String[] args)

    {

        new Outer().method();

    }

}

 

面向对象(内部类-局部内部类)


这里面为什么要加final呢,不就是在局部吗:

/*

内部类可以存放在局部位置上。

内部类在局部位置上只能访问局部中被final修饰的局部变量。

*/

 

 

class Outer

{

    int num = 3;

    Object method()

    {

 

        final int x = 9;

 

        class Inner

        {

            public String toString()

            {

                return "show ..."+x;

            }

        }

 

        Object in = new Inner();

        return in;//0x0045

//      in.show();

    }

 

 

   

}

 

class InnerClassDemo3

{

    public static void main(String[] args)

    {

        Outer out = new Outer();

        Object obj = out.method();

        System.out.println(obj);

 

    }

}

上面这句Object obj = out.method();方法一调用是不是返回一个地址,0x0045,赋值给了obj,这个时候 这个method方法运算完了是不是出栈了,方法一出栈x没有了吧,我们这个ox0045这个对象是不是还在也,就是这个Inner()对象,因为我是obj指向了这个Inner()对象的吧,obj所指向的话也是不是意味着这里面的方法都在栈内存中啊,你说要是这种情况的话x就不能访问了

 

那你如果在method内部内中Inner里面的toString方法去访问变量x就不存在了,所以也访问不到,所以也加final修饰成为常量,你加了常量就解决问题了啊,final修饰完x是一个常量 ,这个常量啊就意味着x在这里面终生为9,是固定值,它不会变化

 

说明:这其实也是一种规则你只要记住就行了

 

 

面向对象(匿名内部类-概述)

 

/*

匿名内部类。就是内部类的简写格式。

   

    必须有前提:

    内部类必须继承或者实现一个外部类或者接口。

 

匿名内部类:其实就是一个匿名子类对象。

 

格式:new 父类or接口(){子类内容}

 

*/

 

abstract class Demo

{

    abstract void show();

}

 

class Outer

{

    int num = 4;

    /*

    class Inner extends Demo

    {

        void show()

        {

            System.out.println("show ..."+num);

        }

    }

    */

    public void method()

    {

        //new Inner().show();

        new Demo()//匿名内部类。

        {

            void show()

            {

                System.out.println("show ........"+num);

            }

        }.show();

    }

}

class InnerClassDemo4

{

    public static void main(String[] args)

    {

        new Outer().method();

    }

}

 

面向对象(匿名内部类-应用)

interface Inter

{

    void show1();

    void show2();

}

 

class Outer

{

    /*

    class Inner implements Inter

    {

        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 InnerClassDemo5

{

 

    class Inner

    {

    }

    public static void main(String[] args)

    {

        System.out.println("Hello World!");

        /*

        show(new Inter()

        {

            public void show1(){}

            public void show2(){}

        });

        */

 

//      new Inner();

    }

 

    public void method()

    {

        new Inner();

    }

 

    public static void show(Inter in)

    {

        in.show1();

        in.show2();

    }

}

 

匿名内部类-细节


分析原因:

主函数是静态的,classInner这个是不是成员啊,这个成员是非静态的吧,静态的不能访问非静态的吧

 

现在说一个问题哈,一般人都挂



class Outer

{

    void method()

    {

        Object obj = new Object()

        {

            public void show()

            {

                System.out.println("show run");

            }

 

        };

        obj.show();//因为匿名内部类这个子类对象被向上转型为了Object类型。

                    //这样就不能在使用子类特有的方法了。

 

 

    }

}

 

class InnerClassDemo6

{

    public static void main(String[] args)

    {

        new Outer().method();

    }

}

 

面向对象(对象的初始化过程)\



接着上面写

public static void main(String[] args)

{

new Zi();

}
猜猜输出结果

show zii......0

zi construct....9

事例2:






什么时候使用匿名内部类呢?

通常在使用方法是接口类型参数,并该接口中的方法不超过三个时,可以将匿名内部类作为参数传递。

增强阅读性。

 

 


0 0
原创粉丝点击