黑马程序员:java基础知识(二)

来源:互联网 发布:淘宝怎么关闭私人定制 编辑:程序博客网 时间:2024/04/28 16:53

---------------------- ASP.Net+Unity开发、 .Net培训、期待与您交流! ----------------------

三、接口
    接口,是一个特殊的抽象类。定义接口的关键字——interface。
    接口中常见的定义:①常量"static final";②抽象方法 "abstract 方法();"
    接口中不可以创建对象,因为在接口中有抽象方法。当一个子类实现一个接口时,必须实现了该接口的所有方法以后才能创建对象,否则这个子类还是一个抽象类,不可实例化。
    在java中,不支持多继承,但子类可以实现等多个接口。相对于类,接口有一个特殊,就是接口与接口之间可以实现多继承,并且只有接口才可以实现多继承。

    例如:

          class CA{}          class CB{}          class CC extends CA,CB{}  //这种做法是错的,java不支持多继承。                    Interface IA{}          Interface IB{}          Interface IC extends IA,IB{}  //这是正确的,接口可以继承多个接口。
    接口的特点:
    ①接口是对外暴露的规则。比如计算机的主板,它定义了一种规则,只要符合它的规则的产品就可以插到主板上使用。
    ②接口是程序功能的扩展;
    ③接口可以用来多实现;
    ④类与接口之间是实现关系,并且一个类在继承一个类的基础上,可以实现多个接口;
    ⑤接口与接口之间可以有继承关系,并且可以多继承;
    ⑥接口降低了耦合性。
四、多态
    所谓多态,就是事物存在的多种形态。比如,猫就有两种形态,一个是猫,一个是动物。
    1、多态的基本体现:父类的引用指向了子类的对象,父类的引用可以接收子类对象。例:interface IA{}
       class CA implements IA{}
       ....
       IA ia = new CA(); //父类的引用指向子类对象,这就是多态的基本体现。
    2、多态的前提:类与类之间,必须有从属关系,可以是继承,也可以使实现。
    3、多态的好处:使用多态可以大大的提高了程序的扩展性。
    4、多态的弊端:父类的引用只能访问父类中既有的成员。也就是说,在子类中扩展的新成员,使用父类引用是访问不到的。
    5、类型转换:
    类型转换分为向上转型和向下转型。向上转型,也叫做类型提升,就是子类类型转换成父类类型。类似于,char型转换为int型,可以隐式转换。向下转型,就是将父类类型转换为子类类型。类似于,int型转换为char型,需要进行强制类型转换。
    在使用多态时,父类的引用不能访问子类的中特有的成员,所以我们往往需要将父类的引用转换成子类类型。例如:
        Super sp = new Sub();//父类引用指向子类对象
        Sub sb = (Sub)sp;//将父类引用转换成子类类型
    在进行强制类型转换时,切记不能将父类的对象转换成子类类型。多态中,自始至终都是子类对象在做变化。例如:
        Super sp = new Super();        Sub sb = (Sub)sp;//这种做法将会出现类型转换异常:ClassCastException        //在进行类型转换时,下面这种情况也会出现类型转换异常.        class Super{}        class Sub1 extends Super{}        class Sub2 extends Super{}        ……        Super sp = new Sub1();        Sub2 sb2 = (Sub2)sp;//这种类型转换也会出现类型转换异常。    这是什么原因呢?可以这么解释一下,猫和狗都属于动物,想让一只猫强制转换成一条狗,当然是不行的。    那怎样避免出现类型转换异常呢?java中提供了一个关键字——instanceof。该关键字用来判断一个引用变量是否属于某个类型。沿用上面的例子:        Super sp = new Sub1();//父类引用指向了子类Sub1的实例对象        “sp instanceof Sub1” //这个判断将返回true        “sp instanceof Sub2” //这个判断将返回false
    所以在使用强制类型转换时,我们可以利用instanceof来判断引用的类型,避免类型转换异常。即:
         if(sp instanceof Sub1){             Sub1 s1 = (Sub1)sp;         }else if(sp instanceof Sub2){             Sub2 s2 = (Sub2)sp;         }
    6、多态中成员的特点:
    ①非静态成员函数:在编译时期参照引用变量所属类的成员函数,在运行时期参照所创建的对象的成员函数。举例说明:
        class Super{             void print1(){System.out.print("super")}         }        class Sub extends Super{             void print1(){System.out.print("sub1")}              void print2(){System.out.print("sub2")}         }        ……        Super sp = new Sub();        sp.print1();//编译正常通过,因为Super类中有print1这个方法,此处输出的结果是“sub1”,因为print1()方法已经被子类覆盖。        sp.print2();//编译不通过,因为Super类中没有print2这个方法。
    所以,成员函数在多态中,编译时看左边,运行时看右边。
    ②成员变量:无论是在编译时还是运行时,都参照引用变量所属的类(左边)。
    ③静态成员:无论是在编译时还是运行时,都参照引用变量所属的类(左边)。
五、内部类
    1、内部类的访问规则:
    ①内部类可以直接访问外部类的成员,包括私有成员。之所以可以直接访问,是因为内部类中持有了一个外部类的引用:Outer.this
    ②外部类访问内部类,须要创建内部类的对象。
    内部类对象的创建:Outer.Inner io = new Outer().new Inner();
    内部类是外部类的成员,与普通的成员,可以使用成员修饰符修饰。例如,static、final等。
    2、静态内部类:
    静态内部类对象的创建:Outer.Inner io = new Outer.Inner().
    外部类中访问内部类的非静态成员的方式:new Outer.Inner().非静态成员
    外部类中访问内部类的静态成员的方式:Outer.Inner.静态成员
    需要注意的是,①如果内部类中定义了静态成员,则该内部类必须是静态的;②外部类的静态方法不能访问非静态的内部类;③外部类的静态方法可以直接访问静态的内部类。例如:
        class Outer{            static void function(){                Inner.show();//错误的方式                new Inner().show();//这也是错的                new Outer().new Inner().show();//这也是正确的,上面②的说法是错的?但老师是这么说的。            }            class Inner{                void show(){}            }        }
    3、局部内部类:
    类似于局部变量,定义在方法或代码块中。局部内部类不能是静态的;不可以被成员修饰符修饰;他仍然可以直接访问外部类的成员,因为它仍然持有外部类的引用;可以访问该局部中被final修饰的变量,没有被final修饰的变量该内部类不能访问。例:
        class Outer{            void function(){                int x = 1;       //没有final修饰符                final int y = 2; //有final修饰符                class Inner{                    void show(){                        System.out.println(x); //不可以访问                        System.out.println(y); //可以访问                    }                }            }        }
    4、什么时候使用内部类?
    类是对事物的描述,所以当某个事物内部还有事物时,我们就使用内部类来描述。例如,人体是一个事物,也就是一个类,人体内部还有心脏之类的事物,这是人体这一事物的内部事物,所以心脏这一事物就使用内部类来描述。就说,人体是外部类,心脏是内部类。
    5、匿名内部类
    顾名思义,就是没有名字的内部类,是内部类的简写格式。定义一个匿名内部类的前提是,该内部类必须有父类,可以是继承一个类或实现一个接口。
    匿名内部类的定义格式:new 父类或接口(){ 定义子类内容 }; 。其实就是创建了父类或接口的匿名子类对象,而且是一个“带内容”的对象。

    例:

        interface Super{      void show1();      void show2();        }        class Outer{            //方式一:      void function1(){                new Super(){        public void show1(){     System.out.println("show1");        }        public void show2(){     System.out.println("show2");        }         }.show1();//创建了一个匿名内部类,并调用的内部类的方法show1      }            //方式二:      void function2(){                Super sp = new Super(){        public void show1(){     System.out.println("show1");        }        public void show2(){     System.out.println("show2");        }         };//创建了一个匿名内部类,并创建一个接口的引用指向这个匿名内部类。               sp.show1();               sp.show2();      }        }
    上面的两种匿名内部类的创建方式中,方式二更为灵活。从方式二中,我们可以看出,匿名内部类的使用,也是多态的一种体现。但不管哪种方式,内部类必须全部实现父类或接口的抽象方法,因为内部类不能是抽象类。如果父类中的抽象方法太多,那么创建匿名内部类时,就显得很臃肿。所以,当父类或接口中的抽象方法太多时,不建议使用匿名内部类。使用匿名内部类时,内部类中定义的方法最好不要超过3个。


---------------------- ASP.Net+Unity开发、 .Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net


0 0
原创粉丝点击