多态:某一事物的多种存在形态;简单说、就是一个对象对应不同的类型

    例如:对象多态性

    Class 动物{}

    Class 猫 extends 动物{}

    猫 x= new ()

    动物 y= new ()


    猫这类事物即具备猫的形态,又具备动物的形态;这就是对象的多态性

 


 

多态在代码中的体现:父类或者接口的引用指向其子类的对象

 

多态的好处:提高代码扩展性,前期定义的代码可以使用后期的内容(被重写的父类或者接口中的抽象方法)

 

多态弊端:前期定义的内容不能使用(调用)后期子类特有的内容

 

多态的前提:必须有关系(继承 或 实现);要有覆盖(重写父类或接口中的抽象方法)

 

向上转型:自动类型提升,猫对象提升为动物类型,但是特有功能无法访问,作用就是限制对特有功能的访问

 

如果还想用具体动物猫的特有功能,可以将该对象进行进行向下转型

Animal a = new cat()

Cat x = (cat)a

向下转型的目的就是为了使用子类中的特有方法。

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

 

ClassCastException 即为类型转换错误。

 

    /*

    姜先生和姜太公的故事

    */

    class 姜太公

    {

        void 讲课() 

        {

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

        }    

        void 钓鱼()

        {

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

        }

    }

 

    class 姜先生 extends 姜太公

    {

        void 讲课() 

        {

            System.out.println("java");

        }

        void 看电影()

        {

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

        }

    }

    class  BDemo

    {

        public static void main(String[] args) 

        {

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

            /*

            姜先生 x = new 姜先生();

            x.讲课();

            x.看电影();

            */

            姜太公 x = new 姜先生();

            x.讲课();

            x.钓鱼();

 

            x = new 姜尚();

            x.讲课();

            x.钓鱼();

            姜尚 y = (姜尚)x;

            y.吃饭();

            x.讲课();

        }

    }

     class 姜尚 extends 姜太公

    {

        void 讲课() 

        {

            System.out.println("封神榜的好与坏");

        }

        void 吃饭()

        {

            System.out.println("封神榜成就了谁?");

        }

    }

 

可以使用instanceof关键字判断对象的具体类型,只能用于引用类型的判断。通常在向下转型之前,用于健壮性的判断。

    If(a instanceof Cat)

    {

    Cat x = (Cat)a;

    x.catchMouse()

    }

    else if(a instanceof Dog)

    {

    Dog x = (Dog)a;

    X.kengutou();

    }

 

多态时、成员的特点?

成员变量:(作为了解,一般面试用)

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

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

简单说、就是编译和运行均参考向上转型的语句中等号左边

成员函数(非静态):(重点掌握)

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

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

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

静态函数:

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

运行时:参考引用型变量所属的类中是否有调用的函数

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

 

内部类:将一个类定义在另一个类的内部,里面的类就称为内部类

内部类可以直接访问外部类中的成员,包括私有成员

外部类若想访问内部类中的成员,则必须创建内部类的对象

 

内部类一般用于类的设计。分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这时就是还有的事物定义成内部类来描述。

 

内部类修饰符;

在其他类中直接访问外部类中的内部类中的成员,此时需要使用下面的格式来创建:

外部类.内部类  var = new 外部类().new 内部类()//内部类权限必须不能为private

如果内部类是静态的,那就相当于一个外部类。使用下面的格式

外部类.内部类 var = new 外部类.内部类(); //内部类必须不能为private

如果内部类是静态的,成员是静态的。使用如下格式

外部类.内部类.函数名(); //如果内部类中的成员是静态的,则该内部类必须被静态修饰。

 

注意以下代码:

    class Outer

    {

        int num = 3;

        class Inner

        {

            int num = 4;

            void show()

            {

                int num = 5;

                System.out.println(num);

                System.out.println(this.num);

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

            }

        }

        void method()

        {

            new Inner().show();

        }

    }

    class  InnerDemo

    {

        public static void main(String[] args) 

        {

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

            new Outer().method();

        }

    }

    输出结果为 5   4   3


为什么内部类能直接访问外部类中的成员,那是因为内部类持有外部类的引用(外部类名.this

 

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

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

 

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

必须得前提:内部类必须继承或者实现一个外部类或者接口

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

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

    abstract class Demo

    {

        abstract void show();

    }

    class Outer

    {

        public void method()

        {

            new Demo()

            {

                void show()

                {

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

                }

            }.show();

        }

    }

    class  InnerDemo1

    {

        public static void main(String[] args) 

        {

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

            new Outer().method();

        }

    }


匿名内部类应用:

通常的使用场景之一:

当函数参数是接口类型时,而且接口中的方法不超过三个,可以使用内部类作为实际参数进行传递。

interface Inner

{

    void show1();

    void show2();

}

class Outer

{

    public void method()

    {

        Inner in = new Inner()

        {

            public void show1()

            {System.out.println("show1");}

            public void show2()

            {System.out.println("show2");}

        };

        in.show1();

        in.show2();

    }

}

class InnerClassDemo 

{

    public static void main(String[] args) 

    {

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

        new Outer().method();

     }

}

与如下等同,但是实际上均使用如下方式。

interface Inner

{

    void show1();

    void show2();

}

 

class InnerClassDemo 

{

    public static void main(String[] args) 

    {

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

        show(new Inner()

        {

            public void show1()

            {System.out.println("show1");}

            public void show2()

            {System.out.println("show2");}

        });

    }

    public static void show(Inner in)

    {

        in.show1();

        in.show2();

    }

}

 

匿名内部类细节:

class Outer

{

    void method()

    {

        Object obj = new Object()

        {

            public void show()

            {

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

            }

        }

        obj.show(); //此处会调用失败,因为匿名内部类这个子类对象被向上转型为了Object类型,这样就

                    //不能再使用子类特有的方法了。

    }

}