< 今日心情 >塞满电池加上酱油,fighting!
一、 面向对象的概念
1.面向对象是一种思想
一个小孩的诞生,都会有哪些属性呢?
姓名(小名):狗蛋生日:某年某月某日(某时)动作(方法):哭基本上,不管李家生了个小孩,还是孙家生了个,我们都会去做这些动作,这个就是面向过程的。
面向过程:
强调的是功能行为。
现在我们不这么做了。我们把这些过程封装起来形成一个具有属性和功能的类,每次诞生一个小孩只需一个命令调用这个类来创建出一个对象(具体过程交由jvm来实现),那么这个对象就有了这些功能和属性,我们只需要对这个对象进行操作即可。这就是面向对象思想。
面向对象:
将功能封装进对象,强调具备了功能的对象。
面向对象和面向过程都是一种思想,面向对象是基于面向过程而言的。
2.面向对象特点
是一种符合人们思考习惯的思想;
可以将复杂的事情简单化;
将程序员从执行者转换成了指挥者;
完成需求时:
先要去找具有所需的功能的对象来用;如果该对象不存在,那么创建一个具有所需功能的对象;这样简化开发并提高复用。3.面向对象开发,设计,特征
开发的过程:
其实就是不断的创建对象,使用对象, 指挥对象做事情。
设计的过程:
其实就是在管理和维护对象之间的关 系。
面向对象的特征:
封装(encapsulation)继承(inheritance)多态(polymorphism)
二、 类和对象的关系
1.类与对象
李家生了一个小孩,叫狗蛋,要想创建这个对象就要有描述小孩的类。孙家又生了一个小孩,叫臭蛋,难道还要定义一个臭蛋的类吗?
姓名这个属性是该类对小孩的描述,至于具体叫什么就不管了,那是对象要做的事。
那么类和对象到底有什么关系呢?
其实类就是:对现实生活中事物的描述。
对象是:与描述相符合的一个实实在在的个体。
创建对象就是将描述具体化,细致化,就是将类中的属性赋予具体的值。
注:不能单独的为了建造一个汽车去建造一个汽车厂,同样不能为了实现一个或一些功能而单独定义类,类是对有共性属性和方法的事物的描述。
2.类的定义
类是事物的描述,描述的就是事物的属性和行为。定义类其实就是在定义属性和行为。理所当然,定义在类中的属性和行为都是该类的成员,属性就是成员变量(类中定义的变量),行为就是成员函数(类中定义的函数)。
类中的变量有成员变量和局部变量。成员变量:
成员变量定义在类中,在整个类中都可以被访问。成员变量随着对象的建立而建立,存在于对象所在的堆内存中。局部变量:成员变量有默认初始化值。
局部变量只定义在局部范围内,如:函数内,语句内等。局部变量存在于栈内存中。作用的范围结束,变量空间会自动释放。
局部变量没有默认初始化值。
注:在函数中定义了与成员变量相同的局部变量,如果不加描述,在该函数中访问和修改的都是局部变量,对应的成员变量与函数操作无关。
在一个叫狗蛋小孩抱着一个叫狗蛋的小狗,小狗的死活对小孩并无关系。
2.创建对象
class Baby//定义一个描述小孩的类 { String name;//成员变量,对小孩姓名的描述 String birth; public void ku()//成员函数,小孩会哭 { System.out.print("wawa"); } public void dogOver()//成员函数,小孩会哭 { String name="狗蛋";//局部变量,小狗的名字 System.out.println(","+name+"死啦!"); } } class Test { public static void main(String[] args) { Baby bb=new Baby();//创建一个描述了小孩的类的对象 bb.name="gou dan";//给这个孩子命名 bb.birth="2014.10.01";//记录孩子的出生日期 bb.ku();//让这个小孩哭一次 bb.dogOver();//因为小狗死啦 System.out.println("这个孩子叫:"+bb.name);//查看小孩的姓名 } }
对象在内存中的结构:
只要是个小孩他都会哭,现在我只想听听这种哭声怎么办?(好邪恶啊!)
可以这么做:new Baby.ku();
这就是匿名对象及调用。单独匿名一个对象一般没有意义。
匿名对象是对象的简写形式。
匿名对象使用情况:
当对对象方法仅进行一次调用的时;
匿名对象可以作为实际参数进行传递。
三、 封装
是指隐藏对象的属性和实现细节,仅对外提供 公共访问方式。
小孩哭都是有原因的,环境原因或者生理原因都会造成小孩哭,所以对象外部不需要单独访问小孩的哭行为。只需要用private修饰这个哭方法一下就可以了,这也是一种封装。private :私有,权限修饰符:用于修饰类中的成员(成员变量,成员函数)。class Baby//定义一个描述小孩的类 { String name;//成员变量,对小孩姓名的描述 String birth; private void ku()//成员函数,小孩会哭 { System.out.print("wawa"); } public void dogOver()//成员函数,小孩会哭 { String name="狗蛋";//局部变量,小狗的名字 ku(); System.out.println(","+name+"死啦!"); } } class Test { public static void main(String[] args) { Baby bb=new Baby();//创建一个描述了小孩的类的对象 bb.name="gou dan";//给这个孩子命名 bb.birth="2014.10.01";//记录孩子的出生日期 //bb.ku();//让这个小孩哭一次 bb.dogOver();//因为小狗死啦 System.out.println("这个孩子叫:"+bb.name);//查看小孩的姓名 } }
私有只在本类中有效。
将ku()似有后,即使创建对象,通过对象也不能直接调用这个方法。小孩也是个人,你不能随便让它哭。想让他哭怎么办?杀掉他的狗狗,肯定能让他哭起来的(我又邪恶了,^_^)。
成员变量也可以似有化,外部想访问,只能通过类中的成员函数,没有提供这种成员函数外部就不能访问了。
四、 构造函数
小孩出生时往往都伴随着一个哭的动作,但是ku()已经被私有了,怎么办?此时再通过“杀狗”来让小孩哭已经不现实,再者说,哭是伴随着出生而发出的动作,此时就需要一个构造函数。class Baby//定义一个描述小孩的类 { String name;//成员变量,对小孩姓名的描述 String birth; Baby()//空参数的构造函数 { ku(); } private void ku()//成员函数,小孩会哭 { System.out.print("wawa"); } public void dogOver()//成员函数,小孩会哭 { String name="狗蛋";//局部变量,小狗的名字 ku(); System.out.println(","+name+"死啦!"); } } class Test { public static void main(String[] args) { Baby bb=new Baby();//创建一个描述了小孩的类的对象 //bb.name="gou dan";//给这个孩子命名 //bb.birth="2014.10.01";//记录孩子的出生日期 //bb.ku();//让这个小孩哭一次 //bb.dogOver();//因为小狗死啦 //System.out.println("这个孩子叫:"+bb.name);//查看小孩的姓名 } }
注:在创建对象的时候就完成的动作放在构造函数中。
构造函数的特点:
函数名与类名相同;
不用定义返回值类型;
不可以写return语句。
作用:
给对象进行初始化。
默认构造函数:在不给类添加构造方法时,类中有一个默认的构造空参数空内容的构造函数。
一个类中可以有多个构造函数,也就是说构造函数可以且必须重载
注意:一旦手动添加了构造函数,程序中的默认构造函数就不存在了。
构造代码块:
格式:一对独立的大括号。
作用:
给对象进行初始化。
对象一建立就运行,而且优先于构造函数执行。
和构造函数的区别:
构造代码块是给所有对象进行统一初始化,
而构造函数是给对应的对象初始化。
五、 this关键字
前面说过,局部变量的名字和成员变量的名字一样时,在方法中访问的是局部变量,那么如何让局部变量的值传递给同名的成员变量呢?class Baby//定义一个描述小孩的类 { String name="haha";//成员变量,对小孩姓名的描述 String birth; Baby() { ku(); } Baby(String name,String smallName) { System.out.println("姓名:"+name);//验证访问name变量到底是局部位置那个还是成员位置的那个 name=smallName;//改变name的值 this.name=name;//将局部变量的值赋值给成员变量 } private void ku()//成员函数,小孩会哭 { System.out.print("wawa"); } public void dogOver()//成员函数,小孩会哭 { String name="狗蛋";//局部变量,小狗的名字 ku(); System.out.println(","+name+"死啦!"); } } class Test { public static void main(String[] args) { Baby bb=new Baby("张三","狗蛋");//创建一个描述了小孩的类的对象 //bb.name="gou dan";//给这个孩子命名 //bb.birth="2014.10.01";//记录孩子的出生日期 //bb.ku();//让这个小孩哭一次 //bb.dogOver();//因为小狗死啦 System.out.println("这个孩子叫:"+bb.name);//查看小孩的姓名 } }
似乎this可以区别同名的局部变量和成员变量,这是为什么呢?
this:就代表本类的对象;代表它所在函数所属对象的引用。
其实就是在对哪个对象操作就代表了哪个对象。
在构造函数中可以使用this()来调用其他重载的构造函数,参数的多少和类型与被调用者一致。如:class Baby//定义一个描述小孩的类 { String name="haha";//成员变量,对小孩姓名的描述 String birth; Baby() { ku(); } Baby(String name,String smallName) { this(); System.out.println("姓名:"+name); name=smallName; this.name=name; } private void ku()//成员函数,小孩会哭 { System.out.println("wawa"); } public void dogOver()//成员函数,小孩会哭 { String name="狗蛋";//局部变量,小狗的名字 ku(); System.out.println(name+"死啦!"); } } class Test { public static void main(String[] args) { Baby bb=new Baby("张三","狗蛋");//创建一个描述了小孩的类的对象 //bb.name="gou dan";//给这个孩子命名 //bb.birth="2014.10.01";//记录孩子的出生日期 //bb.ku();//让这个小孩哭一次 //bb.dogOver();//因为小狗死啦 System.out.println("这个孩子叫:"+bb.name);//查看小孩的姓名 } }
注意:构造函数间调用,this必须放在构造函数的第一行。
this的应用:
当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。
但凡本类功能内部使用了了本类对象,都用this表示。
六、static关键字
在对事物进行描述时往往会有一些通用的属性值,比如描述一个圆的时候,π一样的。小孩也有这样的值,比如:两个胳膊两条腿,一个脑袋一张嘴这个时候我们用static来修饰这些变量或方法。
被修饰后的成员具备以下特点:
随着类的加载而加载
优先于对象存在
被所有对象所共享
可以直接被类名调用
注意:
访问被static修饰的成员:静态方法只能访问静态成员
静态方法中不可以写this,super关键字
主函数是静态的
类名.被static修饰的变量名
类名.被static修饰的函数名
七、static关键字的应用
static修饰构造函数
单例设计模式:
禁止外部创建对象。
自身提供一个本类对象给外部使用。
保证了本类对象的唯一性。
class Baby//恶汉式 { String name; private static Baby bb = new Baby();//先创建对象 private Baby() { } public static Baby getBaby() { return bb; } } class SingleDemo { public static void main(String[] args) { Baby bb1=Baby.getBaby(); bb1.name="gou dan"; Baby bb2=Baby.getBaby(); bb2.name="çu008Bu0097ču009Bu008B"; System.out.println("bb1:"+bb1.name); System.out.println("bb2:"+bb2.name); } } class Baby//懒汉式,多线程不安全 { String name; private static Baby bb = null; private Baby() { } public static Baby getBaby()//调用的时候创建对象 { if(bb==null) Baby.bb=new Baby(); return bb; } } class SingleDemo { public static void main(String[] args) { Baby bb1=Baby.getBaby(); bb1.name="gou dan"; Baby bb2=Baby.getBaby(); bb2.name="狗蛋"; System.out.println("bb1:"+bb1.name); System.out.println("bb2:"+bb2.name); } } class Baby//懒汉式,多线程安全 { String name; private static Baby bb = null; private Baby() { } public static Baby getBaby() { if(bb==null) { synchronized(Baby.class)//加锁,多线程安全 { if(bb==null) Baby.bb=new Baby(); return bb; } } } } class SingleDemo { public static void main(String[] args) { Baby bb1=Baby.getBaby(); bb1.name="gou dan"; Baby bb2=Baby.getBaby(); bb2.name="狗蛋"; System.out.println("bb1:"+bb1.name); System.out.println("bb2:"+bb2.name); } }
static修饰代码块
静态代码块:随着类的加载而运行,只运行一次。
class Baby { static{ System.out.println("ha ha ha"); } public void ku() { System.out.println("wawawa"); } } class StaticDemo { public static void main(String[] args) { Baby bb=new Baby(); //bb.ku(); Baby bb2=new Baby(); bb.ku(); bb2.ku(); } }