【重走Android之路】【Java面向对象基础(三)】面向对象思想

【重走Android之路】【基础篇(三)】【Java面向对象基础】面向对象思想
 

1 面向对象的WWH

 

    1.1 What--什么是面向对象

        首先,要理解“对象”。在Thinking in Java中提到“Everything is an object”,即万物皆对象。这里的“对象”指的是任何实体或者任何可以当作实体看待的“虚幻的事物”。比如现实中的人(男人、女人、老人、小孩而。。。)、动物(大象、狮子、猴子。。。)、桌子、凳子、汽车、ATM机等等,也可以使看不见摸不着的空气(氧气、二氧化碳、氮气。。。)、科幻片里的各种怪物、甚至包括人的意识等等,只要你能想到的客观存在的实体和主观抽象的概念,都可以作为对象。
        知道了“对象”的定义,便可理解面向对象编程(Object-Oriented Programming)的概念,下面是我个人的理解:OOP,是软件开发中一种自生而下的编程方式,它通过“对象”模拟现实环境,把环境属性注入到“对象”当中,通过操作对象以及对象之间的关联实现程序功能,这种方式提升了程序结构清晰度,提高了代码的重用性和扩展性,也降低了开发人员对程序理解和开发的难度。
    

    1.2 Why--为什么要面向对象

        我们知道面向过程和面向对象两种编程方式。面向过程的C语言已经独霸几十年,随后产生的C++、Java、C#、Object-C等语言大部分采用的是面向对象方式。对于C语言大牛们来说,面向过程已经够用,因为他们把计算机基础甚至底层知识掌握的很牢固,用面向过程的方式开发如行云流水般顺畅。但是结构化设计(面向对象编程)在设计系统的时候,无法解决重用、维护、扩展等问题,而且会导致逻辑过于复杂,代码晦涩难懂。于是人们就想,能不能让计算机直接模拟现实的环境,用人类解决问题的思路、习惯、步骤来设计向英的应用程序。这样的程序,人们在读它的时候会更容易理解,也不需要把现实世界和程序世界之间来回做转换。
        人们发现,在现实世界中存在的实体或概念是问题域中的主角,亦即我们上边所提的“对象”。对象具有属性和行为,属性是稳定的,行为不稳定。而且对象之间往往具有各种关联关系。因此面向对象编程比面向过程编程更稳定。在面对频繁的需求更改时,改变的往往是行为而对象本身一般不会改变,从而保证架构的稳定性。
        人们追求的系统可维护性,可扩展性,可重用性又是怎么在面向对象中体现出来的呢?
        首先看看面向对象的三大特征:
        封装:找到变化并且把它封装起来,你就可以在不影响其它部分的情况下修改或扩展被封装的变化部分,这就是所有设计模式的基础,就是封装变化,因此封装的作用就是解决程序的可扩展性。
        继承:子类继承父类,可以继承父类的方法和属性,实现了多态以及代码的重用,因此解决了系统的重用性和扩展性。但是继承破坏了封装,因为它是对子类开放的,修改父类会导致所有子类的改变,因此继承一定程度上又破坏了系统的可扩展性。所以,继承需要慎用,只有明确的is-a关系才能使用。同时继承是在程序开发过程中重构得到的,而不是程序设计之初就使用继承,很多面向对象开发这滥用继承,结果造成后期的代码解决不了需求的变化了。因此优先使用组合而不是继承,是面向对象开发中一个重要的经验。
        多态:接口的多种不同的实现方式即为多态。接口是对行为的抽象,刚才在封装中提到,找到变化部分并封装起来,但是封装起来后怎么适应接下来的变化?这正是接口的作用,主要目的是为不相关的类提供通用的处理服务。设想一下,鸟会飞,但是超人也会飞,可以让鸟和超人都实现飞这个接口,这样维护飞这个行为或者后来又有其他对象实现飞接口就会很方便,如此便体现了系统的可维护性和可扩展性。
        因此面向对象能实现人们追求的系统可维护性,可扩展性,可重用性。面向对象是一种编程思想,起初,“面向对象”是专指在程序设计中采用封装、继承、多态等设计方法,但面向对象的思想已经涉及到软件开发的各个方面,比如现在细分为了面向对象的分析(OOA),面向对象的设计(OOD),面向对象的编程实现(OOP) 。

    1.3 How--如何进行面向对象开发

        那么如何进行面向对象开发呢?
        面向对象是一种思想,它让我们在分析和解决问题时把思维和重点转向现实中的客体中来,然后通过UML等工具理清这些客体之间的联系,最后用面向对象的语言实现这种客体之间的联系。它分为面向对象分析(OOA)、面向对象设计(OOD)和面向对象编程(OOP)三大步。
        a、分析需求,先不要考虑怎么用程序实现,要先分析需求中稳定不变的客体有哪些,找到这些客体之间的联系。亦即确定面向的“对象”以及相互关系。
        b、设计模型,根据第一步分析出来的需求,通过进一步扩充模型,变成可实现、符合成本、模块化、低耦合高内聚的模型。通常使用UML工具(常用的有IBM的Rose和Microsoft的Visio)实现。
        c、编程实现,根据以上两步积累,使用面向对象思想实现模型和需求。
 

2 相关知识点的Q&A

    
    a、面向对象的基本特性是什么?
        抽象,封装,继承,多态
        抽象:忽略事物中对当前目标无关的非本质特性,充分关注本质特性。找出事物的共性,并把具有共性的事物划为一类,得到一个抽象的概念。
        封装:把对象的属性和行为结合成一个独立的单位,并尽可能隐藏对象的内部细节。
        继承:指特殊类的对象拥有其一般类的属性和行为(子类继承父类)。继承意味着“自动拥有”被继承类的属性和行为。
        多态:简单来说,多态是具有表现多种形态的能力的特征,根据对象的不同形态以不同方式处理,特别是方法重载和类的继承。多态还分为编译时多态和运行时多态。
 
    b、面向对象和基于对象有什么区别?

    “面向对象”和“基于对象”都实现了“封装”的概念,但是面向对象实现了“继承和多态”,而“基于对象”没有实现这些。因此在我们进行WEB开发,普通三层开发中,基本上是基于对象的实现,因为只是实现了封装,但是没有使用继承和多态。        

 
    c、创建对象的方式有哪几种?
  • 用new语句创建
  • 利用反射,调用java.lang.Class或者java.lang.reflect.Constructor的newInstance()实例方法
  • 调用对象的clone()方法
  • 使用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法
  • 字符串常量以及字符串+操作符都会产生新String对象
    d、简述对象的初始化顺序
  • 所有静态成员初始化(父类-->子类)
  • 父类初始化(普通成员-->构造方法)
  • 子类初始化(普通成员-->构造方法)
  • static成员初始化吮吸只和类定义中的顺序有关
    e、简述Java的垃圾回收机制
        在Java中,内存回收任务由JVM(Java Virtual Machine)来担当。在程序的运行环境中,JVM提供了一个系统级的垃圾回收器现成,它负责自动回收那些无用对象所占用的内存空间。这种内存回收的过程被称为垃圾回收。
        一个对象,可以有一个或多个引用变量指向它。当一个对象不再有任何一个引用变量指向它的时候,这个对象就可以被垃圾回收机制回收。
        但是,并不是对象被抛弃后立即回收。JVM进程做空间回收有较大的系统开销,如果每当应用进程丢弃一个对象就立即回收空间,势必会使整个系统的运转效率非常低下。
        将引用设为null或者调用System.gc()、Runtime.gc(),JVM就会接收到消息,然后对几个垃圾回收算法做加权处理,使垃圾回收操作容易发生或提早发生。
        由于垃圾回收器的运行时间不是固定的,所以清理工作的实际运行时间也是不可预知的。
 
    f、Java包含几种内部类?各有什么特点?
        Java内部类有两种情况共四类:
        (1)在类中定义一个类(私有内部类,静态内部类)
        (2)在方法中定义一个类(局部内部类,匿名内部类)
        内部类的特点:
        (1)私有内部类
                外部类和内部类可以互相访问自己的私有成员
                内部类中不能定义静态成员变量
        (2)静态内部类
                只能访问外部类的静态成员
        (3)局部内部类
                该内部类没有任何的访问控制权限
                外部类无法访问局部内部类,但是局部内部类可以访问外部类的任何成员
                方法体中可以访问局部内部类,但是访问语句必须在定义局部内部类之后
                局部内部类只能访问方法体中的常量,即用final修饰的成员
        (4)匿名内部类
                没有构造器,取而代之的是将构造器参数传递给超类构造器
 
    g、如何继承内部类?需要注意什么?
        首先,只有私有内部类和静态内部类才可以被继承,局部内部类和匿名内部类由于访问权限限制,外部无法继承。
        (1)私有内部类的继承方式和普通继承方式略微不同: class  A extends Outer.Inner  即需要调用外部类。另外,需要为子类A创建以外部类Outer为形参的构造方法,并调用形参的super方法。
        (2)静态内部类和普通类的继承方式一样,可以直接继承。
        示例代码如下:
 1 class  Outer {
 2      /**私有内部类*/
 3      class  Inner {
 4         
 5     }
 6     
 7      /**静态内部类*/
 8      static   class  SInner {
 9         
10     }
11 }
12 /** 通过外部类继承 私有内部类 */
13 class  A  extends  Outer.Inner {
14      /**
15      * 必须创建该构造方法,否则编译不通过
16      *  @param  outer
17      */
18      public  A(Outer outer) {
19         outer. super ();
20     }
21 }
22 /** 直接继承静态内部类 */
23 class  B  extends  SInner {
24 }

 

    h、持续更新补充中。。。
 
posted @ 2014-07-13 16:04  陌上幽人  阅读(1308)  评论(0编辑  收藏  举报