第七讲 面向对象初步
1 面向对象介绍
面向对象:(OO) Oriented Object
C是面向过程的:什么过程?流程,要做一件事情的步骤。对于程序来说,过程体现在哪里?函数。所以,面向过程可以简单地理解为函数式,一个函数一个函数的调用。
比如:我们制造一个桌子,面向过程的是一个部件一个部件的焊接。哪个部件搞错了,桌子就废了。
比如:我们读书,面向过程的是一门课一门课的学,逻辑性很强,依赖很重。比如,我们学计算机科学与技术,先学计算机硬件、再学程序设计、再学数据结构...少一步都不可以,下一步依赖上一步,哪一步出问题了,整个学习过程都无效。
再比如:学语言,我们必须先学单词,然后学词组,再学短语,再学语法,....,最后才能使用。这是面向过程的。
面向过程是有先后顺序的。
面向对象:
java是纯面向对象的语言,比如:我们制造桌子,就不再焊接了,而是分模块来做,桌子可以分为:桌面、桌腿
我们先将桌腿和桌面衔接的部分规划好,留出接口,做桌面不影响做桌腿,桌面做好了以后,放在那里,桌腿做好了以后,直接接上。那么桌面做错了,桌腿还能用,只要重新做个桌面就好了。没有先后顺序,你可以先做桌面,也可以先做桌腿。
比如,我们的电脑,集成显卡,就是一个面向过程的。但是主板上还有可以拔插的内存条这些是面向对象的。
面向对象的扩展性、维护性更好。比如我们的电脑内存坏了,可以换一根。如果是面向过程的,内存集成在主板上,内存坏了,你没有办法换。只能换主板。
面向对象的含义到底是什么,这个需要实践需要积累。
OOA/OOD/OOP
OOA: oriented object analysis 面向对象分析
OOD:oriented object design 面向对象设计
OOP:oriented object programming 面向对象编程
三者之间的关系,先进行分析,然后设计,最后编程实现。
分析:抽象,对于需求中的内容进行提取、建模。把一些有共性的东西提取出来,形成类
设计:类与类之间的关系
编程:编码实现
对象:
什么是对象?女生说:花花是我对象,男生说:爽爽是我对象。对象是一个实实在在的个体,是实实在在存在的。
但是,花花也好,爽爽也好,他们都有一个共性,他们都是人,他们都是人类中的一类,叫做明星。
明星是实实在在的概念吗?它是指哪一个人吗?哪一个个体吗?它是一个抽象的概念,它指的是一类人,这一类人是公众人物,有很多粉丝,从事娱乐行业。
花花、爽爽只不过是明星这个类中的具体的个体,我们也叫作实例(实实在在的例子)。往后我们说对象的时候,也会讲是实例。
明星是一类人,人以群分,物以类聚。这就是面向对象的思想。
讲这么多,这里有两个主要的概念:类,对象。明星是一类人,这是一个类,叫做明星类。花花、爽爽是具体的人,他们是明星,所以我们说他们是明星类中的对象。
找朋友:
你是不是上去就找,看见是异性就上去搭讪?肯定不是。
首先,自己心中刻画一个朋友的样子。身高1.7m 长发齐腰 丹凤眼...这是指具体的哪个人吗?这是指的一类人。女朋友类。
其次,你遇到了符合条件的个体,是不是就是你要开始下手追求的对象啊!
对象和类之间的关系:
类是什么?是一个模板。它刻画了某一类事物,这一类事物具有相同的属性,是抽象的概念。比如女朋友类,这一类具有相同的属性(身高1.7m 长发齐腰 丹凤眼...)
对象:是具有类中属性的实例。实实在在的例子。它是具体的,不是抽象的。
一个类,可以产生多个对象,明星类中,有很多具体的明星对象。歌星:花花、华仔...歌星是一类,花花、华仔是类中的对象。
我们在具体操作的时候,操作了对象。所以叫做面向对象。
举例:
学生是一个群体,这类群体有特性
特性叫做属性
学生类的属性是:有学号、有学校、有院系、有姓名、有性别
学生类还有一些行为:上课、上课睡觉、逃课、逃课打游戏、吃饭、学习...
一个类中所包含的内容:
属性:这个类共有的性质
方法:这个类共有的行为
public class Student {
int sNum;
String schoolName;
String collegeName;
String name;
boolean sex;// true--female false---male
// 行为就是方法
public void eat() {
System.out.println("Student eat!");
}
public void study() {
System.out.println("Student study!");
}
public void playGames() {
System.out.println("Student play games!");
}
}
// 这就是一个类
// 类包含:属性、方法
// 通过类怎样生成对象呢?有了学生类,我想要具体的学生对象,怎么来?
编译器工作的一些补充:
我们在StudentTest.java文件中使用了Student.java,前提是他们在同一个文件夹下。
我们编译StudentTest.java文件,:> javac StudentTest.java
它为我们生成了StudentTest.class 和Student.class
我们可以猜测,编译器是这样工作的:
编译器先编译StudentTest.java文件,扫描其中的内容,当它发现数据类型名不是基础数据类型的时候,它会自动去找该类型对应的.class文件,如果该文件不存在,则在StudentTest.java文件夹下找该类型对应的.java文件,然后将其编译生成.class文件。
public class StudentTest
{
public static void main(String[] args) // String.class
{
Student zhangPeiYi = new Student();// Student.class在JDK中找不到
// 那么它就会去StudentTest.java所在目录下找Student.class
// 这个也找不到,它就会找Student.java文件,
// 找到之后加载到编译器,进行编译。
// 如果都找不到,那么编译报错。
/*
E:\java基础\day04-1>javac StudentTest.java
StudentTest.java:5: 错误: 找不到符号
Student zhangPeiYi = new Student();
^
符号: 类 Student
位置: 类 StudentTest
StudentTest.java:5: 错误: 找不到符号
Student zhangPeiYi = new Student();
^
符号: 类 Student
位置: 类 StudentTest
2 个错误
*/
zhangPeiYi.eat();
}
}
- 分析StudentTest.java
public class StudentTest
{
public static void main(String[] args)
{
// Student是一个类
// Student zhangPeiYi,这就是定义了一个变量
// 变量名字叫做zhangPeiYi,这是标识符,符合标识符的写法,规范的写法,驼峰命名法。
// Student是一个类,也是一个数据类型名,这个数据类型是我们定义的。不是系统给的。
// 数据类型:一类是系统给的,基础数据类型,一类是自定义的。我们在java中定义一个类,也可以说这个类是一种数据类型。与C语言中的结构体相似。
// 类名就是类型名,后面跟的是变量名,可以用赋值语句。"="右边的是一个实实在在的对象,这个变量叫做引用。
// 也就是说,"Student zhangPeiYi"这是一个Student类型的引用。
// 解释:也就是说,学生类中有个学生,我们把这个学生叫做"zhangPeiYi"。我们也可以将这个学生叫做"zhangSan"、"liSi".....叫什么不重要,只不过我们用一个名字来代替这个对象。这叫做引用。"zhangPeiYi"只是一个代号,大名叫做"zhangPeiYi",家里人可能叫他"宝宝"。引用只是具体对象的别名。
// 对象存在于内存中。在内存中,对象只有一个名字,就是它所存储的内存空间的首地址。
// 对象如何产生呢?要产生一个对象,使用关键字new。 new 类名();这就产生了一个对象。
Student zhangPeiYi = new Student();
// Student zhangPeiYi 这是一个引用。
new Student();// 这是一个实例。这样做,在内存中产生了一个对象,这个对象我们没法访问,因为我不知道它的内存地址是多少。我们要很方便的操作它,就要给它起一个名字。
// 比如,你们以后进入阿里,阿里巴巴公司都有花名。比如zhangPeiYi进入阿里以后,花名叫做"武松"。AliEmp wuSong = new AliEmp();如果zhangPeiYi跳槽了,去了字节,阿里公司里的这个花名留下来了,wuSong被留下来了,它可以作为另外一个员工的花名。它可以指向另外一个新加入的员工,这叫做引用。
// 类名(),这是什么?Student() 这是什么?它是方法。它有个特殊的名字叫做构造方法。因为使用它能够产生对象。用它来构造对象,所以它叫做构造方法。
// new 是一个关键字,也是一个操作符。用new来操作一个构造方法,就会产生一个对象。
// 所以,没有对象怎么办?new一个就好了。一个不够,多new几个。
zhangPeiYi.eat();// 这其他类中调用的,不能是private修饰的。
// 关于".",这个"."和C语言结构体中的"."一样。意思是"的"。zhangPeiYi的eat().
// "zhangPeiYi"是不是一个对象?不是。它只是对象的引用。要记住。zhangPeiYi如果是一个对象的话,那么zhangPeiYi就不能被改变了。zhangPeiYi指向的是new Student()。new出来的才是对象。才是一个实实在在的值。
// x = y;你们要想想这个语句的原理啊!y是值。值一旦产生就是实实在在存在的,至于放在哪个盒子中,叫什么别名,这是我们自己取的。zhangPeiYi是人为取出来的名字而已。不是一个实实在在的对象,它只是对象的一个引用(别名)。
// 我们使用引用.方法名()的方式,对引用的类型所对应的类中的方法进行访问。
// 引用.属性?是否就可以拿到属性的值呢?原则上讲是可以的。只不过这里涉及到访问修饰符。
}
}
2 再讲内存图
JVM内存中,有三块很重要的,其中一块叫做堆内存。昨天我们讨论了方法区内存,这块内空间用了执行方法、存放局部变量。是栈结构的。
今天核心将堆内存与栈内存的使用。(超级重点)
堆内存:这是一块比栈内存大得多的内存空间,它不像栈内存一样有栈数据结构的性质。它主要存放,由new关键字所产生的对象(实例)
在java程序中,一旦遇到new关键字,new 类名();就会产生一个对象实例,存储这个实例所需的内存空间在堆内存空间中分配。
堆内存空间是生成对象时用来存储对象的,它很大,对象在堆中也有生命周期,JVM有一套垃圾回收机制,当对象生命周期到了之后,JVM自动回收。目前来说,程序员不用对自己产生的对象进行管理。C当中动态申请的内存空间,本质上也就是在这块存空间中分配的。但是C中要程序员自己进行管理,主动释放。java中不用了,对象生命周期到了之后,jvm中有GC机制,自动回收。即,缘分已尽,不用纠结,JVM的GC自己帮你回收,不需要你处理。这就是程序员跟对象的关系处理方法。
zhangPeiYi这是一个引用,它在栈中存在,保存的是堆内存中的对象的首地址。这本质上就是指针,在java中我们叫它引用,而且jvm帮你管理了它所指向的对象。
## 当引用断掉之后,GC会自动回收堆中对象所占的内存空间。
GC回收对象的机制是:当对象没有引用指向的时候,会立即回收。
当然,对象有引用指向的时候,也有可能会被回收。对象存在于内存中太久,老了,老了之后引用指向它但使用频率很低,会优先回收。
如果没有给引用名,也就是说new Student(),这种操作,会让该对象一产生就被回收掉。因为没有引用指向它,JVM的GC机制就会立即回收它。但是它确实来过这世界,只不过是昙花一现。
,会立即回收。
当然,对象有引用指向的时候,也有可能会被回收。对象存在于内存中太久,老了,老了之后引用指向它但使用频率很低,会优先回收。
如果没有给引用名,也就是说new Student(),这种操作,会让该对象一产生就被回收掉。因为没有引用指向它,JVM的GC机制就会立即回收它。但是它确实来过这世界,只不过是昙花一现。