学习过前面的内容之后,我们已经能够使用选择、循环、方法和数组解决很多程序设计问题。但是,这些 Java 的特性还不足够用来开发图形用户界面和大型软件系统。假设希望开发一个图形化界面,如我们现在用到的各种软件等,点击某个按钮就完成相应的动作,那么该如何完成呢?按照我们现在的水平是无法完成的,但完成一个系统或是一个软件、网页的开发,我们都离不开一个编程思想——面向对象
说到这里,我们就要引入面向对象了,面向对象概念性的内容真的特别特别多,真的真的要静下心来去理解喔,在开始面向对象之前我们先来说说我们以前写的代码吧。既然我们之前写的代码不是面向对象的思想,那么是啥呢?
答:面向过程,什么是面向过程呢?面向过程也是解决问题的一种思想(其实和面向对象是兄弟啦!),当我们在解决问题时,会按照预先设定的想法和步骤,一步一步去实现,而具体的每一步都需要我们去实现和操作。这些步骤相互调用和协作,完成我们的需求。在面向过程里面我们都是参与者,并且需要面对具体的每一个步骤和过程,面对具体的每 一个功能函数。这些功能函数相互调用,完成需求,这就是面向过程最直接的体现。
如我们要完成一件“给朋友送礼物”的事情如果用面向过程的思想去解决这个问题的话,那么:1.上网或者逛商场去挑选礼物; 2.对比性价比; 3.加包装; 4.找你的朋友; 5.送给他。其实一发现这么一件事情真的好麻烦喔,然后在这个互联网发达的时代,这些事情根本就不用自己去一步一步完成,这就是我们将要说的面向对象。
什么是面向对象呢?当不再面对具体的每一个方法时,发现操作也变的简单了很多。而封装具体功能的这类,是我们需要面对的。而基于这个封装了具体功能的类,那怎么使用呢? 当面向封装了具体功能类,若要使用这个类,一般情况下,在Java中需要通过创建这个类的实体来使用。这个实体称之为对象。在开发中,我们是在不断的找封装不同功能的类。基于这些类,创建其对象, 使用这些对象完成相应的操作。
通过上面的讲解和分析得出:面向对象是基于面向过程,对象是将功能进行了封装。只要找到了具体的类,创建出对象,就可以调用其中的具体功能。面向对象也是用来解决问题的一种思维模式。 在以后开发中,先找对象,调用对象中的具体功能。如果真的没有能够完成需求的对象,这时就自己创建对象,并将所需的功能定义到对象中,方便以后使用。
就如上面买礼物的问题,用面向对象的思维去解决那就是:找买礼物的商家把需求给她描述,她会找出相应的礼物,如果你满意,付钱将送货地址告诉她,她再找快递去运送。这样一来你会发现,你参与的方式变了。而且从一个执行者变成了一个指挥者。但是并不是说,面向过程就不存在了,只是面向过程这一步让别人去做了。但是在编程过程中是没有绝对的面向对象的,因为事情总归是要解决的,而解决事情的过程就是面向过程,所以简单的总结在一个程序中:
类1{
成员变量 (不止一个)
方法(不止一个,代参和不带参,构造方法和其他方法){
面向过程 (具体要怎么实现这个功能,需要自己一步一步写出来)
}
}
类2{
主函数{
面向对象(创建类1的对象,调用类1中的方法)
}
}
这就是面向对象和面向过程在程序中的关系。在上面介绍面向对象时,我们不断提到类和对象,那么什么是对象,什么是类呢?
对象:一句概括的话——万事万物皆对象,其实这句话是太概括了,但说的也没错,这里也只能举例说明,对象代表现实世界中 可以明确标识的一个实体。例如:一个学生、一张桌子、一个圆、一个按钮甚至一笔贷款都 可以看作是一个对象。每个对象都有自己独特的标识、状态和行为
类:就是具有相同属性和行为的对象的统称,比如上面的学生,每个学生都会有一个学号,班级等属性,要上课,写作业等行为,把这些用一个类封装起来,就形成了一个学生的类,它创建的对象就是一个具体的学生。
那么说了这么多概念,我们该怎么去定义一个类和对象呢?
一般而言主要描述两个方面:属性(成员变量):可以用一些参数描述类的信息
行为(相应的函数):可以用一系列的动作描述类的信息
如何把大象装进冰箱(这是个老生常谈的问题)
面向过程思想:数据和行为是分开
打开冰箱()
将大象装进冰箱()
关闭冰箱()
面向对象思想:数据和行为是融合的
类 大象{
}
类 冰箱{
打开()
装入()
关闭()
}
看不懂?
计算两个点的坐标
面向过程思想:
int x1,y1;
int x2,y2;
double distance=getDistance(x1,x2,y1,y2);
面向对象思想:
类 坐标点{
int x;
int y;
getDistance(坐标点 另一个点){}
}
主类 {
主函数{
坐标点 p1=new 坐标点();
坐标点 p2=new 坐标点();
p1.getDistance(p2);
p2.getDistance(p1);
}
}
那么具体用代码怎么实现呢?
class Demo01{
public static void main(String[] args){
Point p1=new Point(); //定义一个Point的对象叫p1
p1.x=10; //给点p1的x和y分别赋值
p1.y=10;
Point p2=new Point(); //再定义一个Point的对象叫p2
p2.x=20; //给点p2的x和y分别赋值
p2.y=20;
System.out.println(p1.getDistance(p2)); //p1调用获取两点之前的方法把p2传进去
System.out.println(p2.getDistance(p1)); // p2调用获取两点之前的方法把p1传进去
}
}
//定义一个名字为Point的类
class Point{
//成员变量:对象的特有属性 每个对象都会有自己的属性 且值可以和其它对象不同
//该类的对象应该有一个x值 默认为0
int x;
//该类的对象应该有一个y值 默认为0
int y;
//成员函数:对象的特有行为 每个对象都会有 谁先调用 this就指谁
//该类的对象应该有一个getDistance功能
//getDistance方法应该传入一个Point对象
public double getDistance(Point p){
//x-p.2 当前对象自己的x-传入的那个对象的x
return Math.sqrt(Math.pow(this.x-p.x,2)+Math.pow(this.y-p.y,2));
}
}
我们再来看一个数学问题,计算一个如果定义一个圆的类,并计算它的周长、面积和两圆心之间的距离。
//主类:主函数所在的类
//功能:为了执行程序
class Demo02{
public static void main(String[] args){
Circle c1=new Circle(); //定义一个圆的具体对象c1
c1.radius=10; //指定该圆c1的半径值
Point o1=new Point(); //定义一个点的对象o1
o1.x=0; //指定o1点的x值和y值
o1.y=0;
c1.o=o1; //将点o1确定为c1的圆心
Circle c2=new Circle(); //定义一个圆的具体对象c2
c2.radius=10; //指定该圆c2的半径值
Point o2=new Point(); //定义一个点的对象o2
o2.x=10; //指定o2点的x值和y值
o2.y=10;
c2.o=o2; //将点o2确定为c1的圆心
System.out.println(c1.getDistance(c2)); //圆c1调用方法获取与c2之间两个圆心的距离
//return;
}
}
/**
定义一个圆的类
*/
class Circle{
public double radius; //他的属性有半径确定圆的大小
public double pi=Math.PI; //和一个计算量π
public Point o; //以及一个圆心确定位置
/**
计算圆的面积
*/
public double getArea(){ //返回的是一个具体的数
double area=pi*radius*radius; //πr²
return area;
}
/**
计算圆的周长
*/
public double getPerimeter(){ //返回的也是一个具体的数
double perimeter=2*pi*radius; //2πr
return perimeter;
}
/**
计算当前圆到其他圆的距离
传入另外一个圆对象
获取两个圆之间的距离
*/
public double getDistance(Circle c){
double distance=this.o.getDistance(c.o);//当前圆心与传入进来圆的圆心的距离
return distance;
}
}
class Point{ //与上面的点类相同,如果写在同一个文件里,是可以不用写这个的,直接用之前写好的类的对象。
public double x;
public double y;
public double getDistance(Point p){
return Math.sqrt(Math.pow(this.x-p.x,2)+Math.pow(this.y-p.y,2));
}
}
通过两个例子,面向对象基本是啥,相信你应该有个明确的定义了,应该能大致了解如何使用现在我们来说一下更深层次的东西,内存的调用,以及运行流程,来上图!
1.javac 对Demo02.java进行编译的时候 产生3个字节码文件
Demo02.class Circle.class Point.class
没有主函数的类(字节码),不能够独立运行
主类 Demo02 主要用于运行程序 作为程序的开始main
实体类 Circle 和 Point 主要用于描述事物 但不推荐写主函数
2.java Demo02 意思将Demo02.class字节码文件加载进虚拟机开始运行
Circle.class Point.class 虽然没有明显的写出加载 但是会随着Demo02加载而加载
那么,这些字节码文件加载到JVM哪里去了?->方法区里
3.JVM在方法区中找主函数-Demo02-main
将该段main代码加载进栈开始运行
4.创建一个Cirlce对象
4.1 在堆内存中开辟一个空间并分配地址(空间大小是透明的)
4.2 对成员变量进行 【默认初始化】
4.3 然后对成员变量进行【显示初始化】
4.4 目前而言 对象创建完毕 将对象的地址赋予函数中的变量
这里引入另一个知识点,每个类之间相互调用的话,他么之间会存在某些联系,就会存在一些关系,类与类之间的关系有五种,即泛化(继承)、依赖、聚合、组合、关联,这里后期会专门写一篇文章讲解。现在用UML图表示上面两个类的关系为
至此我们的面向对象的基础已经介绍完了!