黑马程序员——面向对象

来源:互联网 发布:软件测试系统 编辑:程序博客网 时间:2024/04/28 18:00

---------------------- android培训java培训、期待与您交流! ----------------------

 

一、面向对象
   (一)面向对象概念
       1、理解面向对象
        面向对象是相对面向过程而言的,现象对象和面向过程都是一种思想。面向过程强调的是功能行为;面向对象是将功能封装进对象,强调具备了功能的对象,面向对象是基于面向过程的。
        2、面向对象的三大特征:
         封装、继承、多态。对象用于封装数据。用new关键字在堆内存中创建对象实体。
   (二)类与对象的关系
         1、类就是对现实生活中事物的描述。对象就是这类事物实实在在存在的个体。类是对具体对象的共性的抽象抽取。调用对象成员的方式:对象.对象成员。
         2、成员变量:作用于整个类中;局部变量:作用于函数中或语句中。成员变量存储在堆内存中,因为对象的存在,才在内存中存在;局部变量存储在栈内存中。
         3、匿名对象
            匿名对象是对象的简化形式,匿名对象有两种使用情况:a.当对对象方法仅进行一次调用时。b.匿名对象可以作为实际参数进行传递。
   (三)封装(encapsulation)
        1、封装是指隐藏对象属性和实现细节,仅对外提供公共访问方式。
        2、封装的优点:将变化隔离,便于使用,提高重用性,提高安全性。
        3、封装的原则:将不需要对外提供的内容都隐藏起来。把属性都隐藏提供公共方法对其访问。
         4、private(私有):权限修饰符,用于修饰类中的成员(成员变量,成员方法)。私有只在本类中有效。私有仅仅是封装的一种体现形式。         
   (四)构造函数
        1、特点:函数名与类名相同;不用定义返回值类型;不可以写return语句。
        2、作用:给对象进行初始化。对象一建立就会调用与之对应的构造函数。
        3、当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数。当在类中自定义了构造函数后,系统就不默认构造函数了。
        4、构造函数和一般函数的不同:构造函数和一般函数不仅在写法上有一定的区别,而且在运行上也有不同:构造函数是在对象一建立就运行,给对象初始化,一个对象建立,构造函数只运行一次;而一般方法当对象调用时才执行,是给对象添加对象应具备的功能并且一般方法可以被对象调用多次。
         5、构造函数的建立:当分析事物时,该事物一存在就具备的一些特性或者行为,那么就将这些内容定义在构造函数中。
         6、构造代码块:定义的是所有对象的共性,是给所有对象进行统一的初始化,对象一建立就运行,且在构造函数之前运行。构造函数是给指定对象初始化。
   (五)this关键字
         1、this区分成员变量和局部变量。this代表所在函数所属对象的引用。简单的说:那个对象调用this所在的函数,那么this就代表这个对象。this是对象的引用,当定义类中功能时,该函数内部要用到调用该函数的对象时,就用this代表这个对象。
          2、this在构造函数互相调用时的应用:
           事例:class person
                     {
                        person(string name)
                           {
                              this.name=name;
                            }
                         person(string name,int age)
                             {
                                this(name);//this.name=name;this语句调用上个构造//方法.
                                
                                 this.age=age;
                                }
                      }
           注意:构造函数间的调用只能用this且传给相应的参数,this语句只能定义在构造函数的第一行。因为初始化动作要先执行。
                       
   (六)static关键字
        1、static 用于修饰成员(成员变量和成员函数)不能修饰局部,被修饰后的成员具备以下特点:随着类的加载而加载;优先于对象存在;被所有对象所共享;可以直接被类名调用:类名.静态成员。
         2、使用注意:
          静态方法只能访问静态成员;静态方法中不可以写this,super关键字;主函数是静态的。非静态的既可以访问静态的也可以访问非静态的。
          3、实例变量和类变量的区别:
           a.存放位置:类变量随着类的加载而存在于方法区中;实例变量随着对象的创建而存在于堆中。
           b.生命周期:类变量生命周期最长,随着类的消失而消失;实例变量生命周期随着对象的消失而消失。]
          4、什么时候定义静态变量(成员变量也就是类变量)?
          当对象中出现共享数据时,该数据被静态所修饰。对象中的特有数据定义成非静态存放在堆内存。
           5、什么时候定义静态函数呢?
            当函数内没有访问到非静态数据(对象的特有数据)时,那么该函数可以定义成静态的。
           6、程序说明书的制作
              对每一个功能都用文档注释说明,用一个工具抽取文档,这个工具就是javadoc。(javadoc -d myhelp -author -version Arraytool.java)。注意:要提取的这个类必须用public修饰。
             7、静态代码框格式
                static
                     {
                        静态代码框中的执行语句;
                      }
                静态代码框随着类的加载而执行且只执行一次,优先于主函数执行,用于给类进行初始化。
          事例:class StaticCode
                   static
                     {
                       System.out.println("a");
                      }
                   class StaticCodeDemo
                      {
                          static
                               {
                                     System.out.println("b");
                                }
                          public static void main(String[] args)
                             {
                               new StaticCode();
                               new StaticCode();   
                             }
                           static
                               {
                                     System.out.println("c");
                                }

                       }//执行的结果是:b c a(为什么只有一个a呢?
因为静态代码框在类加载的时候只执行一次,后边调用时类已经在内存中了,所以静态代码框也就不执行了)。
   (七)单例设计模式
        1、设计模式:解决某一类问题最行之有效的方法。java中有23中设计模式。
        2、单例设计模式一
        先初始化对象,称为:饿汉式
  事例:
/*
要想保证对象唯一:
 1、为了保证其他程序过多建立该类的对象,先禁止其他程序建立该类对象。(将构造函数私有化)
 2、还为了让其他程序可以访问该类对象,只好在本类中自定义一个对象。(在类中创建一个本类对象)
 3、为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。(提供以一个方法可以获取该对象)

*/
     class Single
      {
          private Single(){}
          private static single s= new single();
          public static Single getInstance()
                    {
                       return s;
                     }
         }
      class SingleDemo
          {
               public static void main(String[] args)
                  {
                        Single ss=Single.getInstance();
                  }
            }
     3、单例设计模式二
      对象是在方法被调用时,才初始化,也叫做对象的延时加载。称为:懒汉式。
  
            class Single
              {
                   private static Single s=null;
                   private Single()}{}
                   public static Single getInstance()
                     {
                        if(s==null)
                                s=new Single();
                           return s;
                        }
               }
             class  SingleDemo
                    {
                        public static void main(String[] args)
                               {
                                  Single ss=Single.getInstance();
                                 }
                     }

          (八)继承(extends)
            1、继承的特点:
            提高了代码的复用性;让类与类之间产生了关系,有了这个关系,才有了多态的特性。在java语言中只支持单继承,不支持多继承,因为多继承容易带来安全隐患(当多个父类中定义了相通的功能,但功能内容不同时,不确定要运行哪一个)。java支持多层继承,也就是一个继承体系。
            2、子父类中成员的特点:
             变量:如果子父中出现了非私有的同名变量时,子类要访问本类中的变量用this;子类要访问父类中的同名变量用super。super和this的用法几乎一样。this代表子类对象的引用,super代表父类对象的引用。
             函数:当子类和父类出现一模一样的函数时,子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这种情况是函数的另一种特性:重写(覆盖)。继承中覆写的特性可以拓展程序的功能。
            注意:子类覆盖父类必须保证子类的权限大于等于父类的权限。静态只能发、覆盖静态。
              构造函数:在子类对象初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式的语句super()。super()会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super()。
              3、子类访问父类构造函数的原因:
                因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据初始化的。所以子类在对象初始化时,要先访问以下父类中的构造方法。如果要访问父类中自定义的构造方法,可以通过手动定义super语句的方式来指定。注意:super语句一定定义在子类构造函数的第一行。
               4、结论:
                  子类中所有的构造函数默认都会访问父类中空参数的构造方法;因为子类的每一个构造方法的第一行都有默认的隐式语句super();当父类中没有空参数的构造方法时,子类必须手动通过supe()语句形式访问类中的构造函数。当然子类的构造函数第一行也可以手动指定this()语句来访问本类中的构造函数,但子类中至少有一个构造函数会访问父类中的构造函数。                          
         (九)final关键字
             final可以修饰类、方法、变量(成员变量和局部变量);final修饰的类是不可被继承;final修饰的方法不可以被覆盖;final修饰的变量是一个常量,只能赋值一次;内部类只能访问被final修饰的局部变量。
          (十)抽象类
            当多个类中出现相同功能,但功能主体不同,这是可以进行向上抽取。这时只抽取功能定义,而不抽取功能主体。抽象类的特点:抽象方法一定定义在抽象类中,抽象方法和抽象类都被abstract关键字修饰;抽象类不可以用new创建对象,因为没有意义;抽象类中的方法要被使用,必须有子类覆写所有的抽象方法后,建立子类对象调用;如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类;抽象类中即可有抽象类也可以有非抽象类。抽象类中可以不定义抽象方法,这种作用仅仅用于不让该类创建对象。
      抽象类事例:
            class Employee
            {
                  private string name;
                  private string id;
                  private double pay;
                   Employee(string name,string id,double pay)
                      {
                            this.name=name;
                            this.id=id;
                             this.pay=pay;
                      }
                   public abstract void work();
              }
            class Manager extends Employee
              {
                private int bonus;
                Manager(string name,string id,double pay,int bonus)
                        {
                           super(name,id,pay);
                            this.bonus=bonus;
                         }
                 public void work()
                    {
                          System.out.println("manager work");
                      }
              }
             class Pro extends Employee
               {
                   class Pro(string name,string id,double pay)
                        {
                           super(name,id,pay);
                         }
                   public void work()
                       {
                             System.out.println("Pro work");
                        }
                 }
                public class  AbstactDemo
                      {

                         public static void main(String[] args)
                                {
                                Manager man=new Manager(zhansan,01,100.00,400 );
                                    Pro p=new Pro(lisi,05,200.00);
                                    man.work();
                                    p.work();
                                  }
                      }
           (十一)模板方法
             在定义功能时,功能一部分是确定的,另一部分功能是不确定的,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去,由该子类去完成。
            (十二)接口
                  1、接口的格式:interface{}
                  2、接口中的成员修饰符是固定的:成员变量:public static final
                    成员函数 :public abstract
                  3、接口的出现将“多继承”通过另一种形式体现出来,即“多实现”
                  4、implements  关键字,用于类实现接口。
                  5、一个类在继承一个类的同时还可以实现多个接口。
                  6、接口与接口之间也有继承关系。接口与接口之间也可能有多继承。
            (十三)接口的特点
                 接口是对外暴露的规则;接口是程序的功能扩展;接口可以用来多实现;类与接口之间是实现关系,而且类可以在继承一个类的同时实现多个接口;接口与接口之间可以有继承关系,而且在特殊情况下接口与接口之间可以有多继承关系。            

二、多态
   定义:某一类事物多种存在形态.提高了代码的扩展性。
   (一)多态的体现形式
        父类的引用指向了自己的子类对象;父类的引用也可以接收自己的子类对象。
   (二)多态的好处
        多态的出现大大的提高了程序的扩展性。
   (三)多态的前提
        必须是类与类之间有关系,要么继承,要么实现。通常还有一个前提:存在覆盖。
    (四)多态的弊端
       提高了扩展性,但是只能使用父类的引用访问父类中的成员。
     (五)多态-转型
         向上转型:父类的引用指向子类的对象。向下转型:强制把父类的引用转成子类类型。
     (六)instanceof关键字
          判断一个引用是否为指定类型。
      (七)在多态中非静态成员函数的特点:(非多态绑定)
         在编译时期:参阅引用类型变量所属的类中是否有编译方法,如果有编译通过,如果没有编译失败。
         在运行时期:参阅对象所属的类中是否有调用方法。
          结论:成员函数在多态调用时,编译看左边,运行看右边。
        (八)在多态中成员变量的特点
            无论编译和运行,都参考左边(引用类型所属的类)。
         (九)在多态中静态成员函数的特点
             无论是编译还是运行,都参考左边。(静态绑定)
         事例:模拟电脑
                 interface PCI
                   {
                      public void open();
                      public void close();
                   }
                  class MainBoard
                       {
                         public void run()
                                  {
                                     System.out.println("run");
                                   }
                         public void usePCI(PCI p)//多态,接口的引用指向接口对象
                                 {
                                      if(p!=null)
                                             {
                                                p.open;
                                                p.close;       
                                              }
                                  }
                             
                        }
              (十)Object 类
                   类Object 是类层次结构的根类,每个类都是用Object作为超类。所有对象(包括数组)都实现这个类的方法。
三、内部类
    (一)定义
    将一个类定义在另一个类的里边。把里边的那个类就成为内部类(内置类、嵌套类)。
    (二)访问特点:
       内部类可以直接访问外部类的成员,包括私有成员(是因为内部类持有了一个外部内的引用,格式:外部类名.this)。而外部类要访问内部类的成员必须要建立内部类的对象。
     事例:class outer
            {
               private int x=3;
                class inner//内部类
                   { 
                     void function()
                      {
                     System.out.println("inner:"+x);//x 之前省略了outer.this x
                        }
                   }
                 void method()
                    {
                       inner in=new inner();//建立内部类的对象
                       in.function;
 
                     }
              }
        class OutInterDemo()
               {
                  public static void main(String[] args)
                        {
                              outer out = new outer();//通过外部内的对象调用内部类的方法
                              out.method;
                               //outer.inner in=new outer().new inner();
                               //in.function;//直接访问内部类的成员
                        }
                }
        技巧:1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象,格式为:外部类名.内部类名 变量名 = 外部对象.内部对象
                          outer.inner in=new outer().new inner();
        (三)静态内部类
             事例:class outer
                        {

                          private static int x = 3;
                           static class inner//静态内部类
                                 {
                                    void function()
                                            {
                                            System.out.println("inner:"+x);
                                             }
                                  }
                          }
                    class InnerClassDemo
                             {
                                 public static void main(String[] args)
                                     {//当静态内部类的成员非静态时,调用成员的方法
                                         new outer.inner().function();
                                      //当静态内部类的成员也静态时,调用成员的方法
                                        outer.inner.function()
                                      }
                              }
              技巧:当内部类在成员位置上,就可以被成员修饰符所修饰,比如,private:将内部类在外部类中进行封装。static:使内部类具有static的特性,当内部类被static修饰后,就只能访问外部类中的static成员,出现了访问受限。
               在外部其他类中,如何访问静态内部类的非静态成员呢?
                  格式: new outer.inner().function()
               在外部其他类中,如何访问静态内部类的静态成员呢?
                  格式:outer.inner.function()
              注意:当内部类中定义了静态成员,那么该内部类也必须是静态的。
                    当外部内的静态方法要访问内部类时,该内部类也必须是静态的。
        (四)局部内部类
            事例:class outer
                  {
                    int x=3;
                    void method()
                      { 
                          final int y=4
                           class inner//局部内部类,相当于局部变量,它不能被成员                                        //修饰符所修饰
                                {
                                  void function()
                                      {
                                         System.out.println(y);//y必须使用final修饰
                                       }
                                 }
                             new inner().function();
                       }
                             
                  }
                注意:局部内部类不可以被成员修饰符修饰;可以直接访问外部内中的成员,因为还持有外部内中的引用outer.this;但是不可以访问他所在局部中的局部变量,只能访问被final修饰的局部变量。
            (五)匿名内部类
               匿名内部类其实就是内部类的简写格式。定义匿名内部类的前提是:内部类必须继承一个类或实现接口。
              事例:abstract class AbsDemo
                       {
                           abstract void show();
                      }
                     class outer
                        {
                             public void function()
                                    {
                                         new AbsDemo()//匿名内部类
                                           {
                                              void show()
                                                      {
                                                        System.out.println("x="+x);
                                                      }
                                            }.show();//用匿名内部类调用内部类的方                                                          法
                                     }
                         }
                  1、匿名内部类的格式:new 父类或者接口(){定义子类内容}
                  
                    2、匿名内部类其实就是匿名的子类对象,可以理解为带内容的对象。  
                 
                   3、匿名内部类可以作为对象的实际参数传递。  
四、异常
      (一)异常就是程序在运行时出现的不正常情况。
       (二)异常的由来:问题也是现实生活中的一个具体事物,也可以通过java的类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的体现。
        (三)问题的划分
           问题可以分为两种:一种是严重的问题,java通过Error类进行描述。另一种非严重的问题,javaException类进行描述。对于Error一般不编写针对性的代码进行处理。对于Exception可以使用针对性的处理方式进行处理.
         (四)异常的处理
            1、 java提供了特有的语句进行处理
               try
                {
                  需要被检验的代码;
                 }
               catch(异常类 变量)
                  {
                   处理异常的代码;(处理方式)
                  }
                finally
                   {
                     一定会执行的语句;
                    }
       注意:catch适用于处理异常的,如果没有catch就代表着异常没有被处理过,如果该异常是检测时异常,那么必须声明该异常。
            (五)异常的声明
                 1、在功能上声明:throws Exception
                  事例:class  Demo
                           {//声明异常
                              int div(int a,int b)throws Exception
                                 {return a/b;}
                            }
            (六)自定义异常
                 因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java对问题的封装思想将特有问题,进行自定义的描述。
           事例:自定义异常对象:
                   class FuShuException extends exception//自定义异常必须继承Exception。因为异常体系有一个特点:因为异常类和异常对象都被抛出,它们都具备可抛性,这个可抛性是Throwable这个体系中独有的特点。只有这个体系中的类和对象才可以被throws和throw操作。
                      {
                            FuShuException(String message)
                                 {
                                      //super(message);//父类已经定义过了不必自己                                                              再定义了
                                          private int value;
                                        FuShuException(String message,int value)
                                            {
                                                    super(message);
                                                    this.value=value;
                                             }
                                            public int getValue()
                                                 {
                                                       return value;
                                                   }
                                  }
                       }
                    class Demo
                        {
                            int div(int a,int b)throws FuShuException
                               {
                                   if(b<0)
                                       throw new FuShuException(“出现负数”,b);//                                                                   自定义函数声明
                                    return a/b;
                                }
                              
                         }
            注意:当在函数内部出现了throw抛出的异常对象,那么就必须要给对应的处理动作。要么在内部try catch处理,要么在函数上声明让调用者处理。一般情况下,函数内部出现异常,函数上需要声明。
               throws和throw的区别:throws使用在函数上,throw使用在函数内;throws后面跟的是异常类,可以跟多个,要用逗号隔开;throw后跟的是异常对象。
                  
            (七)对多异常的处理
                 1、声明异常时,建议声明更为具体的异常,这样处理的可以更具体。
                 2、对方声明有几个异常,就对应有几个catch块,不要定义多余的catch块。
                 3、如多个catch块中的异常出现继承关系,父异常catch块放在最下边。
            (八)RuntimeException异常
                  Exception中有一个特殊的异常——RuntimeException,这个类以及这个类的子类有一些特殊的性质:
      1、如果函数内抛出该异常以及该异常的子类,函数上可以不声明,编译一样通过。
      2、如果在函数上声明了该异常以及该异常的子类,调用者可以不进行处理,编译一样通过。
     总之,之所以不用再函数上声明,是因为不需要让调用者处理。当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后对代码进行修正。
             (九)对于异常分两种
                 1、编译时被检测的异常
                 2、编译时不被检测的异常(运行时异常:RuntimeException以及它的子类)
              (十)异常finally
                   finally中放的是一定要被执行的语句。通常用于释放资源。finally只有一种情况不被执行,就是前面有System.exit(0)时。
              (十一)异常在子父类中的体现
                1、子类在覆盖父类时,如果父类方法抛出异常,那么子类的覆盖方法只能抛出父类的异常或者该异常的子类。
                2、如果父类方法抛出多个异常,那么子类在覆盖方法时只能抛出父类异常的子集。
                3、如果父类或者接口的方法中没有抛出异常,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须进行try catch处理,绝对不能抛。
                (十二)异常的好处
                 1、将问题进行封装。
                 2、将正常流程代码和异常处理代码相分离,方便阅读。
                (十三)异常处理的原则
                 1、处理方式有两种:try或者throws。
                 2、调用抛出问的功能时,抛出几个就处理几个,一个try对应几个catch。
                 3、异常处理如果有多个catch,父类的catch放到最下边。
                 4、catch内要顶针对性的处理方式,不要简单的定义printStackTrace输出语 句。也不要不写,当捕获的异常,本功能处理不了时,可以再catch语句中继续向外抛:
                    try
                      {
                        throw new Aexception();
                       }
                        catch(Aexception e)
                            {
                              throw e;                              
                            }
    注意:如果该异常处理不了,但并不属于该功能的异常,可以将异常转换后吗,再抛出和该功能相关的异常。或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,让调用者知道并处理。也可以将捕获的异常处理后,转换新的异常。

五、包(package)
     (一)对文件进行分类管理
     (二)给类提供多层命名空间
     (三)写在程序文件的第一行,例如 package pack;
     (四)类名的全称是:包名.类名
           创建包 javac -d 包的路径
     (五)包也是一种封装形式
                
      (六)总结
           包与包之间进行访问,被访问的保重的类以及类中的成员需要public修饰;不同包中的子类还可以直接访问父类中被protected权限修饰的成员。包与包之间可以使用的权限只有两种:public,protected。
       (七)导入包中类的关键字:import
六、jar包
    命令是 jar

 

---------------------- android培训java培训、期待与您交流! ----------------------  

 

 

 

原创粉丝点击