黑马程序员——Java 面向对象(上)

来源:互联网 发布:mac appstore 打不开 编辑:程序博客网 时间:2024/06/10 22:06

-----------android培训java培训、java学习型技术博客、期待与您交流!------------  

 一、面向对象基本概念


        在Java的开发过程,其实就是不断的创建对象,使用对象,指挥对象做事情。设计的过程,其实就是在管理和维护对象之间的关系。

面向对象的三个特征:

        封装(encapsulation 

        继承(inheritance

        多态(polymorphism


    开发中:其实就是找对象使用,没有对象,就创建一个对象


       

 

    成员变量和局部变量 区别在于作用范围不同


       之前我们用到的基本都是局部变量,现在我们将会使用成员变量。其实它两都是变量,规范写法上也没啥区别,都是标识符,但是在作用范围和内存中分配不同。

区别:


成员变量 局部变量成员变量定义在类中,在整个类中都可以被访问。 局部变量只定义在局部范围内,如:函数内,语句内等。成员变量随着对象的建立而建立,存在于对象所在的堆内存中。 局部变量存在于栈内存中。成员变量有默认初始化值。作用的范围结束,变量空间会自动释放。 局部变量没有默认初始化值。


匿名对象

        匿名对象是对象的简化形式。

        匿名对象两种使用情况

                1当对对象方法仅进行一次调用的时

                2匿名对象可以作为实际参数进行传递

注:如果对一个对象进行多个成员调用,必须给这个对象起个名字。

 

  对象的封装

1、 概念

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

2、 好处

        a)将变化隔离。

        b)便于使用。

        c)提高重用性。

        d)调高安全性。

3、 原则

        a)  将不需要对外提供的内容都隐藏起来。

        b)  把属性都隐藏,提供公共方法对其访问。

4、 封装的表现形式之一——private(私有)

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

       

     注意: 将成员变量私有化,对外提供对应的setget方法对其进行访问之所以在对外提供访问方式,就因为可以在访问方式中加入逻辑判断语句,以便提高程序安全性!!

          比如: private int age;

                     public int setAge(int a)

                    {  if......

                        ......

                         else age=a;

                    }


       

    构造函数


       构造函数式在对象一建立就运行,给对象初始化。而一般方法是对象调用才执行,给是对象添加对象具备的功能。一个对象建立,构造函数只运行一次。而一般方法可以被该对象调用多次。

特点:

        a) 函数名与类名相同。

        b) 不用定义返回值类型。

        c) 不可以写return语句。

 作用:

        给对象进行初始化。

构造函数的小细节:

        当一个类中没有定义构造函数时,那么系统就会默认给该类加入一个空参数的构造函数。当在类中自定义了构造函数后,默认的构造函数就没有了。


  注意:当类中重载了构造函数,而且没有定义空参构造函数时,那么以后每次创建对象时必须按照重载的构造函数去创建新的对象!



       

什么时候定义构造函数?

        当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中。

6、构造代码块


     

       作用:给对象进行初始化。对象一建立就运行,而且优先于构造函数运行。

和构造函数的区别:

       构造代码块是给所以对象进行初始化。

       而构造函数是给对应的对象初始化。

构造代码块中定义的是不同对象共性的初始化内容。

 

   this关键字


       this代表它所在函数所属对象的引用。

       谁调用this所在的函数,this就代表哪个对象。


this的应用:

       当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。

       但凡本类功能内部使用到了本类对象,都用this表示。

this语句:

       用于构造函数之间进行互相调用。如:this(name);

        thi语句只能定义在构造函数的第一行。因为初始化要先执行


注:一般函数不能直接调用构造函数,因为this语句不能用在一般函数中,只能用在构造函数间。

 


  static(静态)关键字

        static是一个修饰符,用于修饰成员(成员变量和成员函数)。当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。格式:类名.静态成员。

static特点:

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

              也就是说:静态会随着类的消失而消失,说明它的生命周期最长。

        2、优先于对象存在。明确一点:静态是先存在。对象是后存在。

        3、被所有对象所共享。

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

       由于静态成员可以直接被类名调用,因此静态成员变量又称为类变量。而非静态成员变量又被称为实例变量。

实例变量和类变量的区别:

        1、存放位置。

              类变量随着类的加载而存在于方法区中。

              实例变量随着对象的建立而存在于堆内存中。

        2、生命周期。

              类变量生命周期最长,随着类的消失而消失

             实例变量生命周期随着对象的消失而消失。


静态有利有弊:

        利处:单独存储,节省空间,可以直接被类名调用。

        弊端:生命周期过长  访问出现局限性



jvm在调用主函数时,传入的是new String[0];

   string[ ]  args   传值练习!!

class  args{public static void main(String[] args) {System.out.println(args[0]);  //java args练习,java args  test-argsSystem.out.println(args.length); //等到args的长度}}

输出结果:







静态使用注意事项:

       1  静态方法只能访问静态成员,非静态方法既可以访问静态也可以访问非静态。   

       2  静态方法中不可以定义thissuper关键字,  因为静态优先于对象存在。所以静态方法中不可以出现this  

       3  主函数是静态的。

       4  当对象中出现共享数据时,该数据被静态所修饰。

       5  对象中的特有数据要定义成非静态存在于堆内存中

       6  当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。





静态代码块:

       格式:

              static

              {

                        .........

              }

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



工具类

如果一个类中定义的方法没有封装特有数据,那么可以将此类定义为工具类,而且通常会将工具类中的方法定义为static方法!

 当方法都静态后,为了更加严谨,将空参构造函数私有话,以便于该类无法建立新对象




对象的初始化过程:    定义一个新对象都做了哪些事情?

      

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

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

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

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

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

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

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

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


如图,打印顺序为 1-2-3-4





静态代码块&构造函数&构造代码块区别  

静态代码块:
随着类的加载而执行,只执行一次,并优先于主函数,也优先于构造代码块。用于给类进行初始化。

构造函数“
构造函数是在对象一建立就运行,给对象进行初始化。

构造代码块:
构造代码块是在对象一建立就运行,而且优先于构造函数执行,用来定义不同对象共性的初始化内容。

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

构造代码块与静态代码块:随着类的加载静态代码块只执行一次,构造每次建立对象都会执行 !

代码执行顺序:“静态代码块”>“构造代码块”>“构造函数”。



静态的应用——文档说明书。


@auhor 

@version

@param arr

@return


dos命令行中输入命令:javadoc -d Myhelp -author-version arrayToo.java

其中-d myhelp  表示创建myhelp目录(注意是在java文件夹的同目录下)

-author 和-version 表示生成作者和版本

      

     



Java中的javadoc工具就会帮我们完成说明文档也称API的制作。



 



 

  设计模式----单例设计模式(饿汉式与懒汉式


单例设计模式的作用:使一个类在内存中只存在一个对象。 (EditPlus中背景颜色的设置就是单例设计模式的体现)

用代码实现单例设计模式需要做三部:

        1、将构造函数初始化。

              例:private Single(){}

        2、在类中创建一个本类对象。

              例:private static Single s= newSingle();

        3、提供一个访问方法可以获取到该对象。

              例:public static Single getInstance()

                     {

                            return  s;

                      }


单例设计模式有两种写法:

        1、饿汉式:Single类一进内存,就已经创建好了对象。在实际开发中,出于安全考虑,建议使用饿汉式。

完整代码如下:

class Single  {       private static Single s=new Single();       private Single(){}       public static Single getInstance()       {            return s;       }  }  



   2、懒汉式:特点是对象方法被调用时(getInstance()时),才初始化,这也叫对象的延时加载, (如果多个应用在同事调用这个方法,可能会new出多个独立对象,存在安全隐患)

class Single  {       private static Single s=null;       private Single(){}       public static Single getInstance()       {            if(s==null)                  s=new Single();            return s;       }  }  


  懒汉式想要消除安全隐患可以这样写:

//懒汉式安全版class Single  {       private static Single s=null;       private Single(){}       public static Single getInstance()       {            if(s==null)     synchronized()   //加上安全锁,如果为空可以排队一个个进去    {  if (s==null)  {  s=new Single();    }    }                         return s;       }  }  







   继承


 

特点

        1、提高了代码的复用性。

        2、让类与类之间产生了关系。有了这个关系,提供了多态的前提。

        注意:Java语言中,只支持单继承,不支持多继承。例:一个儿子只能有一个父亲。

        原因:因为类与类多继承的话,容易带来安全隐患。如:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪个一个。

        但是Java保留了这种机制,并用另一种体现形式来完成。叫多实现。

 


        super的使用和this的使用几乎一致,且两者都存在于方法区中。

              this表示本来对象的引用。    

              super表示父类对象的引用

2、函数——覆盖

       当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这种情况是函数的另一个特性:重写(覆盖)。

       当子类继承父类,沿袭了父类的功能,到子类中。但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。子类同时具有父类方法中的内容时,可以用super.方法();


  注意:1、子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。

             2、静态只能覆盖静态。

             3、父类中的私有方法不能被重写。

             4子父类中相同名函数不能返回不同类型值

小知识点:

       重载:只看同名函数的参数列表。

       重写:子父类方法要一模一样。


 

     子类中 构造函数特征:

       在对子类对象进行初始化时,子类的每一个构造函数默认第一行有一条隐式的语句super();

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


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

        因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。

        所以子类在对象初始化时,要先访问一下父类中的构造函数。


       如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。在上面的示例中已经有了很好的体现。

       注:super语句一定定义在子类构造函数中的第一行。


       注意:如果父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数



小知识点:

为什么this()和super()不能在同一个构造函数中?

       因为它们两个都必须出现在第一行!

为什么必须出现在第一行?

       因为初始化动作要先做。



JAVA中this关键字的两种用发:

1、表示对当前对象的引用!

2、用于在构造方法中引用满足指定参数类型的构造器(其实也就是构造方法)。但是这里必须非常注意:只能引用一个构造方法且必须位于开始!




知识点:final关键字

       继承的出现,打破了对象的封装性,使得子类可以随意复写父类中的功能。

       这也是继承的一大弊端。 为了解决这一弊端 ,介绍java新的关键字——final(最终)。


   final作为一个修饰符。具有以下特点:

        1、可以修饰类、函数、变量。

        2、被final修饰的类不可以被继承。这样就可以避免被继承、被子类复写功能。

        3、被final修饰的方法不可以被复写。

        4、被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。

       当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过_连接。

        5内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量

 



     抽象类


 

抽象类的特点

        1、抽象类和抽象方法必须用abstract关键字来修饰。

        2抽象方法只有方法声明,没有方法体,定义在抽象类中。

        3、 抽象类不可以被实例化,也就是不可以用new创建对象。

        4抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则该子类也是抽象类。



抽象类与一般类的区别

        1、事物中出现了一些不知道具体内容的方法部分。无法定义主体。通过抽象方法来表示。

        2、抽象类比一般类多了个抽象函数。就是在类中可以定义抽象方法。

        3、抽象类不可以实例化。

        4抽象类虽然不能创建对象,但是也有构造函数。供子类实例化调用。


注意:抽象类中可以一个抽象方法方法都没有。

注意:1、被abstract修饰的函数不能同时被privatefinalstatic修饰。

      原因:

                final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。

                private:抽象类中的私有的抽象方法,不被子类所知,就无法被复写。

                           而抽象方法出现的就是需要被复写。

                static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。

                            可是抽象方法运行没意义。


             

  小练习:  利用抽象类 写一个获取一段程序的运行时间小程序 ,大家自己想想吧


   接口

一、概述

             当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。接口使用interface来表示,子类中用implements实现。格式为:

                      interface 接口名{}   

        子类名 implements接口名{}

格式特点:

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

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

               常量:public static final

               方法:public abstract

        3、 接口中的成员都是public的。

              在使用中,常量可以不写public static final,方法可以不写publicabstract,编译时Java会自动添加这些修饰符,因为这是固定的格式修饰符。但为了方便阅读,通常我们都写上。

 

二、特点

        1、接口是对外暴露的规则。

        2、接口是程序的功能扩展。

        3、接口的出现降低耦合性。

        4、接口可以用来多实现。这也是对多继承不支持的转换形式。java支持多实现。

        5、类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。

        6、 接口与接口之间可以有继承关系。而且可以多继承。

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

           2、实现多个接口时,接口中不可以有返回不同类型的同名抽象函数。这样子类实现时将不能复写。

 

三、接口与抽象类区别


                1、抽象类体现继承关系,一个类只能单继承。

                    接口体现实现关系,一个类可以多实现。同时接口与接口之间有继承关系。

                2、抽象类是继承,是 "is a "关系。

                    接口是实现,是 "like a"关系。

                3、抽象类中可以定义非抽象方法,供子类直接使用。

                    接口的方法都是抽象接口中的成员都有固定修饰符。

                4、抽象类中可以私有变量或方法。

                5接口可以继承接口,接口之间可以实现多继承(extends)。

    

0 0