---------------http://www.itheima.comjava培训、android培训期待与您交流!---------------
相信大家都听说过这个脑筋急转弯:把大象放冰箱里,需要怎么做(需要哪三步)?相信大家都会不假思索地说出来。是的,第一步,打开冰箱门;第二步,把大象放进冰箱;第三步,关上冰箱门。这也是毕老师对面向对象的一个讲解的最形象的、最易于理解的一个例子(只有把学到的东西用生活的语言讲出来才是最好的一种理解方式)。
一切来源于生活。是的,正是有了对生活的更好理解,才会研发出那么多的技术更好的为生活服务。其实,这些技术是从生活中总结出来的。呃,,不好意思,有点扯远了。步入正题(嘻嘻)。。。
首先,先研究研究那个把大象放进冰箱的脑筋急转弯:
从一个角度说,把大象放进冰箱,就那三步(脑筋急转弯嘛),打开冰箱,把大象存进冰箱,关上冰箱。在这里,我们强调的是我们对冰箱做的这几个动作:打开,存进,关闭。这种强调动作的的行为(强调功能行为),我们称之为 面向过程 ,这在C语言中十分常见。简单地说,我们把大象放进冰箱,我们是一个执行者,是我们在操作冰箱,我们在指挥着冰箱在做某些事(开,存,关)。
而显然,冰箱自己是具有这些功能(开,存,关)的,我们看不到冰箱的具体操作动作,如冰箱是如何开的,因为冰箱门有一些能够滑动的零件,冰箱可以实现开,关的这些动作。这是冰箱自带的。只是我们人为地将冰箱自带的这些功能当做是我们施加给冰箱的外力。那么,我们 换一个角度 思考 ,将冰箱看做是一个事物,或者是一个对象。因为冰箱自己是具有哪些功能的(开,存,关),所以,我们就想象着我们指挥 冰箱打开,冰箱存储,冰箱关闭。这时,我们就是在面对着一个事物,让这个事物将自身所具有的一些功能展现出来,那么,我们就不必去强调那些动作(这些动作可能是多个,甚至更多),只要我们只操作这个对象(事物),那么,我们需要这个事物的哪些功能就操作哪些功能,这样,问题就变得简单了。这种强调对象(事物)的行为称之为 面向对象 。
简单地说,面向对象就是将一个事物的自身所具有的功能隐藏(封装,后面会将到的)起来,当我们需要某些功能的时候只要把这个事物(对象)拿来,对事物(对象)进行特定的操作(调用)就能满足我们的需要(需要哪些功能)。面向对象其实是一种思考问题的另一种简化方式,我们不需要了解过程是怎样的,我们只需要结果。所以,他的好处就在于把复杂的问题简单化。
简单地举几个例子吧(毕老师的经典例子就不重复了,讲个我自己理解的吧):拿我们经常用的笔记本来说吧(因为我现在正在用它,嘻嘻):我现在正面向着一个对象,这个对象就是笔记本。因为我想要使用笔记本的一些功能,比如,我现在正在打字,我就在使用(调用)笔记本的打字功能。我不需要知道笔记本到底是怎么实现打字功能的,我只要敲笔记本上的键盘就可以在文本文件中打字来满足自己的需求。当然,笔记本还有很多功能:开机,关机,散热,上网等等。
引用毕老师的经典语录吧:“万物皆对象”。当然,这还要自己慢慢理解、体会。
面向对象的三个特征:封装、继承、多态。在开发过程中,就是在找对象,建立对象,使用对象和维护对象关系的过程。
一、类与对象的关系
1、类:对具有相同属性和行为的事物的描述。
对象(对象在堆中):用关键字 new 创建的一个实体,也就是事物的一个实例(个体)。
在描述事物(类)时,一般描述的是事物的属性和行为。
一般属性是类中的变量,行为是类中函数或方法,统称为类中成员变量、成员方法。
比如:描述人,人的属性(姓名、性别、年龄等)和行为(行走,吃饭,哭等)
class Person { //描述人的属性 String name; int age; //描述人的行为 void walk(){} } class PersonDemo{ public static void main(String[] args) { //创建人的实体(人的实例化) Person p = new Person(); //P 是类类型变量,指向子类对象 //调用对象成员 格式:对象.对象成员 p.name = "wangting"; p.age = 22; p.walk(); } }
分析一下在内存中的存储情况:人只是笼统的一类事物,而每个人则是这一类人的具体(看的见摸的着)的一个个体。在创建人的实体时,在栈内存中就创建了P这个具体对象,P对应着有一个地址值,这个地址值就指向了堆内存中在堆内存中就存储了P这个对象的具体的一些属性(name = "wangting"; age = 22)。
2、成员变量/局部变量
其作用域不同:
成员变量作用于整个类中,存储在堆内存中,且有默认值(0)。
局部变量作用于函数或语句中,存储在栈内存中,需要初始化。如:for循环中的变量,只要循环一结束,其中的变量就会被释放。
3、匿名对象的应用
比如,在创建对象并调用方法时,上面的例子可以写成匿名对象
Person p = new Person();
p.name = "wangting";
p.walk();
------可写成:
new Person().name = "wangting"; //这是无意义的
new Person().walk();
需要注意的是:匿名对象调用方法有意义,而调用属性无意义。
使用方式一:对对对象的方法只能调用一次
使用方式二:可将匿名对象作为实际参数进行传递。show(new Person());
二、封装
1、封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
就我的理解来说,我认为,封装就是将对象的一些属性或者功能(比如说冰箱具有开、关的功能),我们可以不知道它实现开、关的细节(零件),但应当对外提供一些方式(外力),当用的时候通过调用这个对象的一些方法来实现(开关的动作)。
好处:将变化隔离、便于使用、提高重用性、提高安全性(例子:台式机的机箱,当机箱中的部件坏了时,只需要换掉(隔离)就可以再次使用(重用性)。我们不需要知道里面的构造(封装),只要使用就可以。)
封装原则:将不需要对外提供的内容都隐藏起来、把属性都隐藏,提供公共方法对其访问
2、private:修饰符,关键字。
权限修饰符。用于修饰类中的成员(成员变量、成员方法(函数))。
私有只在本类中有效。
当有些功能不需要对外提供的时候,我们可以用private修饰。
3、构造函数、构造代码块
构造函数:
写法规范:
(1)函数名和类名一致
(2)不用定义返回值,与一般方法不同(一般方法在没有返回值时写void)
(3)不可写return语句
构造函数的作用:
用于给对象进行初始化动作(初始化就是事物特有的属性和行为,如:name,age)
什么时候使用构造函数?
(1)当描述(分析)事物时,事物本来就具有某种特性和行为时
(2)在判断有无未知参数时,这时用于传参
当一个类中未定义构造函数时,系统会默认添加一个空参的构造函数。
对象一建立,就立即调用对应的构造函数(空参,一个参数,几个参数),默认值为null。
构造代码块(笔试常见):
作用:给所有对象进行初始化。表现的是对象们所具有的共性。
优先于构造函数执行。
4、this关键字
应用情况:当成员变量和局部变量相同时。哪个对象调用,this就代表哪个对象。
5、static
static是一个修饰符,可用于修饰成员变量或者函数。可被对象调用,被类直接调用。
格式为:类名.静态成员
对象初始化前就已经存在(优先于对象存在)。 且存在于方法区中。
类变量存在于方法区中,且随着类的消失而消失。
实例变量存在于堆区中,随着对象的消失而消失。
注意:(1)静态方法只能访问静态成员,非静态方法可访问非静态,也可访问静态(静态成员优先存在)。(2)静态中不能有this、super。
静态应用:用于修饰静态成员。当修饰变量时,该变量是共享数据,并非属性。
当修饰函数时:当功能中未访问到对象的特有数据时。
静态代码块:优先于主函数执行。
7、单例设计模式 详见博客 黑马程序员---单例设计模式
三、继承
1、概述:简单滴说,继承是事物间的一种关系(子类不断向上抽取形成的父类)。
举个例子:当我们在描述学生类的时候,他的属性和行为分别是name,age和study。而描述工人的时候,他的属性和行为分别是 name,age和work。通过分析,我们知道,学生类和工人类都具有姓名和年龄这两个属性,而行为不同,那么,我们就可以将姓名和年龄属性定义到另一个类Person中。也就是说,学生类和工人类中的共有特性都向上抽取形成一个单独的类Person,这时学生类、工人类和Person类就有了某种关系,这个关系就是继承。表示类与类之间的关系,并用关键字extends来标识这种关系,这种关系是所属关系。只要子类继承了父类(超类、基类),那么子类中就自然的有了父类中的内容。
继承的特点:
提高了代码重用性,当然,不能单纯的为了简化代码或者使用一些共性属性而使用继承。
类与类产生了关系,有了关系才有了多态。
要注意的是:
java中只支持单继承(只能继承一个类),不支持多继承,但支持多实现。因为多继承会出现安全隐患,比如,父类中定义了功能,但功能内容不同,那么子类对象就不确定要运行哪一个。
java支持多层继承,也就是说C继承了B,B继承了A,那么,C也可以继承A。
这时就形成了继承体系,在查阅继承体系时,要先查阅父类中定义的功能,创建子类对象使用功能。
2、类与类之间的其他关系
类与类之间的以下关系其实是类与类之间紧密联系的程度。
聚集关系:has a
聚合关系:比如球队和球员的关系。球队可以没有其中的某个球员,因为可以再找。
组合关系:人类器官和人的关系,人没有了某个器官是不行的。紧密关系最高。
3、子父类中类成员的特点
(1)变量
当子类与父类的非私有变量相同时:
子类访问本类(子类)中的变量,用this(代表本类对象的引用)。
若子类访问父类中的变量,则使用super(父类对象引用)。
(2)函数
当子类中函数名与父类中函数的方法名一样时,子类会覆盖父类的方法,也就是重写。重写的原理就是子类沿袭(保留)父类功能,并改变父类功能的具体内容,有利于功能扩展。
需要注意的是:
子类覆盖父类是,必须保证子类的权限大于等于父类的权限,否则编译失败。
重写与重载的区别:
重载:只看同名函数的参数列表
重写:子父类方法要一模一样,包括返回类型。
(3)构造函数---子类实例化过程
在对子类对象进行初始化时,父类构造函数也会运行。
子类实例化过程:
子类中所有的构造函数,默认都会访问父类中空参数的构造函数。因为子类么一个构造函数内的第一行都有一句隐式super();
当父类中没有空参数的构造函数时,子类必须手动通过super语句来指定要访问父类中的构造函数。
当然,子类的构造函数第一行也可以手动制动this语句来放哪寡恩本类中的构造函数,子类中至少会有一个构造函数会访问父类中的构造函数。
6、final 关键字
(1)可修饰类、变量、函数
(2)被final修饰的类不能被继承
(3)被final修饰的方法不可被复写
(4)被final修饰的变量是一个常量,只能赋值一次。
即可修饰成员变量,也可修饰局部变量。常量都大写
(5)内部类定义在类中的局部变量位置上时只能访问该局部都被final修饰的局部变量。
7、抽象类---不可实例化
抽象类,从字面上理解就是一些笼统的、不明确(看不懂)的类。也就是说,在描述事物的功能时,不同的事物的功能相同,但功能主体不同。比如:建筑专业的学生和软件专业的学生,他们都具有学习的功能,但他们学习的内容不同,这时就应该把学生定义成抽象类,学生中的学习方法定义成抽象方法,然后让其具体子类复写其学习(study)抽象方法,建立子类对象调用即可,当然,无论是建筑专业的学生还是软件专业的学生,他们都有吃饭这个功能,那么这个共性方法就可以定义在父类(Student)中.
具体代码如下:
//定义一个抽象类Student(这个类是建筑和软件学生类的相同功能向上抽取得来的) abstract class Student { //定义抽象方法study();(建筑专业学生类和软件专业学生类共同的学习功能) //没有方法体 abstract void study(); //也可定义一般方法:建筑专业学生和软件专业学生共有的功能 吃饭 void eat() { System.out.println("I can eat!!!"); } } //定义Student的子类ConsStudent class ConsStudent extends Student { //复写抽象方法,用于实现自己特有的学习内容(建筑课程) void study() { System.out.println("我学习建筑课程"); } } //定义Student的子类SoftStudent class SoftStudent extends Student { ////复写抽象方法,用于实现自己特有的学习内容(软件课程) void study() { System.out.println("我学习软件课程"); } } class AbstractDemo { public static void main(String[] args) { //建立子类对象,并调用子类复写的方法,实现自己学习的不同内容 //new ConsStudent().study(); ConsStudent cs = new ConsStudent(); cs.study(); cs.eat(); new SoftStudent().study(); new SoftStudent().eat(); //SoftStudent ss = new SoftStudent(); //ss.study(); } }
抽象类一些注意的地方:
(1) 抽象方法一定在抽象类中
(2)抽象方法和抽象类都必须用abstract关键字修饰
(3)抽象类不能用new创建对象,调用抽象方法无意义
(4)抽象类中的抽象方法要被使用,必须由子类复写所有的抽象方法后,建立子类对象调用。
(5)若子类只覆盖了父类的部分抽象方法,那么该子类还是抽象类
(6)抽象类其实和一般的类一样,只不过抽象类中有一些不明确的方法。所以,抽象类中可定义抽象方法,也可定义一般方法。
8、模板方法设计模式
需求:获取一段程序的运行时间=程序运行的开始时间 - 结束时间
获取时间:System.currentTimeMillis();
模版方法:在定义功能时,功能的一部分是确定的,但有一部分是不确定的,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去。
模版方法设计模式提高了程序的扩展性,代码重用性。
注意:模版方法不一定都是抽象的,只要子类需要实现某些功能,就需要用此模式,若不需要子类复写的方法用final修饰。
具体代码如下:
//定义一个抽象类,因为我们不需要知道机器是怎么获取的 abstract class GetTime { //子类不能复写getTime方法,我们 public final void getTime() { long start = System.currentTimeMillis(); runcode();//调用方法 long end = System.currentTimeMillis(); System.out.println("毫秒:"+(end-start)); } //把运行语句封装起来,方便调用 //因为运行的内容不一样,所以将方法设置为抽象 public abstract void runcode(); } //要显示另一程序的运行时间就要继承GetTime class SubTime extends GetTime { //复写runcode方法,定义自己的运行代码 public void runcode() { for (int x=0;x<1000;x++ ) { System.out.print(x); } } } class Template { public static void main(String[] args) { //建立子类对象并调用复写的方法 SubTime sb=new SubTime(); sb.getTime(); } }
---------------http://www.itheima.comjava培训、android培训期待与您交流!---------------
发表评论
-
黑马程序员---IO流(2)
2013-05-30 10:03 960-------http://www.itheima.comja ... -
黑马程序员---集合框架
2013-05-19 20:10 959-------http://www.itheima.comja ... -
黑马程序员----面向对象---异常
2013-05-16 17:31 722[size=small] -------http://www. ... -
黑马程序员---String、StringBuffer、StringBuilder
2013-05-23 18:44 1165-------http://www.itheima.comj ... -
黑马程序员---面向对象---接口、多态、Object类、内部类
2013-05-23 21:48 822-------http://www.itheima.comj ... -
黑马程序员 --- 面试
2013-05-31 14:03 994-------http://www.itheima.comja ... -
黑马程序员---GUI
2013-05-30 09:14 941-------http://www.itheima.comj ... -
黑马程序员---java高新技术
2013-05-31 14:03 933-------http://www.itheima.comja ... -
黑马程序员---网络编程
2013-05-31 14:03 998-------http://www.itheima.comja ... -
黑马程序员---java基础
2013-05-16 18:20 1001-------http://www.itheima.comja ... -
黑马程序员---IO流(1)
2013-05-30 09:53 1033-------http://www.itheima.c ... -
黑马程序员---多线程
2013-04-14 14:31 843... -
黑马程序员---单例设计模式
2013-04-14 14:29 808------- http:/ ... -
黑马程序员---泛型
2013-04-14 14:15 480-----http://www.itheima.comjava ...
相关推荐
### 黑马程序员入学Java精华总结 #### 一、Java概述与基础知识 1. **何为编程?** - 编程是指通过编写计算机能够理解的指令来解决问题或完成特定任务的过程。这些指令通常被组织成算法,并使用某种编程语言实现。...
### 黑马程序员入学Java知识 #### Java概述与基础知识 1. **何为编程?** - 编程是通过特定的计算机语言来编写指令,让计算机能够执行一系列任务的过程。 2. **Java语言概述,历史、特点** - Java是一种广泛...
- **面向对象**:Java支持面向对象编程,包括封装、继承、多态等。 - **平台无关性**:Java程序可以在任何安装了Java虚拟机(JVM)的平台上运行。 - **安全性**:Java提供了严格的内存管理机制,减少了内存泄漏和...
Java是一种典型的面向对象编程语言,其核心特性包括封装、继承与多态。 - **封装**:通过隐藏对象的属性和实现细节,仅对外提供公共访问方式来保护数据。 - **继承**:子类可以继承父类的属性和方法,并在此基础上...
这一章将介绍面向对象编程的基本理念,包括封装、继承和多态这三大特性。面向对象编程是现代软件开发中的主流范式,它使得代码更易于维护和扩展。通过实例解析,学员会理解为何面向对象是解决复杂问题的有效方法。 ...
4. **封装、继承和多态**:这是面向对象编程的三大特性。封装隐藏了对象的实现细节,提供了公共接口供外部使用;继承允许子类继承父类的属性和方法,实现了代码复用;多态则允许不同类的对象对同一消息做出不同的...
- **类与对象**:Java是一种面向对象的语言,类是对一组具有相同属性和行为的对象的抽象描述。对象则是类的实例。 - **封装**:封装是指隐藏对象的具体实现细节,只对外提供公共接口的方法。 - **继承**:继承允许...
类可以实现数据的抽象和封装,提高代码的可重用性和可读性。 第7章 操作符重载 操作符重载是指对操作符的重新定义,使其可以用于自定义的数据类型上。操作符重载可以提高代码的可读性和可维护性。 第8章 继承――...
而"黑马程序员_毕向东_Java基础视频教程第05天-06-面向对象(封装概述).avi"则会引导你理解封装的重要性,教你如何在实践中实现封装,提升代码质量。 总的来说,这套视频教程对于想要学习Java编程的初学者来说是一份...
面向对象编程是Java的核心之一,理解其基本概念对程序员至关重要。 1. **封装:** - **定义:** 封装是将对象的状态信息(即数据成员)隐藏在对象内部,不允许外部程序直接访问,而是通过对象自身所提供的方法(即...
- **泛型概述**:泛型是Java 5引入的新特性,它允许程序员在编译时检查类型安全,并且所有的强制转换都是自动和隐式的。 - **泛型应用**:在定义类、接口时可以使用泛型参数,增强代码的灵活性和复用性。 #### 8. ...