一. 面向对象介绍
- 面向过程与面向对象
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
看大家怎么说
- 来自知乎的【大魔头-诺铁】这么说:
面向对象是把世界描绘成N个有主动性的"活物"之间的交互
面向过程是有一个"上帝之手"通过制定一系列规则来操纵一堆"死物" - 来自知乎的【叶晓斌】这么说:
面向过程是一件事"该怎么做"
面向对象是一件事"该让谁来做",然后那个"谁"就是对象,他要怎么做是他自己的事,反正最后一群对象合力能把事做好就行了。 - 我这么说:
面向过程是把一件事分成几个步骤,创建几个方法,每个方法处理一步操作。每个方法按顺序被调用完成一件事。
面向对象类似把一件事交给几个"人",每个"人"做自己会做的那部分,大家配合把事情完成。(这里我们只面向"人",不关心他们具体怎么做——在这里"人"就是所谓的对象)
大家理解什么是面向对象了吗?
如果没有理解,那很好。我们一起来学习本章面向对象,来慢慢感受面向对象的力量。 - 类和对象
Java是面向对象的程序设计语言,类是面向对象的重要内容,我们可以把类当成一种自定义数据类型,可以使用类来定义变量,这种类型的变量称为引用型变量。也就是说,所有类是引用数据类型。
2.1概念
面向对象的程序设计中有两个重要概念:类和对象。其中类是某一类对象的抽象。对象才是一个具体的实体。如:有一条狗叫”花花”,那么这条真实存在的狗才是对象,而”狗”是类,代表一类”花花”这样的实体。
抽象的重要性
抽象是继承和多态的基础。在抽象的过程中,我们获得是事物本质的东西和事物独特的东西,这样我们很自然的认识到抽象的事物和具体的事物之间是一种继承的关系,而他们之间的不同性可以通过多态来表现出来。
2.2定义类
2.2.1语法格式
[权限控制符] class 类名 {
//零个到多个构造器 * 构造器定义 * 注意:构造器无返回值类型
[权限控制符] 类名(参数列表){};
//零个到多个属性 * 属性定义
[权限控制符] [static | final] 属性类型 属性名;
//零个到多个方法 * 方法定义
[权限控制符] [abstract | final] [static] 返回值类型 方法名(参数表){};
}
提示:定义类的时候,不是必须显式写构造方法、属性、方法。
【示例】:定义一个学生类
属性:学号、姓名、年龄、班级
方法:学习、唱歌
2.2.2对象的创建和使用
1)对象创建语法格式
类名 对象名 = new 类名();
示例
Student s = new Student();
2)操作对象的属性和方法
【语法格式】
使用类的属性: 对象名.属性
实用类的方法: 对象名.方法名()
以上面学生类Student为例:
Student s = new Student();
s.age = 18; //为属性age赋值为18
s.sing(); //调用sing方法
2.3构造方法
构造方法是一种特殊的方法,它是一个与类同名且没有返回值类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。
特殊性
1)构造方法作用:构造出来一个类的实例,对构造出来的类的对象初始化。
2)构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有。
3)系统会默认为类定义一个无参构造方法,即默认构造方法。若显式定义了构造方法,则系统不会提供默认无参构造函数。
示例
为上例学生类定义添加构造方法,用来初始化姓名属性。
再添加一个构造方法,用来同时初始化姓名、年龄两个属性。
思考:我们可以定义两个名称一样的属性么?不可以。那么两个方法的名称一样呢?这里的两个构造方法名称相同了,但是没有报错,为什么呢?这就是方法重载。
2.4方法重载
特点
1)方法名一定要相同
2)参数列表不同——参数类型、参数个数
3)与方法的访问控制符和返回值无关
示例
1)定义一个无参构造方法
2)定义一个带一个参数构造方法,初始化姓名属性。
3)定义一个带一个参数构造方法,初始化年龄属性。
4)定义一个带两个参数构造方法,初始化姓名、年龄属性。
2.5对象的引用与this
引用
Student s = new Student(“张三”);
上面的对象名s即为对象的引用,而 new Student(“张三”)才是张三对象。
this
总要有个事物来代表类的当前对象,就像C++中的this指针一样,Java中的this关键字就是代表当前对象的引用。
图例
它有三个主要的作用
1)在构造方法中调用其他构造方法
比如:有一个Student类,有三个构造函数,某一个构造函数中调用另外构造函数,就要用到this(),而不可以直接使用Student()。
2)返回当前对象的引用
3)区分成员变量名和参数名
2.6 static
static关键字的用途
在《Java编程思想》P86页有这样一段话:
“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”
这段话可以看出static关键字的基本作用:方便在没有创建对象的情况下来进行调用(方法/变量)。
很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。
static方法
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说:
- static是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。
- 在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
- 虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
static变量
static变量也称作静态变量,静态变量和非静态变量的区别是: - 静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
- 非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
二. JVM内存分析——案例
内存分配图
JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身。
3.一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中。
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
4.由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
静态区/方法区:
1.方法区又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
3.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
举例
Sample test1=new Sample(“测试1”);
案例
三. 封装
- 概念
什么是封装
封装是把对象的所有组成部分组合在一起,封装使用访问控制符将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。
作用
适当的封装可以让代码更容易理解和维护,也加强了代码的安全性。 - 访问控制符
访问控制符用来控制父类、子类间,不同包中的类间数据和方法的访问权限。包括private、protected、public和默认四中类型。其访问权限如下:
访问控制符 同一类中 同一包中 同一子类中 其他
private 是 否 否 否
default 是 是 否 否
protected 是 是 是 否
public 是 是 是 是
【示例】
演示四种访问类型的访问权限?