Java从入门到实战总结-2.1、Java面向对象基础

Java从入门到实战总结-2.1、Java面向对象基础


1、面向对象概述

(1)、概述

面向对象(Object Oriented)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。

面向对象是相对于面向过程来讲的,指的是把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。

面向过程到面向对象思想层面的转变:

  • 面向过程关注的是执行的过程,面向对象关注的是具备功能的对象。

  • 面向过程到面向对象,是程序员思想上从执行者到指挥者的转变。

面向对象是一种思想,和具体语言无关,即使C语言也有面向对象写法,因此我感觉学习面向对象主要是掌握面向对象这种思想,以及如何用这种思想去设计程序。设计好程序后,使用哪种程序去开发则结合项目周期和运行场景等再综合考虑即可(语言不是核心,设计程序的思维方式才是关键,开发程序也是为了解决问题,哪种方式更好解决问题,哪种方式就会被追捧)。

(2)、两个例子

我们来通过两个例子建立面向对象和面向过程的基础概念,之后再学习面向对象的基础语法,在熟悉语法的过程中使用面向对象思想解决实际问题来加深对面向对象思想的理解。

例子1:

我们通过生活中的一个脑筋急转弯, 来理解这个概念。 

问:
把大象装进冰箱 , 需要分几步?
回答:
面向过程回答:
3步:1把冰箱门打开, 2把大象装进去 , 3把冰箱门关闭
面向对象回答:
2步:1招一个能操作冰箱的工人(对象),2指挥工人装大象

思考:
如果问题改成: 把100只大象依次关进冰箱,共分为几步?
面向过程的回答: 此处需要省略N字。。。
面向对象的回答还是2步:
1招一个能操作冰箱的工人(对象) , 2指挥工人把大象依次装进去。

结论:
从上述的栗子中, 我们发现面向过程很死板 ,是很难适应变化的 。 而面向对象更灵活,可复用性更高。

例子2:

我们再描述一个生活的场景:

场景:当我们独自生活时, 我们经常纠结一日三餐怎么吃。
面向过程: 每天亲力亲为: 买菜 - 做饭 - 吃饭 - 洗碗 的过程。
面向对象: 招聘一个保姆,每天等吃即可。

场景升级: 假设你是一个富豪, 拥有一座占地3000亩地的庄园 ,不再是只关注吃饭问题 , 还有花草树木修剪,泳池维 护清洗,卫生打扫,洗衣做饭。。。。。。
面向过程: 此处省略看着就累的N字。
面向对象: 招聘一个管家, 然后让管家招聘 园丁、泳池维护工、保姆等等。

结论:
从上述的栗子中,我们发现面向过程,我们需要关注很繁琐的过程。
而面向对象不用关注具体的细节,更关注的是统筹架构的问题。
其实我们进行大型应用开发时,就如上述的例子一样,如果我们写程序只关注过程的话,代码量达到一定层次以后,因为过程太多太杂,就很难再编写下去了。
面向过程到面向对象的转变有一种从微观升级到宏观的感觉,只关注处理一件事需要的宏观对象,微观的过程由每个对象具体去实现,这样更便于设计和把控全局,这样可能会由于缺少对细节的关注造成一些问题,但是在处理一件很复杂的事情的时候过度关注细节很可能造成效率低下,没有思考全局造成扩展性差,很容易出现功能堆砌的情况,随着程序迭代几次后可能就会出现很多bug,梳理程序的运行流程可能也会越来越费劲。
(3)、三大思想

面向对象思想从概念上讲分为以下三种:OOA、OOD、OOP

  • OOA:面向对象分析(Object Oriented Analysis)

  • OOD:面向对象设计(Object Oriented Design)

  • OOP:面向对象程序(Object Oriented Programming

(4)、三大特性
  • 封装性:所有的内容对外部不可见

  • 继承性:将其他的功能继承下来继续发展

  • 多态性:方法的重载本身就是一个多态性的体现

2、类和对象

(1)、两者的关系

类表示一个共性的产物,是一个综合的特征,而对象,是一个个性的产物,是一个个体的特征。 (类似生活中的图纸与实物的概念。)

类必须通过对象才可以使用,对象的所有操作都在类中定义。

类由属性和方法组成:

· 属性:就相当于人的一个个的特征

· 方法:就相当于人的一个个的行为,例如:说话、吃饭、唱歌、睡觉

(2)、类的定义格式

class 类名称 {

​ 成员属性

​ 成员方法

}

(3)、属性和方法

属性定义格式:

​ 数据类型 属性名;

属性定义并赋值的格式:

​ 数据类型 属性名 = 初始化值;

方法定义格式:

​ 权限修饰符 返回值类型 方法名(形式参数列表){

​ //方法体

​ return 返回值;

}

(4)、对象的创建和使用

一个类要想真正的进行操作,则必须依靠对象,对象的定义格式如下:

​ 类名称 对象名称 = new 类名称();

如果要想访问类中的属性或方法(方法的定义),则可以依靠以下的语法形式:

​ 访问类中的属性: 对象.属性;

调用类中的方法:

​ 对象.方法(实际参数列表) ;

(5)、示例
package day5;

/**
 * calss 类名{
 *  成员变量;
 *  成员方法;
 * }
 * 
 * 类必须编写在.java文件中
 * 一个Java文件中,可以有N个类,但是只能存在一个public修饰的类
 * .java文件的文件名必须和public修饰类的类名完全一致
 */
public class Demo1 {

	public static void main(String[] args) {
		//创建对象格式:
		//类名 对象名 = new 类名();
		Person p1 = new Person();
		//给对象属性赋值
		//格式:对象名.属性名 = 值;
		p1.name = "张三";
		p1.age = 18;
		p1.sex = '男';
		p1.say();
		
		int res = p1.sum(100, 200);
		System.out.println(res);
		p1.test();
		
		Person p2 = new Person();
		p2.name = "李四";
		p2.age = 19;
		p2.sex = '女';
		p2.say();
	}

}

/**
 * 类就是图纸
 */
class Person {
	//属性 - 特征
	String name;
	int age;
	char sex;
	
	//方法 - 行为
	/**
	 * 定义格式:
	 * 返回值类型 方法名称(形式参数列表) {
	 * 		方法体
	 * 		return 返回值;
	 * }
	 * 
	 * 调用格式:
	 * 对象名.方法名称(实际参数列表);
	 */
	
	void say() {
		System.out.println("自我介绍:我是"+name+",我的年龄"+age+",我的性别"+sex);
	}
	
	int sum(int x, int y) {
		return x+y;
	}
	
	//可以直接return结束方法,即使没有返回值
	void test() {
		System.out.println("just return");
		return ;
	}
}

在这里插入图片描述

3、创建对象内存分析

(1)、栈

栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈、出栈的说法。

Java栈的区域很小 , 大概2m左右 , 特点是存取的速度特别快

栈存储的特点是, 先进后出

存储速度快的原因:

​ 栈内存, 通过 ‘栈指针’ 来创建空间与释放空间 !

​ 指针向下移动, 会创建新的内存, 向上移动, 会释放这些内存 !

​ 这种方式速度特别快 , 仅次于PC寄存器 !

​ 但是这种移动的方式, 必须要明确移动的大小与范围 ,

​ 明确大小与范围是为了方便指针的移动 , 这是一个对于数据存储的限制, 存储的数据大小是固定的 , 影响了程序的灵活性 ~

​ 所以我们把更大部分的数据 存储到了堆内存中

存储的是:

​ 基本数据类型的数据以及引用数据类型的引用!

​ 例如:

​ int a =10;

​ Person p = new Person();

​ 10存储在栈内存中 , 第二句代码创建的对象的引用§存在栈内存中

(2)、堆

存放的是类的对象

Java是一个纯面向对象语言, 限制了对象的创建方式:

​ 所有类的对象都是通过new关键字创建

new关键字, 是指告诉JVM , 需要明确的去创建一个新的对象 , 去开辟一块新的堆内存空间:

堆内存与栈内存不同, 优点在于我们创建对象时 , 不必关注堆内存中需要开辟多少存储空间 , 也不需要关注内存占用时长 !

堆内存中内存的释放是由GC(垃圾回收器)完成的

垃圾回收器回收堆内存的规则:

​ 当栈内存中不存在此对象的引用时,则视其为垃圾 , 等待垃圾回收器回收 !

例如:

​ Person p0 = new Person();

​ Person p1 = p0;

​ Person p2 = new Person();

(3)、方法区

存放的是

​ - 类信息

​ - 静态的变量

​ - 常量

​ - 成员方法

方法区中包含了一个特殊的区域 ( 常量池 )(存储的是使用static修饰的成员)

(4)、PC寄存器

PC寄存器保存的是 当前正在执行的 JVM指令的 地址 !

在Java程序中, 每个线程启动时, 都会创建一个PC寄存器 !

(5)、本地方法栈

保存本地(native)方法的地址 !

(6)、示例

对象的引用是存储在栈区的,在new之后指向堆区的一块空间,因此Java中将一个对象引用赋值给新创建的新对象引用时该引用也指向该对象堆内存而不是新创建一个堆内存,因此对这两个任意引用指向的属性的修改都是修改的同一块内存的内容。

package day5;

public class Demo2 {

	public static void main(String[] args) {
		Book b1 = new Book();
		b1.name = "金苹果";
		b1.info = "讲述了果农辛勤种植金苹果的过程";
		
		Book b2 = new Book();
		b2.name = "银苹果";
		b2.info = "讲述了果农辛勤种植银苹果的过程";

		b2 = b1;
		b2.name = "铜苹果";
		b1.say();
		b2.say();
	}

	public static class Book {
		String name;
		String info;
		
		void say() {
			System.out.println("书名:"+name+",简介:"+info);
		}
	}
}

在这里插入图片描述

4、构造方法(构造器)

(1)、回顾对象创建
Person p = new Person();
//在右侧Person后面出现的小括号, 其实就是在调用构造方法 !
(2)、概述

作用:

​ 用于对象初始化。

执行时机:

​ 在创建对象时,自动调用

特点:

​ 所有的Java类中都会至少存在一个构造方法

​ 如果一个类中没有明确的编写构造方法, 则编译器会自动生成一个无参的构造方法, 构造方法中没有任何的代码!

​ 如果自行编写了任意一个构造器, 则编译器不会再自动生成无参的构造方法。

(3)、构造方法设计

建议自定义无参构造方法,不要对编译器形成依赖,避免错误发生。

当类中有非常量成员变量时,建议提供两个版本的构造方法,一个是无参构造方法,一个是全属性做参数的构造方法。

当类中所有成员变量都是常量或者没有成员变量时,建议不提供任何版本的构造。

(4)、定义格式和示例
package day5;

public class Demo3 {

	public static void main(String[] args) {
		Person1 p = new Person1(); 
		p = new Person1();
		p = new Person1();
		p = new Person1();
		
		p = new Person1("张三", 18, '男');
	}
}

class Person1 {
	String name;
	int age;
	char sex;
	
	public Person1(){ 
		System.out.println("对象创建时,此方法调用");
	}
	
	public Person1(String name, int age, char sex) {
		this.name = name;
		this.age = age;
		this.sex = sex;
		System.out.println("对象创建时,此方法调用 "+name+age+sex);
	}
}

在这里插入图片描述

5、方法的重载

**方法名称相同, 参数类型或参数长度不同, 可以完成方法的重载 ! 方法的重载与返回值无关! **

方法的重载 ,可以让我们在不同的需求下, 通过传递不同的参数调用方法来完成具体的功能。

package day5;

public class Demo4 {

	public static void main(String[] args) {
		Math m = new Math();
		
		int x = 1,y = 2;
		System.out.println(m.sum(x, y));
		
		int z = 3;
		System.out.println(m.sum(x, y, z));
	}

}

class Math {
	int sum(int x, int y) {
		return x + y;
	}
	
	double sum(double x, double y) {
		return x + y;
	}
	
	float sum(float x, float y) {
		return x + y;
	}
	
	int sum(int x, int y, int z) {
		return x + y+ z;
	}
}

在这里插入图片描述

6、构造方法重载

一个类, 可以存在多个构造方法 :

​ 参数列表的长度或类型不同即可完成构造方法的重载

​ 构造方法的重载 ,可以让我们在不同的创建对象的需求下, 调用不同的方法来完成对象的初始化!

7、匿名对象

没有对象名称的对象就是匿名对象。

匿名对象只能使用一次,因为没有任何的对象引用,所以将称为垃圾,等待被GC回收。

只使用一次的对象可以通过匿名对象的方式完成,这一点在以后的开发中将经常使用到。

package day5;

public class Demo5 {

	public static void main(String[] args) {
		//匿名对象只能使用一次,如果使用两次或以上,则一定需要给对象创建对象名
		new Person3("张三", 18).say();
	}

}

class Person3 {
	String name;
	int age;
	
	Person3(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	void say() {
		System.out.println("自我介绍,姓名"+name+"年龄:"+age);
	}

}

在这里插入图片描述

8、阿里巴巴Java编程规范

包含相关eclipse、idea插件以及一些规范文档等:

https://github.com/alibaba/p3c

9、代码练习

  1. 编写 Car 类,属性有品牌(brand)和颜色(color),show 方法打印所有属性。

  2. 定义一个游戏类,包括游戏的属性包括:游戏名、类型、大小、星级、介绍等,可以调用方法输出游戏的介绍。

  3. 定义并测试一个代表员工的 Employee 类。它的属性包括“员工姓名”、“员工号码”、“员工基本薪水”、“员工薪水增长率”;他的方法包括“构造方法”、“获取员工姓名”、“获取员工号码”、“获取员工基本薪水”、“计算薪水增长额”及“计算增长后的工资总额”。

package day5;

public class HomeWork10201001 {

	public static void main(String[] args) {
		new Car("特斯拉", "黑色").show();
		
		Game game = new Game("植物大战僵尸", "休闲", 100, 5, "该游戏是风靡全球的休闲游戏,创造植物守护你的家,防止僵尸吃掉你的脑子");
		game.getGameInfo();
		game.introduceGame();
		
		Employee em = new Employee("张三", "110", 3000, 0.20);
		System.out.println("员工姓名:"+em.getEmployeeName());
		System.out.println("员工号码:"+em.getEmployeeNum());
		System.out.println("员工基本工资:"+em.getEmployeeSalary());
		System.out.println("员工薪资增长额度:"+em.countSalaryIncreases());
		System.out.println("员工涨薪后工资:"+em.countSalaryUpRes());
	}

}

/**
 * 1. 编写 Car 类,属性有品牌(brand)和颜色(color),show 方法打印所有属性。
 */
class Car {
	String brand;
	String color;
	
	Car() {
		
	}
	
	Car(String brand, String color) {
		this.brand = brand;
		this.color = color;
	}
	
	void show() {
		System.out.println("Car属性:" + "品牌:"+ brand + ",颜色:" + color);
	}
}

/**
 * 2. 定义一个游戏类,包括游戏的属性包括:游戏名、类型、大小、星级、介绍等,可以调用方法输出游戏的介绍。
 */
class Game {
	String name;
	String type;
	int size;
	int starLev;
	String info;
	
	Game() {
		
	}
	
	Game(String name, String type, int size, int starLev, String info) {
		this.name = name;
		this.type = type;
		this.size = size;
		this.starLev = starLev;
		this.info = info;
	}
	
	String getGameInfo() {
		return info;
	}
	
	void introduceGame() {
		System.out.println("游戏名:"+name);
		System.out.println("游戏类型:"+type);
		System.out.println("游戏大小:"+size);
		System.out.println("推荐星级:"+starLev);
		System.out.println("介绍:"+info);
	}
}

/**
 *3. 定义并测试一个代表员工的 Employee 类。
 *它的属性包括“员工姓名”、 “员工号码”、“员工基本薪水”、“员工薪水增长率”;
 *他的方法包括“构 造方法”、“获取员工姓名”、“获取员工号码”、“获取员工基本薪水”、 “计算薪水增长额”
 *及“计算增长后的工资总额”。
 */
class Employee {
	String name;
	String num;
	int salary;
	double salaryUpRate;
	
	Employee() {
		
	}
	
	Employee(String name, String num, int salary, double salaryUpRate) {
		this.name = name;
		this.num = num;
		this.salary = salary;
		this.salaryUpRate = salaryUpRate;
	}
	
	String getEmployeeName() {
		return this.name;
	}
	
	String getEmployeeNum() {
		return this.num;
	}
	
	int getEmployeeSalary() {
		return this.salary;
	}
	
	double countSalaryIncreases() {
		return this.salary * this.salaryUpRate;
	}
	
	double countSalaryUpRes() {
		return (1 + salaryUpRate) * this.salary;
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

昵称系统有问题

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值