黑马程序员 --面向对象

来源:互联网 发布:创建目录 linux 编辑:程序博客网 时间:2024/06/06 06:32

黑马程序员 --面向对象

---------------------- <ahref="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a><ahref="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------

面向对象”(英语:Object Oriented,简称OO)是一种以事物为中心的编程思想。

面向对象程序设计(英语:Object-oriented programming,缩写:OOP),是一种程序开发的方法。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性

 

面向对象与面向过程对比

 

 万物皆对象

      1:买电脑

          1:面向过程

             1:查资料

             2:电脑城砍价

             3:被黑

             4:痛苦归来

          1:面向对象

             1:找对象。老师

             2:老师.砍价

             3:老师.检测电脑

             4:电脑成功购买

      2:吃饭

          1:面向过程

             1:自己动手做

             2:买菜

             3:洗菜

             4:煮饭炒菜

             5:很难吃,浪费时间

          2:面向对象

             1:找专业对象

             2:餐馆.点餐

             3:餐馆,做饭

             4:饭好吃,节约时间,精力

      4:找对象

          1:求介绍,相亲,找现成的对象。(面向对象的思想先找有的对象,直                                      接拿来使用)

          2:不满意,没有对象,自己造一个。(sun没有提供,自己造对象)

再例如:人开门,人开电视,人画园。

 

面向对象是相对面向过程而言的,面向过程强调的是功能行为,面向对象是将功能封装进对象,强调具备了功能的对象。

 

面试官若问什么是面向对象(开放式问题,回答必须有自己的体会):

 

  1. 面向对象是一种思想,可以使复杂的问题简单化,可以使我们从执行者变成指挥者

  2. 结合实际场景举个例子说明:面试官就是在用面向对象的思想思考问题,公司里面现在有招人的需求,说明公司现在的业务量比较大,代表着公司在蓬勃发展,你需要找一些具有专业编程经验的人来帮你完成公司的工作,我就是那个对象,我具备专业编程的功能,你就是在指挥我做事情,就是使用我的功能,来为公司创造效益。【万物皆对象】

  3.  

    面向对象三大特征:封装、继承、多态

    类和对象的关系:

    类:对现实生活中事物的描述

    对象:就是这类事物,实实在在存在个体

    描述事物就是描述事物的属性(对应类中变量)和行为(对应类中方法),属性和行为共同称为类的成员(成员变量和成员方法)

    成员变量作用于整个类中,局部变量作用于函数中,或者语句中

    成员变量在堆内存中,因为对象的存在,才在内存中存在,局部变量:存在栈内存中

    封装(Encapsulation):是指隐藏对象的属性和实现细节,仅对外提供公共访问方式

    好处:将变化隔离、便于使用、提高重用性、提高安全性

    封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问

    private(私有):权限修饰符,用于修饰类中的成员(成员变量,成员函数),私有只在本类中有效。

    static用于修饰成员(成员变量和成员函数)

    被修饰的成员:随着类的加载而加载,优先于对象存在,被所有对象所共享,可以直接被类名调用。类名.静态成员  【方法区、共享区、数据区】----存放类中的方法和共享数据。

    什么时候定义静态函数:当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的,用类名直接调用。

    Eg:获取数组的最大值

    class ArrayTool

    {

           publicstatic void main(String[] args)

           {

                  int[]arr={5,8,4,1,3,5,8,77,55,99};

                  intmax=GetMax.getMax(arr);

                  System.out.println("max="+max);

           }

    }

    class GetMax

    {

           publicstatic int getMax(int[] arr)

           {

                  intmax=0;

                  for(intx=0;x<arr.length;x++)

                  {

                         if(arr[x]>arr[max])

                                max=x;

                  }

                  returnarr[max];

           }

    }

    构造代码块(定义对象共性初始化内容):给对象进行初始化,对象一建立,就运行,而且优先于构造函数执行。

    构造代码块是给所有对象进行统一初始化,而构造函数是给对应对象进行初始化。

    this关键字:代表它所在函数所属对象的引用。

                     简单说:哪个对象在调用this所在的函数,this就代表那个对象。

    构造函数间调用只能用this语句,this语句只能放在构造函数第一行,因为初始化动作要先执行,构造函数的权限和类的权限一致。

    静态代码块(可以验证类是否加载):

    格式:

    static

    {

           静态代码块中的执行语句。

    }

    特点:随着类的加载而加载,只执行一次,并优先于主函数,一般用于类的初始化。

    Person p = newPerson("zhangsan",20);

     

    该句话都做了什么事情?

    1,因为new用到了Person.class.所以会先找到Person.class文件并加载到内存中。

    2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化。

    3,在堆内存中开辟空间,分配内存地址。

    4,在堆内存中建立对象的特有属性。并进行默认初始化。

    5,对属性进行显示初始化。

    6,对对象进行构造代码块初始化。

    7,对对象进行对应的构造函数初始化。

    8,将内存地址付给栈内存中的p变量

     

    设计模式:解决某一类问题最行之有效的方法,java中有23中设计模式

    单例设计模式:解决一个类在内存只存在一个对象

  1. 避免其他程序过多建立该类对象,禁止其他程序建立该类对象(将构造函数私有化)

  2. 为了让其他程序可以访问到该类对象,在本类中,自定义一个对象(在类中创建一个本类对象)

  3. 为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式(提供一个方法可以获取到该对象)

    对于事物该怎么描述就怎么描述,当需要将该事物的对象保证在内存中唯一时,就将以上的三步加上即可。

    方法被调用只有两种方式:对象调用和类名调用(static

    Eg: class SimpleDemo//单例设计模式

    {

           publicstatic void main(String[] args)

           {

                  Students1=Student.getInstance();

                  Students2=Student.getInstance();

                  s1.setAge(20);

                  s1.setName("HuangQin");

                  System.out.println(s2.getAge()+";"+s2.getName());

           }

    }

    class Student

    {

           privateString name;

           privateint age;

           publicvoid setAge(int age)

           {

                  this.age=age;

           }

           publicint getAge()

           {

                  returnage;

           }

           publicvoid setName(String name)

           {

                  this.name=name;

           }

           publicString getName()

           {

                  returnname;

           }

           privateStudent(){}

           publicstatic Student s=new Student();//先初始化对象,称为:饿汉式类一进内存,就创建对象,设计建议饿汉式

           publicstatic Student getInstance()

           {

                  returns;

           }

    }

    /* class Student

    {

           privatestatic Student s=null;//懒汉式,延迟加载,调用getInstance方法时,才建立对象

           privateStudent(){}

           publicstatic Student getInstance()

           {

                  if(s==null)

                         s=newStudente();

                         returns;

           }

          

    }

    面向对象总结2

    继承(extends):

  1. 提高了代码的复用性

  2. 让类与类之间产生了关系,有了这个关系,才有了多态的特性

     

    注意:千万不要为了获取其他类的功能,简化代码而继承,必须是类与类之间有所属关系才可以继承,所属关系:is a

     

    Java语言中,只支持单继承,不支持多继承,因为多继承容易带来安全隐患:当多个父类(超类,基类super)中定义了相同功能,功能的内容不同时,子类对象不知该运行哪一个。

    但是java保留这种机制,并用多实现形式完成表示。

    Java支持多层继承,也就是一个继承体系。

    想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能,通过了解共性功能,就可以知道该体系的基本功能。

    在具体调用时,要创建最子类的对象,一是有可能父类不能创建对象(抽象类和接口),二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。

    简单说:查阅父类功能,创建子类对象使用功能。

    如果子类中出现非私有的同名成员变量,,子类要访问本类中的变量,用this,要访问父类中的同名变量,用superthis代表本类对象的引用,super代表父类对象的引用。

    子父类函数的特点:

    重写(覆盖)(子父类方法要一模一样):要与重载(只看同名函数的参数列表)区别开来,当子类出现和父类一样的函数时,当子类对象调用该函数,会运行子类函数的内容,如同父类的函数被覆盖一样。

    覆盖注意:子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败;静态只能覆盖静态;

    子父类的构造函数:

    在对子类对象进行初始化时,父类的构造函数也会运行

    那是因为子类的构造函数默认第一行有一条隐式的语句super();

    super():会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();

    为什么子类一定要访问父类中的构造函数:

    因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时,要先访问一下父类的构造函数,俄国要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。

    子类的所有构造函数,默认都会访问父类中空参数的构造函数

    因为子类每一个构造函数内的第一行都有一句隐式super();

    final关键字:可以修饰类、方法、变量,修饰的类不可以被继承,修饰的方法不可以被覆盖,修饰的变量时一个常量,只能被赋值一次,内部类只能访问被final修饰的局部变量。

    抽象类的特点:抽象方法一定定义在抽象类中,抽象方法和抽象类都必须被abstract关键字修饰,抽象类不可以用new创建对象,因为调用抽象方法没意义;

    抽象类中的抽象方法要被使用,必须由子类覆写所有的抽象方法,建立子类对象调用,如果子类只覆写了部分抽象方法,那么该子类还是一个抽象类。

    抽象类和一般类没有太大的不同,只是要注意该怎样描述事物就如何描述事物,只不过该事物中出现了一些看不懂的东西,这些不确定的功能,也是该事物的功能,需要明确出现,但是无法定义主体。

    抽象类比一般类多了抽象函数,在类中可以定义抽象方法,不可以实例化。

    抽象类可以不定义抽象方法,仅仅是不让该类建立对象。

    抽象类Eg

    /*

    假如我们在开发一个系统时需要对员工进行建模,员工包含 3个属性:

    姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个

    奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方

    法进行属性访问。

    员工类:name id pay

    经理类:继承了员工,并有自己特有的bonus

    */

    class Employee

    {

           private String name;

           private String id;

           private double salary;

           Employee(String name,String id,doublesalary)

           {

                  this.name=name;

                  this.id=id;this.bonus=bonus;

           }

           public abstract void work();

    }

    class Managerextends Employee

    {

           private double bonus;

           Manager(String name,String id,doublesalary,double bonus)

           {

                  super(name,id,salary);

                  this.bonus=bonus;

           }

           public void work()

           {

                  System.out.println("Managerwork");

           }

    }

    class Workerextends Employee

    {

           Worker(String name,String id,double pay)

           {

                  super(name,id,salary);

           }

           public void work()

           {

                  System.out.println("Workerwork");

           }

    }

    模板方法模式:在定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去,由该类的子类去完成。

    接口(interface):初期理解,可以认为是一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。

           接口是对外暴露的规则,是程序的功能扩展,可以用来多实现

  1. 接口中常见定义:常量、抽象方法

  2. 接口中的成员都有固定修饰符

    常量:public static final

    方法:public abstract

    记住:接口中的成员都是public的,接口是不可以创建对象的,因为有抽象方法,需要被子类实现(implements),子类对接口中的抽象方法全都覆盖后,子类才可以实例化,否则子类是一个抽象类。

    接口可以被类多实现,也是对多继承不支持的转换形式。

    [类与类之间继承,类与接口之间实现,接口与接口之间继承]

    基本功能定义在类中,扩展功能定义在接口中。

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

    多态的体现(父类的引用也可以接收自己的子类对象)、多态的前提(必须类与类之间有关系,要么继承,要么实现,另外还要存在覆盖)、多态的弊端(只能使用父类的引用访问父类中的成员)、多态的好处(大大提高了程序的扩展性)、多态的应用。

    向下转型:强制将父类的引用,转成子类类型

                         如动物和猫的例子:Cat c=Cata

    成员函数在运行时:编译看左边,运行看右边。

    在多态中,成员变量无论编译还是运行,都参考左边(引用型变量所属的类);

    多态的主板实例:

    class MainBoard

    {

           public void run()

           {

                  System.out.println("mainboardrun");

           }

           public void usePCI(PCI p)

           {

                  if(p!=null)

                  {

                         p.open();

                     p.close();     

                  }

          

           }

    }

    interface PCI

    {

           public void open();

           public void close();

    }

    class Networkimplements PCI

    {

                publicvoid open()

                {

                       System.out.println("networkwork");

                }

                publicvoid close()

                {

                       System.out.println("networkclose");

                }

    }

    class DuotaiDemo4

    {

           public static void main(String[] args)

           {

                  MainBoard mb=new MainBoard();

                  mb.run();

                  mb.usePCI(new Network());

           }

    }

    object:所有对象的直接或者间接父类,该类中定义的肯定是所有对象都具备的功能。

    object类中已经提供了比较对象是否相同的方法,如果自定义类中也有比较相同的功能

    ,没有必要重新定义,只要沿袭父类中的功能,建立自己特有的比较内容即可,这就是覆盖。

    toString():返回对象的字符串表示。

    9天:面向对象

    内部类:

    可以直接访问外部类的成员,包括私有,之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:内部类名.this;外部类要访问内部类,不需建立内部类对象。

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

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

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

    当内部类在成员位置上,就可以被成员修饰符所修饰,如private(将内部类在外部类中进行封装)static(只能访问外部类中的static成员,出现了访问局限)

    在外部其他类中,访问static内部类的非静态成员:new Outer.Inner().function();

    在外部其他类中,直接访问static内部类的静态成员:Outer.Inner.function();

    注意:当内部类中定义了静态成员,内部类必须是静态的;

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

    内部类定义在局部时,不可以被成员修饰符修饰,可以直接访问外部类中的成员,因为还持有外部类中的引用,但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

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

           前提:必须继承一个类或者实现接口。

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

    其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖,或者理解为有内容的对象。

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

    异常:就是程序在运行时出现不正常情况是对问题的描述,将问题进行对象的封装。

    异常由来:问题也是现实生活中的一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象,其实就是java对不正常情况进行描述后的对象体现。

    对于问题的划分:对于严重的,java通过Error类进行描述,一般不编写针对性的代码对其进行处理;对于非严重的,java通过Exception类进行描述,可以使用针对性的处理方式进行处理。

    异常处理语句:

    try

    {

           需要被检测的代码;

    }

    catch(异常类 变量)

    {

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

    }

    finally

    {

           一定会执行的代码;

    }

    对捕获到的异常对象进行常见方法操作:String getMessage():获取异常信息。

    对多异常的处理:

  1. 声明异常时,建议声明更为具体的异常,这样处理可以更具体

  2. 对方声明几个异常,就对应有几个catch块,不要定义多余的catch块,如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。

    throwsthrow的区别:

    throws使用在函数上,后面跟的异常类,可以跟多个,用逗号隔开;throw使用在函数内,后面跟的是异常对象。

    Exception中有一个特殊的子类异常RuntimeException运行时异常,如果在函数内部抛出该异常,函数上可以不用声明(因为不需要让调用者处理),编译一样通过,如果在函数上声明了该异常,调用者可以不用进行处理(当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正),编译一样通过!

    自定义异常时,如果该异常发生,无法再继续进行运算,就让自定义异常继承RuntimeException

    异常的练习:

    /*

    毕老师用电脑上课。

    开始思考上课中出现的问题。

    比如问题是

           电脑蓝屏。

           电脑冒烟。

     

    要对问题进行描述,封装成对象。

    可是当冒烟发生后,出现讲课进度无法继续。

    出现了讲师的问题:课时计划无法完成。

    */

    class Teacher

    {

           privateString name;

           privateComputer cmpt;

           Teacher(Stringname)

           {

                  this.name=name;

                  cmpt=newComputer();

           }

           publicvoid prelect()throws NoplanException

          

           {

                  try

                  {

                                cmpt.run();

                  }

                  catch(LanPingExceptione)

                  {

                         cmpt.reset();

                  }

                  catch(MaoYanExceptione)

                  {

                         test();

                         thrownew NoplanException("课时无法继续"+e.getMessage());

                        

                  }

          

                  System.out.println("老师讲课");

           }

           publicvoid test()

           {

                  System.out.println("做练习");

           }

    }

    class LanPingException extends Exception

    {

           LanPingException(Stringmessage)

           {

                  super(message);

           }

          

    }

    class MaoYanException extends Exception

    {

           MaoYanException(Stringmessage)

           {

                         super(message);

           }

     

    }

    class NoplanException extends Exception

    {

           NoplanException(Stringmessage)

           {

                  super(message);

           }

    }

    class Computer

    {

           privateint state=3;// 通过状态值判定电脑的情况

           publicvoid run()throws LanPingException,MaoYanException

           {

                  if(state==2)

                         thrownew LanPingException("蓝屏了");

                  if(state==3)

                         thrownew MaoYanException("冒烟了");

                  System.out.println("电脑运行");

           }

           publicvoid reset()

           {

                  state=1;

                  System.out.println("电脑重启");

           }

    }

    class ExceptionTest

    {

           publicstatic void main(String[] args)

           {

                  Teachert=new Teacher("毕老师");

                  try

                  {

                         t.prelect();

                  }

                  catch(NoplanExceptione)

                  {

                         System.out.println(e.toString());

                         System.out.println("换老师或者放假");

                  }

           }

    }

    state=3时,运行结果

    10天:面向对象

    finally中存放的是一定会执行的代码,通常用于关闭资源。

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

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

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

  3. 如果父类或者接口在方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常;如果子类方法发生了异常,就必须进行try处理,绝对不能抛。

     

    异常的好处:

  1. 将问题进行封装

  2. 将正常流程代码和问题代码相分离,方便与阅读。

    包(package):对类文件进行分类管理,给类提供多层命名空间,写在程序文件的第一行,类名的    全称是 包名.类名,包也是一种封装形式。

    包与包之间的访问:被访问的包中的类以及类中的成员,需要public修饰;不同包中的子类可以直接访问父类中被protected权限修饰的成员;包与包之间可以使用的权限只有两种:publicprotected

    import导入的是包中的类,建议:不要使用通配符“*”,需要用到包中的哪个类,就导入包中的哪个类。

    建议定义包名不要重复,可以使用url来完成定义,url是唯一的。

    jar包:java的压缩包

  1. 方便项目的携带

  2. 方便于使用,,只要在classpath设置jar路径即可

  3. 数据库驱动,ssh框架等都是以jar包体现的。

    */

    ----------------------<ahref="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a><ahref="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------

     

0 0
原创粉丝点击