面向过程和面向对象都是对软件分析、设计和开发地一种思想,它指导着人们以不同的方式去分析、设计和开发软件。这两种思想是相辅相成的。
面向过程:
使用面向过程思想思考问题时,我们首先思考“怎么按步骤实现?”并将步骤对应成方法,一步一步,最终完成。这个思想适合简单任务,不需要过多协作的情况下。比如:如何开车?
面向对象:
使用面向对象思想思考问题时,我们首先思考的是“有什么?”并将一件物体拆分成无数个物体,一步一步进行设计,最终完成,这样适合较复杂的任务,比如:如何造车?
面向对象和面向过程的总结:
- 都是解决问题的思维方式,都是代码组织的方式。
- 解决简单问题可以使用面向过程。
- 解决复杂问题:宏观上使用面向对象把握,微观处理上仍然是面向过程。
2. 对象的进化史(数据管理和企业管理的共通之处)
- 数据无管理时代
- 数组管理和企业部门制
- 对象和企业项目制
3. 对象和类的概念
类可以看作是一个模板,或者图纸,系统根据类的定义来造出对象。
类:class
对象:我们叫做Object,instance(实例)。以后我们说某个类的对象,某个类的实例,是一个意思。
1. 类的定义:
Java中类的定义分为两个部分:类的声明和类的主体。
1. 类的声明:
格式如下:
[<修饰符>] class <类名> [extends <父类>][implements <接口名>]
- 类定义修饰符。类定义修饰符为类声明的可选部分,定义类的性质(如abstract、final)和访问权限(public、默认)。
- extends。extends为类声明中的可选部分,用于说明类的父类。一般形式为extends<父类>。Java语言中,如果在类声明中无extends,则该类的父类均隐含为java.lang.Object。不同于c++,Java不支持多重继承,因此,extends之后最多只可跟一个类。
- implements。implements为类声明的可选部分,用于说明该类实现的接口。java允许一个类实现多个接口,接口之间使用“,”隔开。
2. 类主体:
类主体包括类的成员变量(field)的说明和成员方法(method)的定义与实现。
1. 成员变量
成员变量定义的一般格式:
[变量修饰符] <变量类型> <变量名>
1. 变量修饰符包括权限修饰符和静态修饰符等:
- 权限修饰符分为四种:
- public:允许被任何程序包中的类访问;
- protected:允许被类自身、子类及其相同包的类访问;
- 默认/default:允许类自身及其同一个包内的类所访问;
- private:只允许类自身进行访问;
- 静态修饰符:
-
static:修饰类变量:如果一个数据需要被所有对象共享使用的时候,那么即可使用static修饰该成员变量。
-
访问方式:
- 可以使用对象进行访问。 格式:对象.静态属性名
- 可以使用类名进行访问。 格式:类名.静态属性名
- 静态的成员变量可以使用类名或者是对象进行访问。
- 非静态的成员变量只能使用对象进行访问,不能使用类名直接访问。
- 千万不要为了方便而是用static修饰一个成员变量,只有这个成员变量的数据是需要被共享的时候才使用static修饰。
-
推荐使用类名进行访问。
- final:
被final修饰的成员变量不可变。
2. 变量类型:
可以是Java语言中任意的基本数据类型或引用数据类型(如类,数组等)。
3. 变量名:
- 类中成员变量名必须唯一。
- 但允许成员变量的名字与类中的成员方法同名。
- 不同类中也允许出现同名的变量名。
2. 成员方法:
成员方法定义的一般形式如下:
与普通方法一样。
1. 方法修饰符:
主要有public、private、protected、final、static、abstract和synchronized。
- 访问权限修饰符:同成员变量的权限修饰符。
- final:修饰最终方法,被final修饰的成员方法不允许被子类重载。
- static:
- 用于修饰类方法(或静态方法),与类变量类似,类方法不需要通过创建对象来使用,可以直接通过类来访问,类方法也不允许被重载。
- 非静态的方法只能使用对象调用,不能使用类名调用。
- 静态方法可以直接访问静态的成员,但是不能直接访问非静态的成员。
- 因静态方法可以使用类名调用,而这个时候对象可能还没有存在在内存中,这时候非静态的数据也就不存在在内存中。
- 非静态方法可以直接访问静态以及非静态的成员。
- 因非静态方法必须要由对象调用,如果对象存在了,静态数据以及非静态数据早就存在内存中了。
- 静态函数不能出现this以及super关键字。
- 因静态方法可以使用类名直接调用,而这个时候可能还没有对象存在,this又要代表当前对象。
- abstract:用于修饰抽象方法,该方法只有方法声明,没有方法体。
- synchronized:修饰符用于线程同步。
2. 方法返回值类型:
成员方法的返回值的类型可以是Java语言的任何数据类型,包括自定义类。
如果一个成员方法不需要返回值,则其返回值的类型为void。
如果有返回值,那么return语句要带参数,并且return语句中返回的数据类型必须与方法说明中的方法返回值的类型一致。
3. 方法名:
方法名是Java语言的合法标识符,方法命名建议符合Java编程规范:首字母小写,并符合驼峰命名规则。
4. 参数列表:
成员的方法列表有逗号分隔的类型即参数名组成,是可选项。参数的类型可以是Java语言的任何数据类型。
5. 方法体:
方法体用{}
括起来,是方法定义的主要部分,包含了实现方法功能的代码。
在方法体中可以定义局部变量,他的作用域仅在方法体内。
3. 构造方法(constructor):
- 构造方法也属于方法,但是是一种非常特殊的方法。
- 构造方法用于生成该类的一个对象实例,并对对象实例中的成员变量初始化。
- 当用new关键字创建一个类的新对象时,构造方法立即执行。
- 构造方法的名字必须与类名相同,语法如下:
public 类名([参数列表]){
[语句序列];
}
-
注意:
-
构造方法没有返回值类型,甚至没有void。其修饰符只能是public、private、protected中的任一个。
- 虽然不能定义返回值类型,但是本质上构造方法是有返回值的。因为返回值类型一定是本类,所以不可以自行定义返回值类型。不能在构造方法中使用return返回某个值。
-
构造方法不能从父类中继承。
-
系统默认提供无参构造方法,该方法根据成员变量的类型进行初始化,数值类型的成员变量被初始化为0,boolean类型的成员变量被初始化为false,引用类型的成员变量被初始化为null。
-
构造方法可以重载,一个类可以有任意多个构造方法。若重载了构造方法,系统将不再提供无参构造方法。
-
构造方法不能直接通过方法名调用,必须通过new运算符调用。
- 但是创建对象不仅仅可以用new,还可以利用反射机制等等进行创建。
-
在构造方法中可以调用当前类和其父类的另一个构造方法,但必须是方法体的第一条语句。使用当前类的构造方法用this来引用,使用其父类的构造方法用super来引用。
-
4. UML图
用来表示一个类的结构:包括属性和方法.
2. 面向对象的内存分析:
Java虚拟机的内存可以分为3个区域:栈stack、堆heap、方法区method area(本质上是在堆中,但是由于比较特殊,所以单列出来).
1. 栈stack:
栈的特点如下:
- 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
- JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
- 栈数与线程私有,不能实现线程之间的共享。
- 栈的存储特性是“先进后出,后进先出”。
- 栈是由系统自动分配,速度快。栈是一个连续的内存空间。
2. 堆heap:
堆的特点如下:
- 堆用于存储创建好的对象和数组(数组本质上也是一个对象)。
- JVM只有一个堆,被所有线程共享。
- 堆是一个不连续的内存空间,分配灵活但是速度慢。
3. 方法区method area(又叫静态区):
方法区的特点如下:
- JVM只有一个方法区,被所有线程共享。
- 方法区实际也是堆,知识用于存储类、常量相关的信息。
- 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)。
4. 当一个程序启动之后会发生什么?
- 使用java.exe来运行这个程序时,JVM启动,会创建堆、栈和方法区。
- 首先要将整个类的相关信息全部加载到方法区中。比如:代码、静态变量、静态方法、字符串常量等等...
- 代码中所有带引号的都是字符串常量,都将在类加载的时候存入方法区内。
- 程序开始调用main方法,则在栈中创建一个main方法的栈帧。
`Student st = new Student();`
方法中若创建一个对象,首先要调用构造方法,栈中创建一个构造方法的栈帧。堆中出现被创建好的对象及其地址。利用赋值符号将st = 该对象的地址。
属性赋值就是利用对象的地址在堆中找到该对象,将其对象的属性进行赋值。(字符串赋值是要在方法区中找到字符串常量的地址,将其赋值)。
当一个方法调用完成之后栈帧就会删除。
4. 垃圾回收机制:
1. 垃圾回收机制
Java引用了垃圾回收机制,令c++程序员最头疼的内存管理问题迎刃而解。Java程序员可以将更多的精力放到业务逻辑上而不是内存管理工作上,大大的提高了开发效率。
1. 内存管理:
java的内存管理很大程度上指的就是对象的管理,其中包括对象空间的分配和释放。
对象空间的分配:使用new关键字创建对象即可。
对象空间的释放:将对象赋值null即可。垃圾回收期将负责回收所有“不可达”对象的内存空间。
2. 垃圾回收过程:
任何一种垃圾回收算法一般要做2件基本事情:
- 发现无用的对象。
- 回收无用对象占用的内存空间。
垃圾回收机制保证可以将“无用的对象”进行回收,无用的对象指的就是没有任何变量引用该对象。Java的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。
3. 垃圾回收相关算法:
引用计数法:
堆中每个对象都有一个引用计数,被引用一次,计数+1,被引用变量值变为null,则计数-1,直到计数为0,则表示变成无用对象,优点是算法简单,缺点是“循环引用的无用对象”无法被识别。
引用可达法:
程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对象的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用的节点,即无用的节点。
2. 通用的分代垃圾回收机制:
分代垃圾回收机制是基于一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率,我们将对象分为3种状态:年轻态、年老态和持久态。JVM将堆内存划分为Eden、Survivor和Tenured/old空间。
垃圾回收过程:
- 新创建的对象,绝大多数都会存储在Eden区中
- 当Eden满了(达到一定比例)不能创建新的对象,则触发Minor GC,清理无用对象,将有用的对象全部复制到Survivor1或者Survivor2中,如放到了Survivor1中,同时清空Eden区。
- 当Eden区再次满了,会将Survivor1中有用的对象放到Survivor2中,同时将Survivor1中的对象清空,然后将Eden区中的有用对象复制到Survivor1中。
- 默认当一个对象在Survivor1和Survivor2中重复15次也没有被清理的对象,会被复制到Old/Tenured区中。
- 当Old区满了之后,则会触发一个一次完整地垃圾回收(Full GC)。
【注】:Full GC:用于清理年轻代、年老代区域。成本比较高,对系统性能产生影响。所以平时我们的JVM调优,就是有很大一部分是对于Full GC的调节。
5. 对象创建的过程和this、static关键字:
类是对象模板,只有实例化之后才可以使用。
1. 对象的创建:
1. 对象声明:
对象声明的一般格式:
类名 对象名;
声明了对象名之后,该对象还没有引用任何实体,只是一个空对象(null)。
2. 对象创建:
new运算符用于创建一个类的实例并返回对象的引用。一般格式如下:
对象名 = new 类名([参数列表]);
- 对象的声明并不为对象分配内存空间。用new运算符为对象分配内存空间,实例化一个对象,并根据所调用的构造方法进行成员变量初始化。
- 如果使用的是默认构造方法,则初始化规则如下:
- 对于整型成员变量,默认初值为0;
- 对于浮点型成员变量,默认初值为0.0;
- 对于boolean类型成员变量,默认初值为false;
- 对于引用型成员变量,默认初值为null;
- 一个类可以有多个对象,并分别为每个对象分配空间,一个对象的成员变量的改变不会影响其他对象的成员变量(类变量除外)。
3. 对象使用
可以通过“.”运算符来实现对自己的成员变量和方法的调用。
4. 对象的释放:
通过垃圾回收器GC
【总结】创建一个对象过程分为4步:
- 分配对象空间,并将对象成员变量初始化。
- 执行属性值的显式初始化。
- 执行构造方法。
- 返回对象的引用给相关的变量。
2. this的本质:
this的本质就是“创建好的对象的地址”,由于在构造方法调用前,对象已经创建(对象已经分配好了内存,this指针指向的是这块内存)。因此在构造方法中也可以使用this代表“当前对象”。
在实例方法和构造方法中使用this
区分成员变量和局部变量:
成员变量在整个类中有效,局部变量仅在方法内有效。在方法体中的声明变量以及方法的传入参数均称为局部变量,局部变量只在方法体内有效。
如果实例方法中或类方法中的局部变量名字与成员变量名字相同,这个成员变量在这个方法内暂时失效。如果确实想引用成员变量,则可以使用this关键字。
返回实例对象本身的引用
this还可以作为类成员方法的return语句的参数,用来返回对象本身的引用。
使用this调用类的其他构造方法:
在类的构造方法中,可以使用this()来调用该类的其他构造函数,具体调用那个构造函数是根据this的参数类型来确定的。this调用其他构造方法一定要在方法体中的第一行。
this不能用于static方法中
this指的是当前对象,但是static方法是类方法,可以在对象创建之前调用此方法,则this不可以存在static方法中。
3. static关键字:
在类中,用static声明的成员变量为静态成员变量,也称为类变量。类变量的生命周期和类相同,在整个应用程序执行期间有效。static修饰的成员变量和方法,从属于类。普通变量和方法从属于对象的。
静态方法中不可以使用非静态方法和非静态变量。
静态初始化块:
- 构造方法用于对象的初始化。静态初始化块用于类的初始化操作。在静态初始化块中不能直接访问非static成员。
- 静态初始化块在类加载的时候就已经执行了,所以说没有创建对象,也会执行静态初始化块内的内容。
【注意事项】:
1.上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止。
2.构造方法执行顺序和上面顺序一样。
6. 参数传值机制:
Java中方法中所有参数都是“值传递”,也就是“传递的是值的副本”。也就是说,我们得到的是“原参数的复印件,而不是原件”。因此复印件改变不会影响原件。
基本数据类型参数的传值:
传递的是值的副本,副本改变不会影响原件。
引用类型参数的传值:
传递的是值的副本,但是引用类型指的是“对象的地址”。因此,副本和原参数都指向了同一个“地址”,改变“副本指向地址对象的值,也就意味着原参数指向对象的值也发生了改变”。
7. 包机制和命名空间:
包机制是java中管理类的重要手段。开发中,我们会遇到大量同名的类,通过包我们很容易对解决类重名的问题,也可以实现对类的有效管理。包对于类,相当于文件夹对于文件的作用。
1. 命名空间
Java注重解决名字空间的冲突问题,没有全局方法、全局变量。
所有的变量和方法都是在类中定义,且是类的重要组成部分,每个类又是包的一部分,因此每个java变量或方法都可以用全限定的名字定义,即使用包名、类名、域名三部分(之间用“.”分隔)的形式访问类成员。
2. 包的定义和引入:
1. 包的定义:
一般可以使用package知名源文件中的类数与那个具体的包。定义包语句的格式如下:
package pkg1[.pkg2[.pkg3...]];
- 包的名字有层次关系,各层之间以点分隔。包层次与java开发系统的文件系统结构相同,也就是说包名和他们的结构应该同目录(文件夹)相对应。
- 需要注意的是,如需要定义包,程序首行必须是package语句,他的前面只能由注释或者空行。另外,一个文件只能有一个package语句。
- 包的命名规范:域名倒着写:
com.jd(京东)、com.alibaba(阿里巴巴)
- com.gsl和com.gsl.car,这两个包没有包含关系,时两个完全独立的包。只是逻辑上看起来后者是前者的一部分。
2. 包的引入:
当使用其他的包内的类时,需要在package语句之后使用import语句。import语句的格式如下:
import pkg1[.pkg2[.pkg3...]];
- import语句用于将其他包的类引入当前名字空间中,而当前包总是处于当前名字空间中,程序中无需引用同一个包或该包的任何元素。
- java.lang包被默认导入,即可以直接使用。除此之外,JDK主要还有java.io、java.util、java.awt、java.swing、java.awt.image、java.applet、java.net、java.sql、sun.tools.debug等包。
3. 静态导入(import static):
静态导入的作用是导入指定类的静态属性,这样我们可以直接使用静态属性。
标签:Java,变量,构造方法,对象,成员,面向对象,面向,静态,方法 From: https://www.cnblogs.com/guosiliang/p/18037357