面向过程和面向对象的区别
“面向过程”(Procedure Oriented)是一种以过程为中心的编程思想,简称 OP。“面向过程” 也可称之为“面向记录”编程思想,就是分析出解决问题所需要的步骤,然后用函数把这些步 骤一步一步实现,使用的时候一个一个依次调用就可以了。所以面向过程的编程方式关注点不 在“事物”上,而是做这件事分几步,先做什么,后做什么。例如:早晨起来:起床、穿衣、 洗漱、上班,只要按照这个步骤来,就能实现“一天”的功能,整个这个过程中关注的是一步 一步怎么做,并没有关注“人”这个事物。再例如:开门、调整座椅、系好安全带、踩离合、 启动、挂档、给油,只要按照这个步骤来,车就走了,显然关注点还是在步骤上,只要实现每 一步就行,整个过程并没有关注“汽车”这个事物。
“面向对象”(Object Oriented)是一种以对象为中心的编程思想,简称 OO。随着计算机技 术的不断提高,计算机被用于解决越来越复杂的问题。一切事物皆对象,通过面向对象的方式, 将现实世界的事物抽象成对象。通过面向对象的方法,更利于用人理解的方式对复杂系统进行 分析、设计与编程。同时,面向对象能有效提高编程的效率,通过封装技术,可以像搭积木的 一样快速开发出一个全新的系统。面向对象将对象作为程序的基本单元,将程序和数据封装其 中,以提高软件的重用性、灵活性和扩展性。Java语言是一种面向对象的程序设计语言,而面向对象思想(OOP)是一种程序设计思想,我们在面向对象思想的指引下,使用Java语言去设计、开发计算机程序。使用面向对象编程思想开发系统,在现代开发中会将面向对象贯穿整个过程,一般包括: OOA/OOD/OOP:- OOA:面向对象分析(Object-Oriented Analysis)
- OOD:面向对象设计(Object-Oriented Design)
- OOP:面向对象编程(Object-Oriented Programming)
面向过程(POP) 与 面向对象(OOP)
二者都是一种思想,面向对象是相对于面向过程而言的。面向过程,强调的 是功能行为,以函数为最小单位,考虑怎么做。面向对象,将功能封装进对 象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。面向对象思想是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成了指挥者。
面向对象的三大特征
- 封装 (Encapsulation)
- 继承 (Inheritance)
- 多态 (Polymorphism)
- 根据问题需要,选择问题所针对的现实世界中的实体。
- 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
- 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序
- 语言,把类构造成计算机能够识别和处理的数据结构。
- 将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。
类和对象的概念
软件存在的意义就是为了解决现实世界当中的问题,它必然模拟现实世界,也就是说现实 世界中有什么,软件中就对应有什么。 面向对象编程思想中关注点是“对象”或者“事物”,那么在编程语言当中要想创建对象则必须先有类,那么类和对象分别是什么,它们的区别和联系是什么呢?
什么是类?
类:是一类具有相同特性的事物的抽象描述,是一组相关属性和行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该类事物。 可以理解为:类 = 抽象概念的人,比如黄种人;对象 = 实实在在的某个人,比如诸葛亮。
- 面向对象程序设计的重点是类的设计
- 类的设计,其实就是类的成员的设计
- 现实中的属性(就是该事物的状态信息),比如说人的姓名,年龄,国籍,对应了类中的成员变量
- 现实中的行为(就是该事物能够做什么),比如说吃饭丶睡觉对应了类中的成员方法
什么是对象
对象:是一类事物的具体体现。对象是类的一个实例(对象并不是找个女朋友),必然具备该类事物的属性和行为。类:我们叫做class。 对象:我们叫做Object,instance(实例)。以后我们说某个类的对象,某个类的实例。是一样的意思。 通过类可以创建对象,对象又被称为实例(instance),这个过程也可以称为实例化。对象具有共同特征,进行抽象形成了类,所以从对象到类称为抽象。
通过以上的描述,我们得知常见的类的成员有 属性和方法,而属性描述的是状态,方法描述的是行为动作。
- 类是对一类事物的描述,是抽象的。
- 对象是一类事物的实例,是具体的。
- 类是对象的模板,对象是类的实体。
类的语法格式
Java自定义Person类,步骤如下:
- 定义类(考虑修饰符、类名)
- 编写类的属性(考虑修饰符、属性类型、属性名、初始化值)
- 编写类的方法(考虑修饰符、返回值类型、方法名、形参等)
public class Person { //属性name,age,isMale // 成员变量 String name; int age = 1; boolean isMale; //成员方法 public void eat() { System.out.println("人可以吃饭"); } public void sleep() { System.out.println("人可以睡觉"); } public void talk(String language) { System.out.println("人可以说话,使用的是:" + language); } }
对象的创建和使用
类定义之后,就可以使用类这个“模板”来创造“对象”了,一个类是可以创建多个对象 的哦!怎么创建呢,语法是什么?其实语法格式很简单:new 类名(),这样就可以完成对象的创建了。俗话说,你想要什么 java 都可以给你,想要啥你就 new啥。对象的创建
那么,对象名中存储的是什么呢?答:对象地址 。直接打印对象名和数组名都是显示“类型@对象的hashCode值",所以说类、数组都是引用数据类型,引用数据类型的变量中存储的是对象的地址,或者说指向堆中对象的首地址 。
创建自定义Person类的对象
public class PersonTest { public static void main(String[] args) { //2. 创建Person类的对象 Person p1 = new Person(); //Scanner scanner = new Scanner(System.in); //调用对象的结构:属性、方法 //调用属性:“对象.属性” p1.name = "Tom"; p1.isMale = true; System.out.println(p1.name); //调用方法:“对象.方法” p1.eat(); p1.sleep(); p1.talk("Chinese"); //******************************* Person p2 = new Person(); System.out.println(p2.name);//null System.out.println(p2.isMale); //******************************* //将p1变量保存的对象地址值赋给p3,导致p1和p3指向了堆空间中的同一个对象实体。 Person p3 = p1; System.out.println(p3.name);//Tom //给age属性赋值 p3.age = 10; System.out.println(p1.age);//10 } }
注意事项:
- 创建对象语法: 类名 对象名 = new 类名();
- 类、数组都是引用数据类型,引用数据类型的变量中存储的是对象的地址,或者说指向堆中对象的首地址。
- 匿名对象:我们也可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象。匿名对象只能使用一次。
- 使用“对象名.对象成员”的方式访问对象成员(包括属性和方法)
- 如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的(非static)属性。意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。
- 属性的类型可以是Java的任意类型,包括基本数据类型、引用数据类型(类、接口、数组等) 。如果属性是引用类型,则给其赋值的是其对应的内存地址值。
- 当多个对象的引用指向同一个内存空间(变量所记录的地址值是一样的)只要有任何一个对象修改了内存中的数据,随后,无论使用哪一个对象进行数据获取,都是修改后的数据。
类的访问机制:
- 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。 (例外:static方法访问非static,编译不通过。)
- 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员。
对象的创建和使用:内存解析
程序计数器:- 概念:可以看做当前线程所执行的字节码的行号指示器。程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址 。
- 特点:线程私有的内存
- 概念:描述的是 java 方法执行的内存模型。(每个方法在执行的时候会创建一个 栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每个方法 从调用直至完成的过程,就对应一个栈帧从入栈到出栈的过程。)虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char 、 short 、 int 、 float 、 long 、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。 方法执行完,自动释放。
- 特点 :线程 私 有, 生 命 周期 和 线 程 相同 。 这 个 区域 会 出 现 两种 异 常 : *Error 异常: 若线 程请求 的深 度大于 虚拟 机所允 许的 深度 。 OutOfMemoryError 异常:若虚拟机可以动态扩展,如果扩展是无法申请到足够的 内存。
- 概念:它与虚拟机栈所发挥的作用是相似的,区别是 java 虚拟机栈为执行 java 方 法服务,而本地方法栈是为本地方法服务。当程序中调用了native的本地方法时,本地方法执行期间的内存区域 。
- 特点:线程私有,也会抛出两类异常:*Error 和 OutOfMemoryError。
- 概念:是被所有线程共享的一块区域,在虚拟机启动时创建。
- 特点:线程共享,存放的是对象实例(所有的对象实例和数组),GC 管理的主要区域。可以处于物理上不连续的内存空间。
- 概念:存储已被虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代 码等数据。
- 特点:线程共享的区域,抛出异常 OutOfMemory 异常:当方法区无法满足内存分 配需求的时候。
针对于目前来说,大家必须要知道 java 虚拟机有三块主要的内存空间,分别是“虚拟机栈(后面简称栈)”、“方 区”、“堆区”,方法区存储类的信息,栈中存储方法执行时的栈帧以及局部变量,堆区中主 要存储 new 出来的对象,以及对象内部的实例变量。其中垃圾回收器主要针对的是堆内存, 方法区中最先有数据,因为程序执行之前会先进行类加载。栈内存活动最频繁,因为方法不断 的执行并结束,不断的进行压栈弹栈操作。
类的成员之一:属性
属性的类型可以是Java的任意类型,包括基本数据类型、引用数据类型(类、接口、数组等)。如果是class类作为属性,赋值的时候是赋值其new出来的对象。变量的分类
成员变量(属性)和局部变量的区别
在 java 语言当中,当实例变量 没有手动赋值,在创建对象的时候,也就是说在 new 的时候,系统会对实例变量默认赋值, 它们的默认值请参考下表: 代码示例/* * 类中属性的使用 * * 属性(成员变量) vs 局部变量 * 1.相同点: * 1.1 定义变量的格式:数据类型 变量名 = 变量值 * 1.2 先声明,后使用 * 1.3 变量都有其对应的作用域 * * * 2.不同点: * 2.1 在类中声明的位置的不同 * 属性:直接定义在类的一对{}内 * 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量 * * 2.2 关于权限修饰符的不同 * 属性:可以在声明属性时,指明其权限,使用权限修饰符。 * 常用的权限修饰符:private、public、缺省、protected --->封装性 * 目前,大家声明属性时,都使用缺省就可以了。 * 局部变量:不可以使用权限修饰符。 * * 2.3 默认初始化值的情况: * 属性:类的属性,根据其类型,都有默认初始化值。 * 整型(byte、short、int、long):0 * 浮点型(float、double):0.0 * 字符型(char):0 (或'\u0000') * 布尔型(boolean):false * * 引用数据类型(类、数组、接口):null * * 局部变量:没有默认初始化值。 * 意味着,我们在调用局部变量之前,一定要显式赋值。 * 特别地:形参在调用时,我们赋值即可。 * * 2.4 在内存中加载的位置: * 属性:加载到堆空间中 (非static) * 局部变量:加载到栈空间 * */ public class UserTest { public static void main(String[] args) { User u1 = new User(); System.out.println(u1.name); System.out.println(u1.age); System.out.println(u1.isMale); u1.talk("韩语"); u1.eat(); } } class User{ //属性(或成员变量) String name; public int age; boolean isMale; public void talk(String language){//language:形参,也是局部变量 System.out.println("我们使用" + language + "进行交流"); } public void eat(){ String food = "烙饼";//局部变量 System.out.println("北方人喜欢吃:" + food); } }
成员变量的分类
- 实例变量:没有static修饰,也叫对象属性,属于某个对象的,通过对象来使用
- 类变量:有static修饰,也叫类变量,属于整个类的,不是属于某个实例
类变量的值是所有对象共享的,而实例变量的值是每个对象独立的
实例变量和类变量相同点:
- 声明的位置都是在类中方法外。
实例变量和类变量不同点:
如何在类外面访问成员变量类变量有2种访问方式,如下所示:
- 类名.静态成员变量 //推荐
- 对象名.静态成员变量 //不推荐
实例变量只能使用下面这种方式
- 对象名.静态成员变量
总结:
在Java中,一共就三种变量,他们分别是静态变量 丶成员变量丶局部变量 。我们可以从代码声明位置丶所在内存位置丶生命周期丶是否有默认值丶作用域(有效范围)大小几个方面去区分他们。
声明位置和方式
- 静态变量:在类中方法外,并且有static修饰
- 实例变量:在类中方法外,没有static修饰
- 局部变量:在方法体{}中或方法的形参列表、代码块中
在内存中存储的位置不同
- 静态变量:方法区
- 实例变量:堆
- 局部变量:栈
生命周期
- 静态变量:和类的生命周期一样,因为它的值是该类所有对象共享的,早于对象的创建而存在。
- 实例变量:和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡, 而且每一个对象的实例变量是独立的。
- 局部变量:和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡, 而且每一次方法调用都是独立。
作用域
- 静态变量和实例变量:不谈作用域 ,在本类中,唯一的限制,静态方法或静态代码块中不能使用非静态的,其他都可以直接使用。 在其他类中,能不能使用看修饰符(public,protected,private等)
- 局部变量:有作用域限制,出了作用域就不能使用。
修饰符
- 静态变量:很多 public,protected,private,final,volatile等,一定有的是static
- 实例变量:public,protected,private,final,volatile,transient等
- 局部变量:final
public,protected,private:权限修饰符 final:是否是常量,即值是否可以修改 volatile:和多线程有关 transient:是否序列化,和IO有关
默认值
- 静态变量:有默认值
- 实例变量:有默认值
- 局部变量:没有,必须初始化 其中的形参比较特殊,靠实参给它初始化