Java基础-面向过程和面向对象

面向过程和面向对象都是对软件分析、设计和开发地一种思想,它指导着人们以不同的方式去分析、设计和开发软件。这两种思想是相辅相成的。

面向过程:

使用面向过程思想思考问题时,我们首先思考“怎么按步骤实现?”并将步骤对应成方法,一步一步,最终完成。这个思想适合简单任务,不需要过多协作的情况下。比如:如何开车?

面向对象:

使用面向对象思想思考问题时,我们首先思考的是“有什么?”并将一件物体拆分成无数个物体,一步一步进行设计,最终完成,这样适合较复杂的任务,比如:如何造车?

面向对象和面向过程的总结:

  1. 都是解决问题的思维方式,都是代码组织的方式。
  2. 解决简单问题可以使用面向过程。
  3. 解决复杂问题:宏观上使用面向对象把握,微观处理上仍然是面向过程。

1|02. 对象的进化史(数据管理和企业管理的共通之处)

  • 数据无管理时代
  • 数组管理和企业部门制
  • 对象和企业项目制

2|03. 对象和类的概念

类可以看作是一个模板,或者图纸,系统根据类的定义来造出对象。

class

对象:我们叫做Object,instance(实例)。以后我们说某个类的对象,某个类的实例,是一个意思。

2|11. 类的定义:

Java中类的定义分为两个部分:类的声明和类的主体。

1|01. 类的声明:

格式如下:

[<修饰符>] class <类名> [extends <父类>][implements <接口名>]
  1. 类定义修饰符。类定义修饰符为类声明的可选部分,定义类的性质(如abstract、final)和访问权限(public、默认)。
  2. extends。extends为类声明中的可选部分,用于说明类的父类。一般形式为extends<父类>。Java语言中,如果在类声明中无extends,则该类的父类均隐含为java.lang.Object。不同于c++,Java不支持多重继承,因此,extends之后最多只可跟一个类。
  3. implements。implements为类声明的可选部分,用于说明该类实现的接口。java允许一个类实现多个接口,接口之间使用“,”隔开。

1|02. 类主体:

类主体包括类的成员变量(field)的说明和成员方法(method)的定义与实现。

1|01. 成员变量

成员变量定义的一般格式:

[变量修饰符] <变量类型> <变量名>
1. 变量修饰符包括权限修饰符和静态修饰符等:
  1. 权限修饰符分为四种:
    • public:允许被任何程序包中的类访问;
    • protected:允许被类自身、子类及其相同包的类访问;
    • 默认/default:允许类自身及其同一个包内的类所访问;
    • private:只允许类自身进行访问;
  2. 静态修饰符:
    • static:修饰类变量:如果一个数据需要被所有对象共享使用的时候,那么即可使用static修饰该成员变量。

    • 访问方式:

      1. 可以使用对象进行访问。 格式:对象.静态属性名
      2. 可以使用类名进行访问。 格式:类名.静态属性名
    1. 静态的成员变量可以使用类名或者是对象进行访问。
    2. 非静态的成员变量只能使用对象进行访问,不能使用类名直接访问。
    3. 千万不要为了方便而是用static修饰一个成员变量,只有这个成员变量的数据是需要被共享的时候才使用static修饰。

推荐使用类名进行访问。

  1. final

被final修饰的成员变量不可变。

2. 变量类型:

可以是Java语言中任意的基本数据类型或引用数据类型(如类,数组等)。

3. 变量名:
  1. 类中成员变量名必须唯一。
  2. 但允许成员变量的名字与类中的成员方法同名。
  3. 不同类中也允许出现同名的变量名。
1|02. 成员方法:
成员方法定义的一般形式如下: 与普通方法一样。
1. 方法修饰符:

主要有public、private、protected、final、static、abstract和synchronized。

  1. 访问权限修饰符:同成员变量的权限修饰符。
  2. final:修饰最终方法,被final修饰的成员方法不允许被子类重载。
  3. static:
    • 用于修饰类方法(或静态方法),与类变量类似,类方法不需要通过创建对象来使用,可以直接通过类来访问,类方法也不允许被重载。
    1. 非静态的方法只能使用对象调用,不能使用类名调用
    2. 静态方法可以直接访问静态的成员,但是不能直接访问非静态的成员
      • 因静态方法可以使用类名调用,而这个时候对象可能还没有存在在内存中,这时候非静态的数据也就不存在在内存中。
    3. 非静态方法可以直接访问静态以及非静态的成员
      • 因非静态方法必须要由对象调用,如果对象存在了,静态数据以及非静态数据早就存在内存中了。
    4. 静态函数不能出现this以及super关键字
      • 因静态方法可以使用类名直接调用,而这个时候可能还没有对象存在,this又要代表当前对象。
  4. abstract:用于修饰抽象方法,该方法只有方法声明,没有方法体。
  5. synchronized:修饰符用于线程同步。
2. 方法返回值类型:

成员方法的返回值的类型可以是Java语言的任何数据类型,包括自定义类。

如果一个成员方法不需要返回值,则其返回值的类型为void。

如果有返回值,那么return语句要带参数,并且return语句中返回的数据类型必须与方法说明中的方法返回值的类型一致。

3. 方法名:

方法名是Java语言的合法标识符,方法命名建议符合Java编程规范:首字母小写,并符合驼峰命名规则。

4. 参数列表:

成员的方法列表有逗号分隔的类型即参数名组成,是可选项。参数的类型可以是Java语言的任何数据类型。

5. 方法体:

方法体用{}括起来,是方法定义的主要部分,包含了实现方法功能的代码。

在方法体中可以定义局部变量,他的作用域仅在方法体内。

1|03. 构造方法(constructor):
  1. 构造方法也属于方法,但是是一种非常特殊的方法。
  2. 构造方法用于生成该类的一个对象实例,并对对象实例中的成员变量初始化。
  3. 当用new关键字创建一个类的新对象时,构造方法立即执行。
  4. 构造方法的名字必须与类名相同,语法如下:
public 类名([参数列表]){ [语句序列]; }
  1. 注意:

    1. 构造方法没有返回值类型,甚至没有void。其修饰符只能是public、private、protected中的任一个。

      • 虽然不能定义返回值类型,但是本质上构造方法是有返回值的。因为返回值类型一定是本类,所以不可以自行定义返回值类型。不能在构造方法中使用return返回某个值。
    2. 构造方法不能从父类中继承。

    3. 系统默认提供无参构造方法,该方法根据成员变量的类型进行初始化,数值类型的成员变量被初始化为0,boolean类型的成员变量被初始化为false,引用类型的成员变量被初始化为null。

    4. 构造方法可以重载,一个类可以有任意多个构造方法。若重载了构造方法,系统将不再提供无参构造方法。

    5. 构造方法不能直接通过方法名调用,必须通过new运算符调用。

      • 但是创建对象不仅仅可以用new,还可以利用反射机制等等进行创建。
    6. 在构造方法中可以调用当前类和其父类的另一个构造方法,但必须是方法体的第一条语句。使用当前类的构造方法用this来引用,使用其父类的构造方法用super来引用。

1|04. UML图

用来表示一个类的结构:包括属性和方法.

2|22. 面向对象的内存分析:

Java虚拟机的内存可以分为3个区域:栈stack、堆heap、方法区method area(本质上是在堆中,但是由于比较特殊,所以单列出来).

1|01. 栈stack:

栈的特点如下:

  1. 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
  2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
  3. 栈数与线程私有,不能实现线程之间的共享。
  4. 栈的存储特性是“先进后出,后进先出”。
  5. 栈是由系统自动分配,速度快。栈是一个连续的内存空间。

1|02. 堆heap:

堆的特点如下:

  1. 堆用于存储创建好的对象和数组(数组本质上也是一个对象)。
  2. JVM只有一个堆,被所有线程共享。
  3. 堆是一个不连续的内存空间,分配灵活但是速度慢。

1|03. 方法区method area(又叫静态区):

方法区的特点如下:

  1. JVM只有一个方法区,被所有线程共享。
  2. 方法区实际也是堆,知识用于存储类、常量相关的信息。
  3. 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)。

1|04. 当一个程序启动之后会发生什么?

  1. 使用java.exe来运行这个程序时,JVM启动,会创建堆、栈和方法区。
  2. 首先要将整个类的相关信息全部加载到方法区中。比如:代码、静态变量、静态方法、字符串常量等等...
    • 代码中所有带引号的都是字符串常量,都将在类加载的时候存入方法区内。
  3. 程序开始调用main方法,则在栈中创建一个main方法的栈帧。
`Student st = new Student();`

方法中若创建一个对象,首先要调用构造方法,栈中创建一个构造方法的栈帧。堆中出现被创建好的对象及其地址。利用赋值符号将st = 该对象的地址。

属性赋值就是利用对象的地址在堆中找到该对象,将其对象的属性进行赋值。(字符串赋值是要在方法区中找到字符串常量的地址,将其赋值)。

当一个方法调用完成之后栈帧就会删除。

3|04. 垃圾回收机制:

3|11. 垃圾回收机制

Java引用了垃圾回收机制,令c++程序员最头疼的内存管理问题迎刃而解。Java程序员可以将更多的精力放到业务逻辑上而不是内存管理工作上,大大的提高了开发效率。

1|01. 内存管理:

java的内存管理很大程度上指的就是对象的管理,其中包括对象空间的分配和释放。

对象空间的分配:使用new关键字创建对象即可。

对象空间的释放:将对象赋值null即可。垃圾回收期将负责回收所有“不可达”对象的内存空间。

1|02. 垃圾回收过程:

任何一种垃圾回收算法一般要做2件基本事情

  1. 发现无用的对象。
  2. 回收无用对象占用的内存空间。

垃圾回收机制保证可以将“无用的对象”进行回收,无用的对象指的就是没有任何变量引用该对象。Java的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。

1|03. 垃圾回收相关算法:

引用计数法:

堆中每个对象都有一个引用计数,被引用一次,计数+1,被引用变量值变为null,则计数-1,直到计数为0,则表示变成无用对象,优点是算法简单,缺点是“循环引用的无用对象”无法被识别。

引用可达法:

程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对象的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用的节点,即无用的节点。

3|22. 通用的分代垃圾回收机制:

分代垃圾回收机制是基于一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率,我们将对象分为3种状态:年轻态、年老态和持久态。JVM将堆内存划分为Eden、Survivor和Tenured/old空间。

垃圾回收过程:

  1. 新创建的对象,绝大多数都会存储在Eden区中
  2. 当Eden满了(达到一定比例)不能创建新的对象,则触发Minor GC,清理无用对象,将有用的对象全部复制到Survivor1或者Survivor2中,如放到了Survivor1中,同时清空Eden区。
  3. 当Eden区再次满了,会将Survivor1中有用的对象放到Survivor2中,同时将Survivor1中的对象清空,然后将Eden区中的有用对象复制到Survivor1中。
  4. 默认当一个对象在Survivor1和Survivor2中重复15次也没有被清理的对象,会被复制到Old/Tenured区中。
  5. 当Old区满了之后,则会触发一个一次完整地垃圾回收(Full GC)。

【注】:Full GC:用于清理年轻代、年老代区域。成本比较高,对系统性能产生影响。所以平时我们的JVM调优,就是有很大一部分是对于Full GC的调节。

4|05. 对象创建的过程和this、static关键字:

类是对象模板,只有实例化之后才可以使用。

4|11. 对象的创建:

1|01. 对象声明:

对象声明的一般格式:
类名 对象名;

声明了对象名之后,该对象还没有引用任何实体,只是一个空对象(null)。

1|02. 对象创建:

new运算符用于创建一个类的实例并返回对象的引用。一般格式如下:
对象名 = new 类名([参数列表]);

  1. 对象的声明并不为对象分配内存空间。用new运算符为对象分配内存空间,实例化一个对象,并根据所调用的构造方法进行成员变量初始化。
  2. 如果使用的是默认构造方法,则初始化规则如下:
    • 对于整型成员变量,默认初值为0;
    • 对于浮点型成员变量,默认初值为0.0;
    • 对于boolean类型成员变量,默认初值为false;
    • 对于引用型成员变量,默认初值为null;
  3. 一个类可以有多个对象,并分别为每个对象分配空间,一个对象的成员变量的改变不会影响其他对象的成员变量(类变量除外)。

1|03. 对象使用

可以通过“.”运算符来实现对自己的成员变量和方法的调用。

1|04. 对象的释放:

通过垃圾回收器GC

【总结】创建一个对象过程分为4步:

  1. 分配对象空间,并将对象成员变量初始化。
  2. 执行属性值的显式初始化。
  3. 执行构造方法。
  4. 返回对象的引用给相关的变量。

4|22. this的本质:

this的本质就是“创建好的对象的地址”,由于在构造方法调用前,对象已经创建(对象已经分配好了内存,this指针指向的是这块内存)。因此在构造方法中也可以使用this代表“当前对象”。

在实例方法和构造方法中使用this

区分成员变量和局部变量:

成员变量在整个类中有效,局部变量仅在方法内有效。在方法体中的声明变量以及方法的传入参数均称为局部变量,局部变量只在方法体内有效。

如果实例方法中或类方法中的局部变量名字与成员变量名字相同,这个成员变量在这个方法内暂时失效。如果确实想引用成员变量,则可以使用this关键字。

返回实例对象本身的引用

this还可以作为类成员方法的return语句的参数,用来返回对象本身的引用。

使用this调用类的其他构造方法:

在类的构造方法中,可以使用this()来调用该类的其他构造函数,具体调用那个构造函数是根据this的参数类型来确定的。this调用其他构造方法一定要在方法体中的第一行。

this不能用于static方法中

this指的是当前对象,但是static方法是类方法,可以在对象创建之前调用此方法,则this不可以存在static方法中。

4|33. static关键字:

在类中,用static声明的成员变量为静态成员变量,也称为类变量。类变量的生命周期和类相同,在整个应用程序执行期间有效。static修饰的成员变量和方法,从属于类。普通变量和方法从属于对象的。

静态方法中不可以使用非静态方法和非静态变量。

静态初始化块:

  1. 构造方法用于对象的初始化。静态初始化块用于类的初始化操作。在静态初始化块中不能直接访问非static成员。
  2. 静态初始化块在类加载的时候就已经执行了,所以说没有创建对象,也会执行静态初始化块内的内容。

【注意事项】:
1.上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止。
2.构造方法执行顺序和上面顺序一样。

5|06. 参数传值机制:

Java中方法中所有参数都是“值传递”,也就是“传递的是值的副本”。也就是说,我们得到的是“原参数的复印件,而不是原件”。因此复印件改变不会影响原件。

基本数据类型参数的传值:

传递的是值的副本,副本改变不会影响原件。

引用类型参数的传值:

传递的是值的副本,但是引用类型指的是“对象的地址”。因此,副本和原参数都指向了同一个“地址”,改变“副本指向地址对象的值,也就意味着原参数指向对象的值也发生了改变”。

6|07. 包机制和命名空间:

包机制是java中管理类的重要手段。开发中,我们会遇到大量同名的类,通过包我们很容易对解决类重名的问题,也可以实现对类的有效管理。包对于类,相当于文件夹对于文件的作用。

6|11. 命名空间

Java注重解决名字空间的冲突问题,没有全局方法、全局变量。

所有的变量和方法都是在类中定义,且是类的重要组成部分,每个类又是包的一部分,因此每个java变量或方法都可以用全限定的名字定义,即使用包名、类名、域名三部分(之间用“.”分隔)的形式访问类成员。

6|22. 包的定义和引入:

1|01. 包的定义:

一般可以使用package知名源文件中的类数与那个具体的包。定义包语句的格式如下:

package pkg1[.pkg2[.pkg3...]];
  1. 包的名字有层次关系,各层之间以点分隔。包层次与java开发系统的文件系统结构相同,也就是说包名和他们的结构应该同目录(文件夹)相对应。
  2. 需要注意的是,如需要定义包,程序首行必须是package语句,他的前面只能由注释或者空行。另外,一个文件只能有一个package语句。
  3. 包的命名规范:域名倒着写:com.jd(京东)、com.alibaba(阿里巴巴)
  4. com.gsl和com.gsl.car,这两个包没有包含关系,时两个完全独立的包。只是逻辑上看起来后者是前者的一部分。

1|02. 包的引入:

当使用其他的包内的类时,需要在package语句之后使用import语句。import语句的格式如下:

import pkg1[.pkg2[.pkg3...]];
  1. import语句用于将其他包的类引入当前名字空间中,而当前包总是处于当前名字空间中,程序中无需引用同一个包或该包的任何元素。
  2. java.lang包被默认导入,即可以直接使用。除此之外,JDK主要还有java.io、java.util、java.awt、java.swing、java.awt.image、java.applet、java.net、java.sql、sun.tools.debug等包。

1|03. 静态导入(import static):

静态导入的作用是导入指定类的静态属性,这样我们可以直接使用静态属性。


__EOF__

本文作者SalemG
本文链接https://www.cnblogs.com/guosiliang/p/18037357.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   SalemG  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示