Java面向对象浅谈

作者简介

作者名:编程界明世隐
简介:CSDN博客专家,从事软件开发多年,精通Java、JavaScript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注,期待与您一起学习、成长、起飞!

热门专栏推荐

【1】Java小游戏(俄罗斯方块、飞机大战、植物大战僵尸等)
【2】JavaWeb项目实战(图书管理、在线考试、宿舍管理等)
【3】JavaScript精彩实例(飞机大战、贪吃蛇、验证码等)
【4】Java小白入门200例
【5】从零学Java、趣学Java
【6】Idea从零到精通

引言:

群里有个小伙伴请我写一篇关于面向对象的文章,起初我也是没有直接答应的,其一是因为最近有点忙,其二是我怕写不好,毕竟面向对象这个点所涉及的内容范围广。
我也是酝酿了好几天,才把这个文章写出来,希望对小伙伴们理解面向对象有一些些帮助,也希望我的那位粉丝朋友能够从这篇文章中得到他想要的知识。

面向过程与面向对象描述

面向过程,就是先把要解决问题的步骤分析出来,然后一步步的去实现,再一个个去调用。
面向对象,是把解决问题分解成多个对象,而对象是描述处理某些问题的一种行为。

这样简单描述一下,肯定是有点没搞明白,下面举些生活中的例子来说明。

面向过程与面向对象举例

生活中的例子:你想吃脐橙
面向过程举例:

出门–>坐车–>超市–>挑选脐橙–>付钱–>坐车回家–>拿出脐橙–>剥脐橙–>吃脐橙–>洗手。

这里简单描述了从买脐橙到吃脐橙的一个过程,面向过程就是把上面每个步骤用不同的方法来实现。

面向对象举例:
面向对象的设计则是从另外的思路来解决问题,如下:

我要吃脐橙–>女朋友把脐橙拿到你面前–>吃。 完事

分析一下,女朋友要做哪些事情:

出门–>坐车–>超市–>挑选脐橙–>付钱–>坐车回家–>拿出脐橙–>剥脐橙–>喂你–>洗手。

这是肯定会有小伙伴说了,你这跟面向过程并没有区别呀,这是动作只是分成了2个人去完成而已,并没有减少或者优化什么。
表面上看起来确实是这样的,但我们可以透过问题看本质:

  1. 对于“你”,这个角色来说,是不是只需要说我要吃橙子(调用方法),然后张开嘴巴吃就行了,这是毫无疑问的优化,如果没有女朋友(对象),你有这个福利吗?
  2. 对于“女朋友”这个角色来说,她是不是只可以给你发这福利?当然不是,如果哪天她不是你的对象,而是别人的对象了,别人说“我要吃橙子”,他是不是也可以使用到这个福利? 也就是说“女朋友”这个对象,有个方法叫“给男朋友吃橙子”,是不是她的男朋友就可以调用了呢。
  3. 如果你还是面向过程(单身),你想吃脐橙,那你只能重复如下过程:

出门–>坐车–>超市–>挑选脐橙–>付钱–>坐车回家–>拿出脐橙–>剥脐橙–>吃脐橙–>洗手,周而复始。

  1. 同理面向对象,只要调用“我想吃脐橙”方法,重复利用,不需要关心方法里面具体在做什么,当然这个“女朋友”对象也是可以重复利用的,要是对象切换了,”吃脐橙“方法也是封装好的,不会消失,别人也可以调用。

于是明哥我就问你,你听懂了吗?如果没听懂,那我就没辙了。

对象的定义

对象就是存在的具体实体,具有明确定义的状态和行为,是面向对象编程的核心,用来描述现实世界中的实体,为计算机应用程序提供实体基础,也是完成特定任务一个封装。

面向对象的三大特性

封装

封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

通俗来说,你的女朋友你调用”我要吃脐橙“方法,你可以吃到脐橙,别人也可以调用他的女朋友对象的”我要吃脐橙“方法,而你能否调用”别人“女朋友”的 “我要吃脐橙”方法?答案显然是不可以的。

也就是说类是一个抽象的集合,在这里“女朋友”抽象成类。

而对象是一个独立的个体,比如你的女朋友,他的女朋友;她们都是“女朋友”,但她们又是相互独立没有关系的。

代码举例

  1. 创建一个“女朋友”类
public class GirlFriend {
	String name;//名字
	int age;//年龄
}

测试一下:

public class Test {

	public static void main(String[] args) {
		GirlFriend girlFriend = new GirlFriend();
		girlFriend.name="蔡文姬";
		System.out.println("我的女朋友:"+girlFriend.name);
	}
}

运行结果:

我的女朋友:蔡文姬

  1. 对成员属性的封装
    上例中2个成员属性,name、age没有做限制,所以可以直接在测试类中使用(赋值、取值),但实际上一般来说成员属性是要做限制的,给成员属性加上private。
public class GirlFriend {
	private String name;//名字
	private int age;//年龄
}

此时我们再看测试类,是报错的
在这里插入图片描述
于是我们可以将赋值和取值封装成方法。

  1. 取值方法、 赋值方法
    成员属性是private私有的,而方法是public公开的。
public class GirlFriend {
	private String name;//名字
	private int age;//年龄
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

测试调用:

public class Test {

	public static void main(String[] args) {
		GirlFriend girlFriend = new GirlFriend();
		//girlFriend.name="蔡文姬";
		//System.out.println("我的女朋友:"+girlFriend.name);
		girlFriend.setName("蔡文姬");
		girlFriend.setAge(18);;
		System.out.println("我的女朋友:"+girlFriend.getName()+","+girlFriend.getAge()+"岁");
	}
}

调用:

我的女朋友:蔡文姬,18岁

  1. 构造方法赋值
	public GirlFriend(String name,int age){
		this.name=name;
		this.age=age;
	}

测试代码

public class Test {

	public static void main(String[] args) {
		GirlFriend girlFriend = new GirlFriend("蔡文姬",18);
//		girlFriend.setName("蔡文姬");
//		girlFriend.setAge(18);
		System.out.println("我的女朋友:"+girlFriend.getName()+","+girlFriend.getAge()+"岁");
	}
}

运行结果:

我的女朋友:蔡文姬,18岁

  1. 加入对象的归属
    为什么要加入对象的归属呢,因为类是抽象的,而对象是一个个的独立的,总不能人人“女朋友”都是蔡文姬吧,这不是乱了套吗?而且java中一旦使用 new 创建一个对象后,这个对象就是独立的个体。

GirlFriend girlFriend = new GirlFriend(“蔡文姬”,18);

都使用了上述代码来创建了一个 girlFriend ,但是每次都其实不是同一个“女朋友”。

代码验证一下:

public class Test {

	public static void main(String[] args) {
	/*	GirlFriend girlFriend = new GirlFriend("蔡文姬",18);
//		girlFriend.setName("蔡文姬");
//		girlFriend.setAge(18);
		System.out.println("我的女朋友:"+girlFriend.getName()+","+girlFriend.getAge()+"岁");
		*/
		GirlFriend girlFriend = new GirlFriend("蔡文姬",18);
		GirlFriend girlFriend1 = new GirlFriend("蔡文姬",18);
		
		System.out.println(girlFriend.hashCode());
		System.out.println(girlFriend1.hashCode());
	}
}

运行结果:

366712642
1829164700

从输出可以看到,不是同一个对象,我可以这样改:

public class GirlFriend {
	private String name;// 名字
	private int age;// 年龄
	private String manName;// 男人的名字

	public String getManName() {
		return manName;
	}

	public void setManName(String manName) {
		this.manName = manName;
	}

	public GirlFriend(String name, int age,String manName) {
		this.name = name;
		this.age = age;
		this.manName = manName;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}

测试代码:

public class Test {

	public static void main(String[] args) {
		GirlFriend girlFriend = new GirlFriend("蔡文姬",18,"我");
		GirlFriend girlFriend1 = new GirlFriend("瑶",19,"你");
		
		System.out.println(girlFriend.getManName()+"的女朋友:"+girlFriend.getName()+","+girlFriend.getAge()+"岁");
		System.out.println(girlFriend1.getManName()+"的女朋友:"+girlFriend1.getName()+","+girlFriend1.getAge()+"岁");
	}
}

运行结果:

我的女朋友:蔡文姬,18岁
你的女朋友:瑶,19岁

封装的好处

  1. 提高了数据的安全性
    对于私有的成员属性:别人无法通过 变量名.属性名 的方式来修改。
  2. 使用变得更加简单
    封装后,多个调用者在使用的时候,获得此对象,然后调用相对应的方法即可。
  3. 实现了隐藏
    实现过程对调用者是不可见的,调用者只需调用方法即可,不知道具体实现过程。

就如之前举例中,你无需关心你“女朋友”是怎么给你弄到橙子的,你只要告诉“她”我要吃橙子,然后等她拿橙子喂你即可。

继承

概述

继承机制是面向对象程序设计不可缺少的关键概念,是实现软件可重用的根基,是调高软件系统的可扩展性与可维护性的主要途径。
在Java中,被继承的类我们称之为父类,也叫基类;继承的类叫子类,也称为派生类或超类;继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能继承已有类的数据属性和行为,当然子类也可以扩展属于自己的新能力。

通俗来说,我们每个人都从父母那里继承来了不少能力,比如:吃饭、喝水、说话、走路、思考等等,也可以扩展自己的能力,比如:学编程、打王者(跑题了)。

在Java中,使用如下的语法实现继承的关系:

class 子类 extends 父类{}

代码讲解

  1. 继承成员变量
public class Test {

	public static void main(String[] args) {
		Student student = new Student();
		System.out.println(student.age);
	}
}

class Human {
	int age = 20;//年龄
}
class Student extends Human{
	
}

运行结果:

20

可以看到 age属性被继承下来了,但是如果 age声明为private的,则无法被继承了。

  1. 继承成员方法
public class Test {

	public static void main(String[] args) {
		Student student = new Student();
		student.study();
	}
}

class Human {
	int age = 20;//年龄
	
	void study(){
		System.out.println("学习技能");
	}
}
class Student extends Human{
	
}

运行结果:

学习技能

当然也是不能继承父类声明为 private 的成员方法的。

  1. 重写
    重写,是让子类拥有自己的实现,当然形参和返回值不能够改变,可以修改子类中的实现代码。
public class Test {

	public static void main(String[] args) {
		Student student = new Student();
		student.study();
	}
}

class Human {
	int age = 20;//年龄
	
	void study(){
		System.out.println("学习技能");
	}
}
class Student extends Human{
	@Override
	void study(){
		System.out.println("在学校学习知识");
	}
}

运行结果:

在学校学习知识

  1. super关键字
public class Test {

	public static void main(String[] args) {
		Student student = new Student();
		student.study();
		student.pStudy();
		
	}
}

class Human {
	int age = 20;//年龄
	
	void study(){
		System.out.println("人学习技能");
	}
}
class Student extends Human{
	@Override
	void study(){
		System.out.println("在学校学习知识");
	}
	
	void pStudy(){
		super.study();
	}
}

运行结果:

在学校学习知识
人学习技能

super关键字的用法如下:

1、super可以用来引用直接父类的实例变量。
2、super可以用来调用直接父类方法。
3、super()可以用于调用直接父类构造函数。

这里只说明了super可以直接调用父类,其他也比较类似的使用方式。

多态

概念

所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。

多态是同一个行为具有多个不同表现形式或形态的能力。

代码讲解

public class Test {

	public static void main(String[] args) {
		Human h = new Student();
		h.study();	
	}
}

class Human {
	int age = 20;//年龄
	
	void study(){
		System.out.println("人学习技能");
	}
}
class Student extends Human{
	@Override
	void study(){
		System.out.println("在学校学习知识");
	}
}

运行结果:

在学校学习知识

可能有小伙伴就没看明白了,这和之前得代码不是差不多吗?
其实差别在这里:

Human h = new Student();
h.study();

这里实例的对象是Student,但是向上转型成了Human后,然后通过Human的实例对象来调用study 方法,但其实这个 h 是Student的实例对象,最终调用的是Student的study方法。

Java实现多态有三个必要条件:

继承、重写、向上转型。

继承、重写,本例之前就已经满足了;
Human h = new Student(); 就是向上转型;

多个子类代码

public class Test {

	public static void main(String[] args) {
		//向上转型
		Human h = new Student();
		h.study();	
		//向上转型
		Human h1 = new Coder();
		h1.study();	
		//未向上转型
		Human h2 = new Human();
		h2.study();	
	}
}

class Human {
	int age = 20;//年龄
	
	void study(){
		System.out.println("人学习技能");
	}
}
class Student extends Human{
	@Override
	void study(){
		System.out.println("学生在学校学习知识");
	}
}

class Coder extends Human{
	@Override
	void study(){
		System.out.println("程序员在办公室加班学习编程知识");
	}
}

运行结果:

学生在学校学习知识
程序员在办公室加班学习编程知识
人学习技能

看上述代码,在编译时无法区别出他们的不一样,但是运行的时候,结果却截然不同。

为什么要这么用

可能你会问了,为什么要这么弄呢,搞继承、重写、还要向上转型。
其实在工作中会碰到程序扩展的问题,比如要新加一个学工程的,在这里就很方便了。

public class Test {

	public static void main(String[] args) {
		//向上转型
		Human h = new Student();
		h.study();	
		//向上转型
		Human h1 = new Coder();
		h1.study();	
		//未向上转型
		Human h2 = new Human();
		h2.study();	
		
		Human h3 = new Builder();
		h3.study();	
		
	}
}

class Human {
	int age = 20;//年龄
	
	void study(){
		System.out.println("人学习技能");
	}
}
class Student extends Human{
	@Override
	void study(){
		System.out.println("学生在学校学习知识");
	}
}

class Coder extends Human{
	@Override
	void study(){
		System.out.println("程序员在办公室加班学习编程知识");
	}
}


class Builder extends Human{
	@Override
	void study(){
		System.out.println("建造者在工地上学习建造");
	}
}

这样的扩展就非常的方便,无需要对 Student 和 Coder 的代码做任何的修改,在日常开发中,往往 Student 和 Coder类的代码很复杂,一个不小心会导致一些错误,从而给我们的编码工作带来一些困扰。

当然基于接口实现的多态是工作中更为常见的,其原理和上述基本一致,这里就不再说明了。
以上就是我的浅见了,大家觉得还行的话,给明哥来个三连吧!

热门专栏推荐

【1】Java小游戏(俄罗斯方块、飞机大战、植物大战僵尸等)
【2】JavaWeb项目实战(图书管理、在线考试、宿舍管理等)
【3】JavaScript精彩实例(飞机大战、贪吃蛇、验证码等)
【4】Java小白入门200例
【5】从零学Java、趣学Java
【6】Idea从零到精通
在这里插入图片描述

  • 29
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程界小明哥

请博主喝瓶水,博主持续输出!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值