• 黑马程序员---java基础-----多态、内部类、异常、包


    第一讲     多态

            多态可以理解为事物存在的多种体现形态。

            例:动物中猫,狗。猫这个对象对应的类型是猫类型,如:猫 x = new猫();同时猫也是动物中的一种,也可以把猫称为动物。动物  y = new猫();那么动物就是猫和狗具体事物中抽取出来的父类型。父类型引用指向了子类对象。

    一、多态的体现

           1、父类的引用指向了自己子类的对象。

            2、父类的引用也可以接收自己的子类对象。

    如:   Animal a = new Cat();

           其中就将父类型的 a 引用指向了子类的对象。

    二、多态的前提

           1、类与类之间必须有关系,要么继承,要么实现。

            2、存在覆盖。父类中有方法被子类重写。

    三、多态的利与弊

           利:提高了程序的可扩展性和后期可以维护性。

           弊:只能使用父类中的引用访问父类中的成员。也就是说使用了多态,父类型的引用在使用功能时,不能直接调用子类中的特有方法。如:Animal a = new Cat(); 这代码就是多态的体现,假设子类Cat中有特有的抓老鼠功能,父类型的a就不能直接调用。这上面的代码中,可以理解为Cat类型提升了,向上转型。

           如果此时父类的引用想要调用Cat中特有的方法,就需要强制将父类的引用,转成子类类型,向下转型。如:Catc = (Cat)a;

    注:如果父类可以创建对象,如:Animal a = new Animal(); 此时,就不能向下转型了,Cat c = (Cat)a;这样的代码就变得不容许,编译时会报错。所以千万不能出现这样的操作,就是将父类对象转成子类类型。

            我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。多态至始至终都是子类对象在做着变化

    四、多态的特点

    1、多态中非静态成员函数的特点

           在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。

           在运行时期:参阅对象所属的类中是否有调用的方法。这就是说,如果父类中有一个非抽象的方法,而子类继承后又将其复写了,在多态运行时,父类的引用调用这个同名函数时,被运行的将是父类中的方法。

            简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

    2、多态中成员变量的特点

    无论编译和运行,都参考左边(引用变量所属的类)。如:多态中的父类引用调用成员变量时,如果父类和子类有同名的成员变量,那么被调用的是父类中的成员变量

    3、多态中静态成员函数的特点

    无论编译和运行,都参考左边。也就是父类引用在调用静态同名函数时,被调用的是父类中的静态函数。这是因为,当类一被加载,静态函数就随类绑定在了内存中。此时,不需要创建对象,就可以使用类名直接调用。同时,父类中的静态成员函数一般是不被复写的。

    类在方法区中的分配:分为静态区和非静态区,而关键字this和super在非静态区。

    object类----所有对象的父类

    equals:比较的是地址值

     

    第二讲     内部类

    一、概述 

            将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。

            编译时,如果代码中有内部类,生成的class文件中会含有这样的文件:Test$1.class。编译器将会把内部类翻译成用$(美元符号)分隔外部类名和内部类名的常规类文件。这是内部类的一种编译现象。

    二、内部类的访问规则

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

                 之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:  外部类名.this。

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

    三、访问格式

    1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。可以直接建立内部类对象。

           格式:

                    外部类名.内部类名  变量名 =外部类对象.内部类对象;

            如:    Outer.Inner in =new Outer().new Inner();

    当内部类在外部类中的成员位置上时,可以被成员修饰符所修饰。比如:

            private:将内部类在外部类中进行封装。

            static:内部类就局部static的特性。但是当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。

    在外部其他类中,直接访问static内部类的非静态成员的格式为:

            new外部类名.内部类名().方法名();

            如:new  Outer.Inner().function();

    在外部其他类中,直接访问static内部类的静态成员格式为:

            外部类名.内部类名.方法名();

            如:Outer.Inner.function(); 

    注意: 

            1)当内部类中定义了静态成员时,该内部类必须是static的。

            2)当外部类中的静态方法访问内部类时,内部类也必须是static的。

            3)在实际应用中,内部类通常被定义为private,而很少定义为public。

    package atheima;
    
    public class Outer 
    {
        private int x=3;
        //当内部类中定义了静态成员,该内部类必须是static
        static class Inner
        {
            int x=4;
            static void function()
            {
                int x=6;
                //内部类可以直接访问外部类中的成员,包括私有
                System.out.println("inner:"+x);
            }
        }
        void method()
        {
            //外部类要访问内部类,必须建立内部类对象
            Inner n1=new Inner();
            n1.function();
        }
    }
    class InnerClassDemo
    {
        public static void main(String[] args) {
    //        Outer o1=new Outer();
    //        o1.method();
            //直接访问内部类中的成员
    //        Outer.Inner n1=new Outer().new Inner();
    //        n1.function();
            Outer.Inner.function();
        }
    }

    2、内部类定义在局部

            内部类定义在外部类中的某个方法中,创建了这个类型的对象时,且仅使用了一次,那么可在这个方法中定义局部类。

            1)不可以被成员修饰符修饰。如public、private、static等修饰符修饰。它的作用域被限定在了声明这个局部类的代码块中

            2)可以直接访问外部类中的成员,因为还持有外部类中的引用。

    注意:内部类不可以访问它所在的局部中非最终变量。只能访问被final修饰的局部变量。

    package atheima;
    
    public class Outer1 
    {
         int x=3;
         void method(final int a)
         {
             final int y=4;//final修饰的局部变量
            //局部内部类  
             class Inner
             {
                 void function()
                 {
                    // System.out.println(Outer1.this.x);
                     System.out.println(a);
                 }
             }
             new Inner().function();//使用局部内部类中的方法。 
         }
        
    }
    class InnerClassDemo3
    {
        public static void main(String[] args) {
            Outer1 out=new Outer1();
            out.method(7);//打印7 
            out.method(8);//打印8
        }
    }

    注:为什么上面的代码中打印的值为什么会改变呢?被final修饰的变量的值是不会被改变的。这里类调用方法使用完后,这时这个被final修饰的变量已经从栈内存中消失了,类再次调用这个方法时,已经是另一变量,所以可以重新被传值。

    四、匿名内部类

            1、匿名内部类其实就是内部类的简写格式。

            2、定义匿名内部类的前提:

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

                 特殊情况:因为所以的类都有一个父类Object,所以在定义时也可以用Object。

            3、匿名内部类的格式:  new父类或者接口(){定义子类的内容}

            4、其实匿名内部类就是一个匿名子类对象。可以理解为带内容的对象。

            5、匿名内部类中定义的方法最好不要超过3个。

    匿名内部类的利与弊:

            好处:简化书写

            弊端:1、不能直接调用自己的特有方法、

                         2、不能做强转动作。

                         3、如果继承的父类或接口中有很多方法时,使用匿名内部类阅读性会非常差,且调用会很麻烦。所以匿名内部类中定义的方法有一般不超过3个。

    匿名内部类的应用:

    package atheima;
    abstract class AbsDemo
    {
        abstract void show();
    }
    public class Outer2 
    {
        static int x=3;
        static AbsDemo function()
           {
                return new AbsDemo() {        //匿名内部类new 父类或接口        
                    @Override
                   void show() {
                        System.out.println("show:"+x);                                    
                    }
                };
            }
     }
    class InnerClassDemo4
    {
        public static void main(String[] args) {
             Outer2.function().show();
        }
    }

    分析:重点掌握

    Outer2.function().show();相当于AbsDemo in=Outer2.function();in.show();

                                                  //Outer2.function().Outer2类中有一个静态的方法function。

                                                 //.show()  function这个方法运算后的结果是一个对象。而且是一个Outer2类型的对象

                                                //因为只有是Outer2类型的对象,才可以调用method方法。

    第三讲 异常 

    一、概述

            1、异常:就是程序在运行时出现不正常情况。

    二、异常体系

           有两种对问题的划分方式:

                  一种是严重的问题;  一种是非严重的问题。

            对于严重的问题,java通过Error类进行描述。对Error类一般不编写针对性的代码对其进行处理。

            对于非严重的,java通过Exception类进行描述。对于Exception可以使用针对性的处理方式进行处理。

            无论Error或者Exception都具有一些共性内容。比如:不正常情况的信息,引发原因等。

    这也就构成了Java的异常体系:

            Throwable

                    |---Error  //通常出现重大问题如:运行的类不存在或者内存溢出等。

                    |---Exception //运行时出现的一起情况

                                |---R       untimeException    //特殊异常类,抛时不需要声明

            Exception和Error的子类名都是以父类名作为后缀

    三、异常有两种:

            1、编译时被检测异常

                 该异常在编译时,如果没有处理(没有抛也没有try),编译失败。该异常被标识,代表着可以被处理。

             2、运行时异常(编译时不检测)如:RuntimeException以及其子类。

    四、异常的处理语句

    1、 java提供了特有的语句进行处理。

            try

            {

                     需要被检测的代码。

            }

            catch(异常类  对象)

            {

                    处理异常的代码;(处理方式)

            }

            finally

            {

                    一定会执行的语句;

                 catch块使用System.exit(1);除外

            }

    有三个结合格式:

            a、try

                 {

                 }

                 catch ()

                 {

                 }

            b、try

                 {

                 }

                 finally

                 {

                 }

            c、try

                 {

                 }

                 catch ()

                 {

                 }

                 finally

                 {

                 }

    我的总结;

    捕获异常:先捕获小异常再捕获大异常。

    程序是调出来的,不是写出来的;多测试是程序员的必修课。

    异常处理后,程序不会因为出现异常而退出!

    注意:

            1)finally中定义的通常是关闭资源代码。因为资源必须释放。

            2)如果在一个功能中,定义了一些必须要执行的代码,可以用try{}finally{}的方式,将一定执行的代码放在finally代码块中。

            3)finally只有一种情况不会执行。当执行到System.exit(0);---》系统退出。jvm结束。fianlly不会执行。

    2、throw和throws的区别

            throw定义在函数内,后面跟的是异常对象

            throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。

            当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,否则编译失败。

            注意:RuntimeException除外。也就说,函数内如果抛出的RuntimeExcpetion异常,函数上可以不用声明。如果函数声明了异常,调用者需要进行处理,处理方法可以throws可以try。

    如下代码:

    package atheima;
     class aa{
    public static void main(String[] args) {
            try {
                  fn1(1);
            } catch (Exception e) 
            { e.printStackTrace(); 
            }
            fn2(2);
        }
        public static void fn1(int a) throws Exception{
            if(a >0) { throw new Exception("fn1 -- a值不合法"); }
        }
        public static void fn2(int a) {
            if(a >0) { throw new RuntimeException("a值不合法"); }
        }
    }

    3、调用者对抛出信息的处理

            当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。要么在内部try catch处理。要么在函数上声明让调用者处理。

            一般情况下,函数内出现异常,函数上需要声明。在功能上通过throws的关键字声明了该功能有可能会出现异常类型。

    特殊之处:

            Exception中有一个特殊的子类异常RuntimeException运行时异常。

                    1) 如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。

                    2)如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过。

             如果函数声明了异常,调用者需要进行处理。处理方法可以throws可以try。

    对捕获到的异常对象进行常见方法操作:

            String getMessage();//获取异常的信息。返回字符串。

            toString();//获取异常类名和异常信息,返回字符串。

            printStackTrace();//获取异常类名和异常信息,以及异常出现在程序中的位置.返回值void.                      

            printStackTrace(PrintStream s)//通常用该方法将异常内容保存在日志文件中,以便查阅。

    五、自定义异常

           因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对这些特有的问题可以按照java中的面向对象思想。将特有的问题,进行自定义的异常封装。

    定义类继承Exception或者RuntimeException

            1,为了让该自定义类具备可抛性。

            2,让该类具备操作异常的共性方法。

            要定义自定义异常的信息时,可以使用父类已经定义好的功能。异常信息传递给父类的构造函数。如下:

    class NoValueException extends RuntimeException
    {
        public NoValueException(String message) 
        {
            super(message);
        }
    }

    因为父类中已经把异常信息的操作都完成了。所以子类只要在构造时,将异常信息传递给父类通过super语句。那么就可以直接通过getMessage方法获取自定义的异常信息。

    自定义异常:  必须是自定义类有继承关系,通常继承Exception。

            继承Exception原因:

                    异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。

                    只有这个体系中的类和对象才可以被throws和throw操作。

    异常在子父类覆盖中的体现:

    1、子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。

    2、如果父类方法抛出多个异常,那么子类再覆盖该方法时,只能抛出父类异常的子集

    3、如果父类或者接口的方法中没有异常抛出,那么子类再覆盖方法时,只能try不能抛出异常。

    六、异常的好处与原则

    好处:

           1、将问题进行封装。

            2、将正常流程代码和问题处理代码相分离,方便于阅读。

    原则:

            1、处理方式有两种:try或者 throws。

            2、调用到抛出异常的功能时,抛出几个,就处理几个。一个try对应多个catch。

            3、多个catch时,父类的catch放到最下面。否则编译会报错,因为其余的catch语句执行不到。

            4、catch内,需要定义针对性的处理方式。不要简单的定义printStackTrace,输出语句。也不要不写。当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。

    try{throw new AException();}

    catch(AException e){throw e;}

    5、如果异常处理不了,但并不属于该功能出现的异常,可以将异常转换后,在抛出和该功能相关的异常。

    try{throw new AException();}

    catch(AException e){throw new BException();}

    6、或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,当调用者知道。并处理。也可以将捕获异常处理后,转换新的异常。

    第四讲     包

    一、package       

            包也是一种封装形式。在包中可以有很多类文件,但是只提供一个类文件,供外界使用。

    二、包的作用

            1、为避免多个类重名的情况,如果出现两个相同名字的类,可通过包将两者区分,从而避免冲突。

            2、对类文件进行分类管理,可以将相关的一些类放在同一个包中。

            3、给类提供多层命名空间,如a包中的Demo.class文件,如果要创建Demo对象,就要在使用时加上a.如:a.Demo demo=new a.Demo();

            4、包的出现可以将java的类文件和源文件相分离。

            2、类的全称:包名.类名。

            3、编译定义了包的程序文件时,在编译时要指定包的存储目录。

           如:javac –d c:mypack类名.java

    四、包之间的访问     

            4、类中的成员权限:public或者protected。protected是为其他包中的子类提供的一种权限。类公有后,被访问的成员也要公有才可以被访问。不同包中的子类可以直接访问父类中被protected权限修饰的成员。同一个包中,protected只作用为覆盖。

    四种权限

     

    public

    protected

    defauld

    Private

    同一类中

    可以

    可以

    可以

    可以

    同一包中

    可以

    可以

    可以

    不可以

    子类

    可以

    可以

    不可以

    不可以

    不同包中

    可以

    不可以

    不可以

    不可以

    注:一个.java文件里面,不能出现两个以上的公有类或者接口。因为被public修饰的类名必须与java文件名相同。

    五、包的导入——import

            1、可以简化类名。在调用其他包中的类时,需要写类的全称,也就是连同包名一起书写。当类存在多层包中时,如:haha.hehe.pack.Demo,使用import导入后,使用其类时,就可以不加包名了。导入格式如:import haha.hehe.pack.Demo;

            2、一个程序文件中只有一个package,可以有多个import。import导入的是包中的类,不导入包中的包。

  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/Hanxia/p/4493249.html
Copyright © 2020-2023  润新知