JAVA 面向对象(基本概念,对象在内存中的存储方式,构造方式,抽象与封装)

面向对象

在过去的C++学习中,我们老师在讲OOP的第一节课就是告诉我们 面向对象不是让你敲代码脸朝着你老婆你老头敲的,也不是一种框架,如果硬要用一个名词来表示的话应该说是一种编程的思想。
在现在的JAVA学习中,我今天又一次接触了面向对象,老师讲是一种把执行者变为指挥者的思想。面向对象是相对于面向过程而言的。
对我自己目前的学习和编程经验来看,面向对象就是,一种设计的思想,他不是套路性的,也不是固定的,甚至没有要求必须要用。但是他可以在一定程度上,把一些事情抽象化,从而突出事情的一些属性作用,弱化那些暂时对我们来说不相关的属性作用,从而方便我们编程,同时也方便后续的修改完善工作。

一点点基本概念

在JAVA中,虽然我刚学了三-四天,但是我最近听过最多的一句话就是万物皆对象,哦老哥,JAVA没有指针如何做二叉树,如何做堆排序,万物皆对象;如何画链表,栈,对象,万物皆对象…
那么对象到底是什么?
对象其实就相当于一个具体的事务,他有他的特点,有他的标识,有他的作用。他是一个活生生的例子,是可以指挥他去做事情的。也就是说我们编程的时候面向的就是他,指挥他,具体的过程就是他去面对了。换句话说,对象就是面向过程的。
另一个概念叫做类:那么类是什么呢?
我们平时常常会说,张三和李四长得丑是一类人;啊他看博客不点赞,我们不是一类人。那么这里的类指的其实就是具有相同属性和作用(能力)的一个集合。
在编程中同理,我们把具有相同属性和方法的一类事务用类表示出来,然后按照此类进行打印出来对象也就是长得丑的张三,长得丑的李四。所以我们可以把类作为一个图纸,去打印对象的图纸。
说了这么多,看一个代码:

class Person{
	String name;//姓名
	int age;//年龄
	int tall;//身高
	int weight;//体重

	void sing() {
		System.out.println("正在唱歌");
	}

	void cook() {
		System.out.println("正在做饭");
	}

	void work(int a,int b) {
		System.out.println(a+"+"+b+"="+a+b);
	}
}

看代码我定义了一个 人作为类,每一个人都有他的姓名,年龄,身高,体重这四个属性,当然我们知道人的属性不止这些还有性别,爱好,智力等,但是因为我现在想要的就只有姓名年龄,身高体重所以我可以把其他的特征给抽象化,其实就是忽略它,而单独只看这四个属性,当然如果你想要智力250的,也可以加一个int zhili;放到类中;现在我们需要看看他们都会做什么,而我现在需要他们为我做的包括(唱歌,做饭,工作),工作的内容是算两个数相加的和,并且直接告诉我是多少。那么一个类就定义好了,类名叫做Person;类的属性包括姓名,年龄,身高,体重,这个类的功能包括唱歌,做饭,工作。
一个图纸就完成了,那么我想要具体一点。因为我需要一个具体的可以使唤的对象,而不是一个虚幻的抽象的类。也就是说,我们需要让谁干活,我们必须要喊到这个人,张三,咱俩去睡觉吧!类似于这种,不然的话谁知道你具体想喊的是谁?
因此我们需要把类,具体到对象,也就是去new 一个对象。
嗯我想要一个这种样子的人(这类人),性别没要求,活好就行。

		Person p = new Person();
		p.name = "张三";
		p.age=20;
		p.tall=150;
		p.weight=200;

然后我们就面向对象创造了一个名字叫张三今年20岁,身高一米五,体重两百斤的对象。来让他去唱歌,做饭,工作。这个p是因为我们直呼别人名字不礼貌,就用了一个外号喊起来亲切又好听,啊我真是个好老板。
然后今天中午,我饿了,想让张三做饭。顺便还想听着他的歌吃饭,于是我需要喊p并让他做饭,做好后唱歌。

		p.cook();
		p.sing();

这个过程对于我来说应该是面向对象的,因为我吩咐了p(张三)去做什么(指挥人),而张三是面向过程的(执行人)。
从这一系列的事情我想大家都对面向对象有了了解了。当然应该也会创建对象和类了。

对象在内存中的存储

一个好的程序员绝对不能不了解计算机内部的存储逻辑,所以我们来大概说一下具体的存储过程,也就是计算机做的事情。
当我们给张三起外号的时候也就是Person p = new Person();计算机做了很多工作。
1.在栈内存中开辟了空间,存放我们的局部变量p;
2.在堆中也开辟了空间,存放对象;
3.给对象完成初始化的工作;
4.给对象分配唯一的地址值;
5.把地址值交给引用类型的变量p保存。
在JAVA中没有指针的概念,但是此处我觉得应该是栈中的地址指向了堆中的值。就好比我们把张三也就是p雇佣过来后,我们把张三放到堆中,他的数据和作用(具体的数据)都在里边,而我们的脑海里(栈)记得是张三的地址也就是p,换句话说p是张三的地址映射。

构造与析构方法

在上边我们基本上对于类的创建,对象的创建有了一个更深的认知,但是我们其实对于有一点很不满意,我们在给对象属性赋值的时候

		p.name = "张三";
		p.age=20;
		p.tall=150;
		p.weight=200;

这样也太麻烦了…
我在C++的学习中我记得有构造函数和析构函数,那么同样伟大的JAVA自然也有这么一说,也许有小伙伴这时候要说话了,“啊,博主,JAVA应该没有析构函数,人家有自己的垃圾回收机制.”不要急慢慢的来,先说构造方法。
首先来一串概念:构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的创建或者对象的初始化。当类实例化一个对象时会自动调用构造方法。

	public phone(double s,String c,double p) {
		size = s;
		color = c;
		price = p;
	}

然后这个时候有聪明的小伙伴该说了“啊,博主,我没有写这个,他不也没报错吗?”。是这样的,如果不写构造函数,系统会默认调用并把初始值赋值。比如int的初始值是0,那么就会赋值为0,String为null就会赋值为null;
另外构造方法和其他方法一样也可以重载,也就是说只要你提前写好构造方法,你创建对象的时候,想初始化几个属性就初始化几个属性。
然后是析构方法,我们先来解释一下这个词是什么意思:当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。但是JAVA的垃圾回收机制(GC)已经把这些工作做完了,无需程序员来释放,咱们自然也就不要担心内存泄露,只不过java中析构函数所采用的方式不是C++中的那样前加~号,在java中 对象析构时会调用void finalize()方法,因此你如果确实需要析构的话就可以为你写的类添加一个void finalize()方法,来完成你所需要的工作。
但是重点来了,这个析构方法与C++的析构函数(对象在清除之前析构函数会被调用)不同,在Java中,由于GC的自动回收机制,因而并不能保证finalize方法会被及时地执行(因为垃圾对象的回收时机具有不确定性),也不能保证它们会被执行(程序由始至终都未触发垃圾回收)。所以void finalize()方法一般不建议使用
那么这个函数具体是干啥的呢?在这里就先不多说了,后续我学到了自然会回来加上。

面向对象的特征

在部分教材上,面向对象的特征是封装,继承,多态;在另一部分的教材上,我们把特征化为四个:封装,继承,多态,抽象。这一块其实很好理解,但是不好使用,往往需要大量的练习。

抽象

先说抽象,抽象其实在前边已经说过了,我们在定义一个类的时候往往仅需要他的部分属性和功能,这种时候我们就需要抽象他的部分属性和功能,换句话说就是不去定义这些属性和功能,而是去定义我们需要的属性和功能。比如你只看重一个人的活好活差,对性别不感兴趣,那么就不需要定义性别属性,也就是把他抽象了。
这大大减少了我们写代码的量,你想啊描述一个类的特点那么多,怎么写的完嘛。

封装

封装是指隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式。
也就是说你让张三做饭,张三会去做,但是他不会让你知道他用了地沟油甚至是炒坏了三锅菜,才把第四锅给你端了上来。而且如果你不用一些特殊的渠道打听,你甚至不知道张三是一个身高一米五体重两百斤的大美女,这就是封装。而且在刚开始,没有封装的时候因为张三是你new出来的,所以你可以对他做任何事情,包括改名字和体重,这自然极其不好。封装极大的保护了张三的一切。
所以封装的好处很明显,用户无法轻易改变对象的属性甚至不清楚他怎么完成这个事情了,不过这个敬业的对象把一切都完成的很好。这自然对于我们来说大多数情况下,完成任务就已经够了,过程也不是很重要。
那么如何封装呢?
介绍一个新的修饰词private中文意思私有的,其实我们如果不加这个修饰我们必须要知道程序有一个默认的修饰public(公开的,公共的)。同时一个属性或方法只能有这些个的其中一个他不能即私有又公共。
那么他的具体使用办法请看代码:

public class phone {
	double size;//尺寸
	String color;//颜色
	private double price;//价格
	public void sing() {
		System.out.println("画画的baby");
	}
	private void call() {
		System.out.println("电话打通了");
	}
}

从手机店看了一个手机,价格你自然不能随意更改,而且没有买之前店员也不给你说具体价格,店员给你说你能试用它,你摸索了半天,发现他可以唱画画的baby…但是你就因为这句话非常坚决的和店员说,我就想要它,给我说说价钱。
店员在手机上加了这个函数,你终于看到价格了。

	void displayprice() {
		System.out.println(price);
	}

但是你还没发打电话,你质问店员,我买手机不能打电话只能听歌啊,店员给你说你可以把打电话的功能放到听歌功能里,这样就可以先听歌后打电话或者先打电话后听歌了。
也就是说唱歌的代码改为了:

	public void sing() {
		System.out.println("画画的baby");
        call();
	}

你又说虽然歌不错但是每次必须先听歌再打电话太费时间了,你得给我降价。店员被你缠的没办法,又给了一个函数

	void setprice(double a) {
		price=a;
	}

终于可以搞价了,最后你用一个很好的价格得到了手机。
当然手机没有真滴获得,但是封装怎么使用应该已经学会了,封装后的属性必须通过公开方法来使用,封装方法必须通过公开方法来使用。此处的封装指私有

今天先写到这了,初学JAVA还有很多东西需要好好学习准备后再给大家分享。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值