• 黑马程序员——面向对象


      本文是对java面向对象概念的总结和回顾。面向对象是java语言的一个重要特点,只有真正理解了面向对象的基本概念,并应用面向对象的概念编写java程序,才算是真正的java程序员。

    一、面向对象的概念

      面向对象是相对面向过程而言,面向对象和面向过程都是一种思想。面向过程强调的是功能行为,就像我们熟悉的C语言就是面过程的语言。面向对象将功能封装进对象,强调具备了功能的对象,就像java语言。

      我们以一个将大象装进冰箱里的例子来说明面向过程和面向对象的区别。

      面向过程:

      1、把冰箱门打开

      2、把大象装进去

      3、把冰箱门关上

      "打开"、"存储"、"关上"都是功能行为,在代码中的直观体现就是函数或者方法,这就是一种面向过程的以功能行为为主体的思想体现。

      面向对象:把方法封装到冰箱对象中。

      1、冰箱打开

      2、冰箱装大象

      3、冰箱关闭

      可以看到,所有的操作都是以"冰箱"为主体,而不是功能行为。也就是说冰箱自己已经具备"打开"、"存储"、"关上"的行为功能,我们只需要让冰箱执行它具备的功能就可以了。这就是一种面向对象的以执行功能的对象为主体的思想体现。

      面向对象是一种符合人们思考习惯的思想,可以将复杂的事情简单化,将程序员从执行者转换成了指挥者。

      按照面向对象的思想,在解决问题的过程是:

        1、先要去找具有所需功能的对象来用。

        2、如果该对象不存在,那么创建一个具有所需功能的对象。

      这样可以简化开发并提高复用。那么在面向对象的世界中开发的过程就是:不断的创建对象,使用对象,指挥对象做事情。设计的过程就是:在管理和维护对象之间的关系。面向对象具有三大特征就是:封装、继承、多态。

    二、类与对象

      使用计算机语言就是不断地在描述现实生活中的事物,java中描述事物通过类的形式体现,类是具体事物的抽象。对象即是该类事物实实在在存在的个体。

      简单来说人就是一个抽象概念,是一个类,指的是大自然中具有人的特性的个体的总称。而生活中每一个活生生的个体就是一个对象,对象除开具备公共属性外,还具有每个个体的特有属性。

      生活中描述事物无非就是描述事物的属性和行为。Java中用类class来描述事物也是如此。属性:对应类中的成员变量;行为:对应类中的成员函数。那么定义类其实在定义类中的成员(成员变量和成员函数)。

      比如我们描述车,车有颜色,还有几个轮子,那么我们定义的类结构如下:

     1 class Car
     2 {
     3     public String color;//车有颜色
     4     public int number;//轮子个数
     5     public Car()//
     6     {
     7         color="red";//在构造函数中赋初值
     8         number=4;
     9     }
    10     public void show()//类的展示方法
    11     {
    12         System.out.println("color:"+color+" -- num:"+number);
    13     }
    14 }

      上面的类中有属性,也有方法,其中构造函数没有返回值,与类名同名。

      那么接下来我们通过类了来创建对象。

      创建对象的代码如下:

    1     Car c1=new Car();
    2     c1.color="blue";
    3     Car c2=new Car();
    4     c1.show();
    5     c2.show();            

      创建对象的内存中的格式如下:

      

      只要是用new操作符定义的实体就会在堆内存中开辟一个新的空间,并且每一个对象中都有一份属于自己的属性。空间开辟之后,将地址赋给类类型的变量。c1、c2两个类变量指向不同的类内存空间。

      通过对象.对象成员的方式操作对象中的成员,对其中一个对象的成员进行了修改,和另一个对象没有任何关系。就像上面c1所指的内存中color的值变成了blue而c2中的color属性值并没有变化。

      当c1、c2不再指向对象的时候,如果对象没有任何指向他的类类型的变量,则对象会被垃圾回收期在某个时间段清理掉。

      好了我们分析了内存中对象的创建过程 ,那么我们运行一下程序看看和我们分析的结果是不是一样的

      程序运行的结果如下所示:

      

      匿名对象

      匿名对象是对象的简化方式,匿名对象两种使用情况:1.当对对象方法仅进行一次调用时;如:new Car().show();2、2.匿名对象可以作为实际参数进行传递。把new Car()当作参数传递在函数内部操作Car类的数据。

      基本数据类型参数及引用数据类型参数传递

      在java中,方法参数的传递永远都是传值,而这个值,对于基本数据类型,值就是你赋给变量的那个值。而对于引用数据类型,这个值是对象的引用,而不是这个对象本身。

      我们通过代码来感受一下两者的区别:

      

     1 class  MyClass
     2 {
     3     public static void main(String[] args) 
     4     {
     5         int num=4;
     6         Car c1=new Car();
     7         show(num);//将基本数据类型作为参数传递
     8         show(c1);//将应用数据作为参数传递
     9         System.out.println("基本数据类型,传递之前是4,传递之后是:"+num);
    10         System.out.println("引用数据类型,传递之前是4,传递之后是:"+c1.num);    
    11     }
    12     static void show(int num)
    13     {
    14         num=2;
    15     }
    16     static void show(Car c)
    17     {
    18         c.num=2;
    19     }
    20 }

      输出的结果为:

      

      可以看到引用数据类型作为参数传递之后,数据发生了变化,二基本数据类型没有发生变化。

    三、封装

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

      封装的好处:1、将变化隔离。2、便于使用。3、提高重用性。4、提高安全性。

      封装的原则:1、将不需要对外提供的内容都隐藏起来

            2、把属性都隐藏,提供公共方法对其访问。如,getXXX,setXXX。

      私有仅仅是封装的一种体现而已。

    四、构造函数

      作用:为对象初始化。

      特点:1、函数名与类名相同;2、不用定义返回值类型;3、没有具体的返回值

      构造函数和普通函数的区别:

        构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化。只调用一次。

        一般函数:对象创建后,需要函数功能时才调用。可以多次调用。

      一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数。如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了。个构造函数是以重载的形式存在的。

    五、this关键字

      this代表其所在函数所属对象的引用。换言之,this代本类对象的引用。当成员变量和局部变量重名,可以用关键字this来区分,this就是所在函数所属对象的引用。简单说,哪个对象调用了this所在的函数,this就代表哪个对象。一般方法调用默认加this。当在函数内需要用到调用该函数的对象时,就用this。

      通过this在构造函数中调用其他构造函数的时候,只能定义在构造函数的第一行,因为初始化动作要先执行,否则就会报错。这个很好理解,如果不在第一行,那么我们在之前做的初始化的动作有可能会被覆盖而无效。 

    六、static关键字

      static关键字:用于修饰成员(成员变量和成员函数)。

      被修饰后的成员具备以下特点:

        1、随着类的加载而加载。

        2、优先于对象存在。

        3、被所有对象所共享。

        4、可以直接被类名调用。

      成员变量和静态变量的区别

        1、两个变量的生命周期不同

          成员变量随着对象的创建而存在,随着对象被回收而释放。

          静态变量随着类的加载而存在,随着类的消失而消失。

        2、调用方式不同

          成员变量只能被对象调用。

          静态变量可以被对象调用,还可以被类名调用。

        3、别名不同

          成员变量也称为实例变量。

          静态变量也称为类变量。

        4、数据存储位置不同

          成员变量存储在堆内存的对象中,所以也叫对象的特有数据。

          静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。

      注意:静态方法只能访问静态成员,如果访问非静态成员,就会报错!原因很好理解,静态方法随着类的加载而加载,此时还没有创建对象,所以不能访问非静态成员。理解了这一点,相反非静态方法就既可以方位非静态成员,也可以访问静态成员。

      主函数是静态的,主函数是一个特殊的函数,前面我们提到过,main不是关键字,具体来说主函数的特殊之处如下:1、格式是固定的,public static void main(String[] args)。2、被java虚拟机所识别和调用。

      学了这么多静态的特征,那么静态什么时候用呢?

      1、静态变量

        当分析对象中所具备的成员变量的值都是相同时,这时这个成员就可以被静态修饰。只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。如果是相同的数据,对象不需要做修改,只需要使用即可,不需要存储在对象中,定义成静态的。

      2、静态函数

        函数是否用静态修饰,就参考一点,就是该函数功能是否需要访问到对象中的特有数据。简单点说,从代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,但是非静态需要被对象调用。

      静态代码块给类进行初始化,构造代码块给所有的对象进行初始化。

    知识点拓展: 

      对象的初始化过程:

            定义一个新对象都做了哪些事情?

            1、把类名.class文件加载到内存中。

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

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

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

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

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

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

            8、将内存地址赋给栈内存中的对象名变量。

      单例设计模式

        设计模式是解决一类问题的思想。单例设计模式解决的问题:就是可以保证一个类在内存中的对象唯一性。比如多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。

      单例设计模式的思路:

        1、不允许其他程序用new创建该类对象。  ---》私有化构造函数

        2、要有一个这个类的对象。  ----》在该类创建一个本类实例。

        3、对外提供一个方法让其他程序可以获取该对象。 ----》定义一个公有的方法,将创建的对象返回。

      单例模式又分为饿汉式和懒汉式两种方式:

        饿汉式单例模式:  

     1 class SingleClass 
     2 {
     3     //饿汉式,类加载时对象就已经创建了
     4     private static SingleClass sc=new SingleClass();
     5     private SingleClass()
     6     {
     7     }
     8     public static Single getInstance()
     9     {
    10         return sc;
    11     }
    12 }

      懒汉式单例设计模式:

     1 class SingleClass 
     2 {
     3     //懒汉式,类加载时对象不创建,使用时创建,也叫延迟加载
     4     private static SingleClass sc;
     5     private SingleClass()
     6     {
     7     }
     8     public static Single getInstance()
     9     {
    10         if(sc==null)
    11             sc=new SingleClass();
    12         return sc;
    13     }
    14 }

      懒汉式单例设计模式在多线程时时不安全的,在代码进行同步之后才能保证多线程的安全性。

     1 class SingleClass 
     2 {
     3     //懒汉式,类加载时对象不创建,使用时创建,也叫延迟加载
     4     private static SingleClass sc;
     5     private SingleClass()
     6     {
     7     }
     8     public static Single getInstance()
     9     {
    10 
    11         if(sc==null)//在同步之前做一个不为空的判断提高程序的效率和安全性
    12         {
    13             synchronized(new Object())//加同步锁
    14             {
    15                 if(sc==null)
    16                     sc=new SingleClass();
    17             }
    18         }
    19         return sc;
    20     }
    21 }

    面向对象的总结到此就结束了,这一章的内容十分的重要。很多知识点都是必须要理解,要掌握,要能够写出代码来验证的。

    继续努力加油!为了明天更好的自己。

  • 相关阅读:
    线程(C++11)
    初始化、赋值
    优质学习资料总结
    移植之乱谈
    采集音频和摄像头视频并实时H264编码及AAC编码
    H264解码器源码(Android 1.6 版)
    移植ffmpeg到VC环境心得
    收集的网络上大型的开源图像处理软件代码(提供下载链接)
    C++开源库,欢迎补充。
    一个轻量级AOP的实现(开源)
  • 原文地址:https://www.cnblogs.com/dengzhenyu/p/4826750.html
Copyright © 2020-2023  润新知