前文我们介绍了数组,本文我们来开始介绍一下面向对象,本文会介绍面向对象与面向过程的概念及区别,并且会介绍类、方法、属性、对象的概念。
面向过程与面向对象
面向xx是代表软件设计时遇到问题时的思考方式。首先说面向过程,面向过程所代表的就是在面对问题时先做什么后做什么,例如:1 2*3,如果用面向过程的思想来看待这个问题就是先计算2*3再计算加法,这就是面向过程的思想,即在设计一个项目时先做什么后做什么都已经事先设计好了。
接下来是面向对象,例如我们要写一个汽车项目,如果用面向对象的思想来看待问题就是将影院项目拆解,拆解为引擎、轮胎等,即大问题化小,小问题化了。
需要注意的是,面向对象与面向过程并不冲突,以上述汽车例子为例,我们将问题拆解后,先做什么后做什么也需要有个规划,这就是面向过程所需要做的,因此面向过程与面向对象是相辅相成的,而非互斥。
类
我们说面向对象是将问题拆解,拆分成一个一个小的问题来解决,那么在Java中如何来描述这么一个个小问题却成了问题,因此我们要引入一个全新的概念:类。类就是描述某个小问题,或者理解为一个事物,即汽车就可以看做一个事物。在Java中描述一个事物可以使用class关键字,例如我们要定义一个事物:汽车,可以这样做:Javapublic class HelloWorld { public static void main(String[] args) { }} class Car {}
这样就定义了一个汽车了,也就是一个事物了,可是它什么都不能做,我们需要能让它跑起来,跑就需要轮胎,因此我们需要让汽车自带一个轮胎,下面我们来说一下如何让类自带一些属性。
属性
属性也可以称为成员,它附属于一个类中作为一个类的属性而存在,例如我们如果需要在Car中附带4个轮胎,那么我们可以这么做(为了简洁起见,轮胎使用字符串):Javapublic class HelloWorld { public static void main(String[] args) { }} class Car { String tires = "4个轮胎";}
这样我们就让汽车附带了轮胎,有了轮胎,我们就可以让它跑起来,跑属于汽车的行为,因此我们需要让Car类具有跑起来的行为,下面我们来介绍方法,使用方法,我们可以让类具有一定的行为。
方法
我们使用如下方式可以定义方法,有关方法仍然有许多细节需要说明,我们留在后文进行详细说明,先让汽车跑起来:Javapublic class HelloWorld { public static void main(String[] args) { }} class Car { String tires = "4个轮胎"; void run() { System.out.println("汽车使用" tires "跑起来了"); }}
对象
到现在为止,我们定义好了一个汽车,并且它具有4个轮胎,且拥有可以跑起来的行为,如何让它启动?类已经帮我们描述了一个事物,但是终究是一个事务,汽车有很多种,4轮胎的汽车也有太多种了,以品牌来分有:保时捷、路虎等等,因此Car的描述也不够具体,我们可以这么理解:保时捷、路虎等品牌商根据汽车的特征制造出汽车,因此对象的概念就油然而生了,对象就是具体事物,我们可以使用new关键字创建一个对象,然后就可以具有当前对象自己的一些属性和这个类已经具有的行为(图1)。有了保时捷汽车,就可以让汽车跑起来了,我们可以理解为制造了一辆汽车,它的名字叫做保时捷。
对象的内存分配与数组相同,new Car()存储在堆中,保时捷只是一个指向实际Car的指针而已。Javapublic class HelloWorld { public static void main(String[] args) { Car porsche = new Car(); porsche.run(); }} class Car { String tires = "4个轮胎"; void run() { System.out.println("汽车使用" tires "跑起来了"); }}
方法的细节
方法是实战中至关重要的存在,我们可以这样想,一个事物,它有什么东西不重要,重要的是它能做什么,一个事物,如果什么都不能做,那么显得不是那么重要了。我们接下来就看看方法的细节,首先看一下方法的构成。
方法由访问修饰符、修饰符、返回值、名字(也叫方法名)、参数列表、方法体构成,修饰符与访问修饰符是后面的内容,我们暂且无视,换为代码为:返回值 名字(参数列表) {方法体}。
首先介绍一下名字,名字就是这个行为能做什么,好的编码规范能让用户见名知义,因此,方法名的规范也极为重要。
然后是返回值,返回值简单地说就是做了这个行为能为你带来什么东西,可以理解为:健身让身体变得更加强壮、矜矜业业努力能让你变得更优秀,不过,强壮、优秀都是虚无的,程序毕竟是有1说1的,因此方法的返回值就是实实在在的存在,它更加类似于:努力工作给你报酬、好好学习获得一份满意的学历。上文程序中的void代表无,即什么都无法给你带来,什么都无法带来并不是不合适的,它能带来的总是潜移默化的,例如你所处国家发明了新武器,表面上看与你没有什么关系,但是潜在的是你所处的国家变得更加强大了、你变得更加安全了。如果它能为你带来什么,那么带来的东西如何描述?这就是数据类型的一个用途,例如,努力工作带给你报酬,那么此方法的返回值即为一个小数(整数),我们就可以在返回值这里写入double即代表这个方法能给你带来一个小数,有了这个工资,我们就可以将报酬返回给工作者(图1)。Javapublic class HelloWorld { public static void main(String[] args) { Worker worker = new Worker(); System.out.println("经过努力工作,共赚取了:" worker.work() "元"); }}class Worker { double work() { System.out.println("努力工作中..."); return 2000; }}
然后是参数列表,参数列表可以理解为给这个行为什么东西,即给方法什么东西,然后让它去做,例如,给200元人民币,让你去买15个棒棒糖,我们参数列表就可以写入一个int类型的变量,为什么要用变量?因为得将这个值存储起来,方便后续操作,这也就是方法体的作用,方法体作用较为简单,就是如何做,我们将这部分钱丢给方法后,方法将会存储,然后对这部分数据进行处理,如果不用变量,那么这部分数据如何进行复用?如果用编码方式来看如下图(图1)。Javapublic class HelloWorld { public static void main(String[] args) { Child child = new Child(); child.buy(200); }} class Child { void buy(int money) { System.out.println("花了" money "元,买了15根棒棒糖"); }}
方法的本质
方法内的数据仅在本方法有效,方法结束后数据就会失效了,这与方法的原理有关,我们运行一个方法,方法中的变量如何存储?因此肯定是需要有一个地方去存储这些变量的,方法的数据存储在栈中,程序每进入一个方法,就会开辟一个栈桢,一个栈中可以存放很多很多的栈桢,前文说栈像子弹夹,栈桢就类似于一个个子弹。
借此,我们说一下方法的调用,其实我们每次都在main中写代码,main也是一个方法,但是它是一个特殊的方法,它能作为我们的程序入口,但是我们写的buy方法却不行,方法调用其实可以理解为,我要去做一份工作,可是工作量太大,还需要别的行为进行辅助(图1),如果牵扯到参数,参考main调用即可。Javapublic class HelloWorld { public static void main(String[] args) { Child child = new Child(); child.buy(200); }} class Child { int a = 1; void buy(int money) { buyByBike(); System.out.println("花了" money "元,买了15根棒棒糖"); } void buyByBike() { System.out.println("骑着自行车前往商店"); } }
接下来说说为什么方法运行完毕后数据失效的问题,我们将栈视为子弹夹,我们放入子弹即我们将数据存入栈(也叫入栈),就是将数据压入栈中,我们将子弹取出即我们将数据取出(也叫出栈)。方法就是一个栈桢,我们开辟(调用)一个方法就会在栈中压入一个栈桢(图2)。
如果方法调用结束,就会进行出栈操作(图3),出栈即内存消失,消失后就不会再保留数据了。