黑马程序员_面向对象(封装)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 

面向对象(封装) 

一、对于面向对象的理解

 

大学里面都学过c语言,c语言相对java来说是一种面向过程的语言,而java语言就是面向对象,面向对象时相对面向过程而言的,两者都是一种思想。

具体而言,面向过程更强调的是功能行为和过程,就是说实现某个功能的过程,;面向对象则是,把某个我们的功能封装进某个对象,这个对象具备某个我们可以调用的接口或者其他,我们只需要调用这个接口,来实现这个功能,而不必知道其具体过程是怎么实现的。

举个例子来说:

         一个程序员,他会编程,公司需要他完成某个项目,公司不需要知道他具体怎么做,他怎么会的编程,只要完成公司项目就可以,这里公司调用了程序员的编程功能,公司就是一个指挥者,就是说我们是指挥者,只需调用我们需要的功能的对象即可,这就是面向对象。而程序员具体怎么完成任务,具体步骤和过程,这就是面向过程。

 

 

二、类和对象

1、类和对象的关系

两者描述:

1)类:就是对现实生活中事物的描述

2)对象:就是这类事物实在存在的个体

打个比方,比如一个建筑工程,类就是描述整个建筑工程的蓝图或者说图纸,上面关于尺寸,形状,功能都有具体的描述;对象就是依据这个图纸所建成的大楼,具有图纸上所有描述的功能和属性。相对应的,到java程序中,类就是class所定义的类,对象就是在java中通过new在堆内存中建立的实体。

描述来说比较抽象,比面向对象理解难一点,个人认为两者容易混淆,但认清两者使用方式和内存占用的话,就会区别的比较清楚。

使用方式来说:类中的属性和功能,不能直接通过类来调用(静态方法除外),只能通过建立对象来调用,就好比我们不能直接住进建筑的图纸里,但我们可以住进建好的建筑里。

内存占用来说:类,

2、对象的建立及调用

         建立一个对象,格式为:类名 对象名称 = new 类名()

         调用其中的属性和行为:对象名称.对象成员

new一个对象,就会在堆内存中建立一个对象。

 

 

 

示例程序:

class Person{

    intage=20;

    Stringname="zhangsan";

    void study(){}

}

 

Person p =new Person();

p.age=24;

p.study();

3、匿名对象

就是没有名字的对象

有名字对象:Personp = new Person();

匿名对象:  new Person();

匿名对象时对象的简化形式,只用在当对象方法仅进行一次调用的时候,而且匿名对象可以作为实际参数进行传递,这一点要注意,后面学习会用到很多。比如一个函数需要传递一个对象最为参数,这是就可以用匿名对象。

例子:new Car().color

           new Car().color

           new Car().run()

上面第一第二例子是建立了两个对象,当第二个对象建立的时候,第一对象已经变成垃圾了。而第三个对象,只调用了方法一次,这是可行的。

总而言之,匿名对象调用方式:当对象方法只调用一次时。如果对一个对象进行多个成员调用,就必须起名字了。

总结:使用方式:1、对象方法调用一次。2、作为参数

 

4、成员变量和局部变量区别

         作用范围:成员变量作用与整个类中

              局部变量作用与函数中和语句中

在内存中存储:成员变量在堆内存中(对象建立)

              局部变量存在栈内存中

 

 

三、面向对象的三大个特征

三特征:封装,继承,多态

 

 

四、面向对象:封装

封装概念:是指隐藏对象的属性和实现细节,仅保留一个公共的对外访问方式。

优点:将变化隔离,便于使用,提高复用性和安全性

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

1、封装

封装个人理解看来,就是对象的首个属性,我们将事物的属性和行为封装起来,这个对象可以实现某个功能,我们只是需要这个功能,像电视可是看节目,电脑可是显示文档,我们不需要知道其内部构造,只需一个开关点一下即可。这样,我们不用对其内部做什么改动,将变化隔离,同时提高了安全性,因为我们如果随便可以改动电视机里的电路,那么电视机就该坏了。这样我们就把具有某个工能的事物的内部封装到一个盒子里,不告诉你盒子内部有什么,也不让你操作,只给你提供一个方法,就是电视机那个按钮,这就是封装。函数就是java程序中最小的封装体。

 

 

 封装后,调用方法或者使用功能就会变得简单了,我们只需要那个公共方法就可以得到我们需要的功能。

封装就得用到一个权限修饰符private:私有,这个权限修饰符可以修饰成员变量和成员方法,使得类中成员只被本类使用,只在本类中有效。本类之外是直接不知道这个类中有这个成变量和成员方法,只能调用public修饰的公共方法来进行这个功能的访问,不需要知道内部是怎么实现这个工能的过程,及其属性和行为。注意:私有,仅仅是封装的一种表现形式。

程序例子:

class Person{

        private intage;

        private String name;

        void study(){}

}

现在类中agename被私有化了,当我们在建立对象来调用age

                            Person   p = new Person();

                            p.age=20;

这时就会报错,因为ageprivate修饰,不能访问。但我们需要设置或者获取这个age的值,所以对外提供公共方法:

                            public voidsetAge(int a){

                                     age = a;

}

Public int getAge(){

         return  age;

}

通常,每个私有属性都会有两个公共访问方式,一个是设置,一个是获取。有公共访问方式,我们就可以对外面的访问数据进行筛选或者说判断,把我需要的数据传进来,这样提高了程序代码的健壮性。

2、构造函数

特点:函数名与类名一致,不用定义返回类型,不可以写return语句

作用:给对象进行初始化

注意:有默认的构造函数,多个构造函数以重载的形式存在

 

注意不定义返回类型和void的区别:void是一种返回值类型,代表没有具体返回值类型的情况,而构造函数是根本没有返回值类型。

         构造函数示例:

class Person{

        Person(){

            执行语句

}

Person(int x){

           执行语句

}

}

上述示例就是说,构造函数名必须是类名,而且构造函数不止一个,可以有多个,以重载的形式出现,每当我们执行一次  new Person();语句的时候,就是建立对象的时候,相应的构造函数就会被执行一次,就是对象建立即运行。这样表示,构造函数是给当前对象进行初始化的。之前,我们创建一个对象的时候,也没有构造函数,但是我们还是建立了,其实是系统默认给该类加入一个空参数的构造函数,比如上路例子如果我们不加构造函数,系统就会默认给我加一个空参数的构造函数Person(){}。当我自己定义的后,就没有这个系统默认的构造函数。

所以当我们自己写下构造函数,然后建立对象的时候没有使用相对应的构造函数,那么系统就会报错。构造函数也是可以私有化的,因为也属于类的成员,但是一旦私有化,我们建立对象使用这个构造函数的时候,就会出错。

总结来说,构造函数就是对象一建立就会调用的函数,与类同名,可以重载,用于给对象初始化,准确来说是给当前使用的构造函数创建的对象进行初始化。我们在分析事物的时候,当该事物具备一些建立的时就有的特性或行为,那没就可以将这些内容定义在构造函数中。

 

3、构造代码块

         构造代码块,与构造函数类似,但又不同。

         格式为

                   {

                            执行语句;

}

 

         相对于构造函数来说,构造代码块就是“裸奔”,只有大括号包含的语句,作用也是给对象进行初始化。构造代码块和构造函数的区别

                                    相同之处:给对象进行初始化,都是对象一建立就运行

不同之处:1)构造代码块是给所有对象进行初始化,构造函数是给不同对象对象初始化。                           

                                               2)构造代码块优先于构造函数执行

                          3)构造代码块是给不同对象的相同的共性初始化的,而构造函数是给不同对象进行个性的初始化的。

 

         4this关键字

先看示例:

         class Person{

           Stringname;

Person(String name){

              this.name= name;

}

}

从程序上来看,我们传入的参数和类里的成员变量重名了,当没有this时候,name=name,就是自己给自己赋值,没有任何意义。此处,this就表示类里成员变量,从而就区分了局部变量和成员变量同名的情况。

this关键字:就代表本类的对象。可以说就是当前所调用的对象。

我们建立一个对象,对象里就会包含类中所描述的属性和行为,就像上述程序例子,我们一旦建立对象,就会有namePerson构造函数,当我们建立对象时,就会往里传一个name进行初始化,而这个构造函数被我们现在建立的这个对象所调用,所以,this就代表我们现在的这个对象。

总结的说哪个对象在调用this所在的构造函数,this就代表哪个对象且当定义类中功能时,该函数内部要用到本类对象时,就用this

 

注意构造函数间调用

类中如果我们在以个函数中调用相同类中的另一个函数,在函数中直接以函数名调用即可,在study函数中直接调用work函数,程序如下:

class Person{

       intwork(){}

        void study(){

           work();

}

}

但构造函数间就不可以这样调用,需用到this关键字,在第二个构造函数中调用第一个构造函数:

 

         class Person{

           Person(intage){

              执行语句

}

Person(int ageString name){

              this(age);

}

}

 

 


                                                                                                                        

为什么在第一行,因为初始化要先执行,如果初始化中还有初始化,那么先执行里面的初始化动作,就像上述的this调用构造函数。注意不要在两个构造函数见互相调用,会出现死循环。这种this语句只能用于构造函数之间。

 

5static关键字

 

通常,对象在建立的时候有一些共有的数据,比如人,除了个人数据如年龄,姓名每个人都会不同,但都是中国人或者都是某一国籍的人。如果我们建立对象,那么每个对象里都会有一个中国国籍,而这个国籍我们可以把它提取出来作为共有数据来使用。这里就用到了static关键字。

static是一个修饰符,用于修饰成员变量和成员函数,注意,只能修饰成员,不能修士局部。示例程序:

             class   Person{

  static  String  country = “China”;

}

 

这静态成员,可以直接被类名调用,调用方式为:类名.成员  如:Person.country

为什么可以有这些功能,这和内存有关:

之前我们学习过栈内存,堆内存,现在又有一个方法区或者是共享区、数据区。类中的共享数据和方法也在这里。

1)      静态修饰的成员,会在类的加载而加载,就是说类一加载,静态修饰的成员就会存到方法区中,也随着类的消失而消失。缺点也很明显,生命周期过长,占据方法去内存时间过长,所以不宜创建过多的静态成员。相对于对象来说,就优先于对象存在,也就优先于实例变量存在。

              ((小知识点:1、未被static修饰的成员变量,随着对象建立而存在于堆内存中,为实例变量。2、被static修饰的成员变量,因为随类的加载而加载,随类的消失而消失,存在于方法去中,称为类变量))。

2)      无法从非静态方法中引用非静态成员。因为静态优先于非静态存在,就是优先于对象存在,有静态的时候不一定有非静态,所以,静态方法只能访问静态成员。

非静态方法可以访问非静态成员也可以访问静态成员,因为内存中后出现,所以,两者都可以访问。

3)      静态方法中不可以使用thissuper关键字,因为这两个字得先建立对象,所以不可。

4 静态一点应用,如果建议一个工具类,其中没有特有数据,我们可以把方法都静态化,直接以类名进行调用即可,同时把构造函数私有化,这样就可避免不必要建立的对象。

总结:

什么时候使用静态:

        1、定义静态变量:当对象中出现共享数据时,比如国籍,所属学校

        2、定义静态函数:当功能内部没有访问到非静态数据(对象特有数据)时

6、静态的主函数

主函数是一个特殊的函数,是一个程序执行的起始点,是一个入口,可以被jvm识别并调用。

在主函数中,要注意main,这个不是关键字,但是是一个特殊的单词,可以被jvm识别。

String[] args:函数参数,是一个数组类型,其中args可以再eclipse中设置程序初始参数args的信息。在dos命令行中,可以用java类名  数据数据数据… 来给主函数中的args传值。

尤其重要的一点,主函数格式是固定的,jvm识别

 

7、帮助文档制作,中注意,只有类名被public修饰的才可以使用文档注释。

8、静态代码块(小知识)

  格式:static{

         执行语句;

}

静态代码块特点:随着类的加载而加载,可以有多个静态代码块

静态代码块作用:给类进行初始化,并且由于主函数执行,且只执行一次。

                既然是给类进行初始化,那么类一加载,静态代码块就会先执行。

小知识点:类的加载时间,如果有一下程序:Person  p = null; 这时Person这个类是没有被加载进内存的,因为此处没有意义,没有用到一点类中的成员。而只要用到类中的成员,类才会被加载,像p=new Person()Person.getAge(),这才会加载类。

 

总结:构造函数,构造代码块,静态代码块

 

 

 

初始化对象

执行次数

优先级

 

构造函数

对应对象(当前对象)

同对象建立次数

最后

 

构造代码块

所有对象

同对象建立次数

次优

 

静态代码块

只执行一次

最优(随类加载)

 

 

 

9、对象初始化过程

Person p = new Person(“zhangsan”,20);

 

这句话都做了什么?

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

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

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

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

5)  对属性进行显示初始化

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

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

8)  将内存地址值赋给栈内存的p变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值