Java温习——面向对象第一部分

一、软件开发概述

1 软件生命周期

(1)概念

软件的产生到报废的整个过程;


(2)内容

包括问题定义、可行性分析、总体描述、系统设计、编码、调试和测试、验收与运行、维护升级到废弃阶段;

a 问题的定义与规划

软件开发方与需求方共同讨论,主要确定软件开发的目标和可行性;


b 需求分析

在确定软件开发可行的情况下,对软件需要实现的各功能进行详细分析;

该阶段是一个重要阶段,为整个软件开发项目的成功打下良好基础;


c 软件设计

根据需求分析的结果,把整个软件系统划分为大大小小的多个模块,设计每个模块的具体结构;

如系统框架设计、数据库设计等;

软件设计一般分为总体设计和详细设计;


d 程序编码

将软件设计的结果转换成计算机可运行的程序代码;

在程序编码中必须制定统一、符合标准的编写规范,保证程序的可读性、易维护性,提高程序的运行效率;


e 软件测试

在软件设计完成后要经历严密的测试,以发现软件在整个设计过程中存在的问题并加以纠正;

整个测试过程分为单元测试(白盒测试)、集成测试(黑盒、功能测试、强度性能测试)、系统测试三个阶段进行;

测试方法主要包括白盒测试和黑盒测试;

在测试过程中需要建立详细的测试计划并严格按照测试计划进行测试,以减少测试的随意性;


f 运行维护

安装部署软件系统,修复软件中存在的bug和升级系统;

在软件开发完成并投入使用后,由于多方面原因,软件不能继续适应用户的需求,要延续软件的使用寿命,就必须对软件进行维护;

软件维护包括纠错性维护和改进性维护;


2 软件设计原则

为提高软件开发效率,降低软件开发成本,一个优良的软件系统应具备以下特点

(1)可重用性

遵循DRY原则,减少软件中的重复代码;


(2)可拓展性

当软件需要升级增加新的功能,能够在现有的系统架构上方便的创建新的模块,而不需改变软件现有的结构,也不会影响已存在的模块;


(3)可维护性

当用户需求放生变化时,只需修改局部模块中的少量代码即可;


注:

如何让软件系统达到上述特点,对模块的需求:

· 结构稳定性

在软件设计阶段,把一个模块划分为更小的模块时,设计合理,使得系统结构健壮,以便适应用户的需求变化;


· 可拓展性

当软件必须增加新的功能时,可在现有模块的基础上创建新的模块,该模块继承了原有模块的一些特性,并具有一些新特性,从而实现软件的可重用和可拓展性;


· 可组合性

若干模块经过组合,形成大系统,模块的可组合性提高软件的可重用和可维护性,并简化软件开发过程;


· 高内聚性

内聚强调一个模块内的功能联系,每个模块只完成特定的功能,不同模块之间不会有功能的重叠;

高内聚性可提高软件的可重用性和可维护性;


· 低耦合性

耦合强调多个模块之间的关系,模块之间相互独立,修改某一个模块,不会影响其他的模块;

低耦合性提高软件的可维护性;




二、软件开发方式

1 面向过程的开发

(1)面向过程

较早的编程思想;

该思想是站在过程的角度思考,强调功能行为,功能的执行过程是先做什么后做什么;

每个功能通过使用函数把这些步骤一步步实现;

使用时依次调用即可;


(2)面向过程的设计

最小的程序单元是函数,每个函数负责完成某一个功能,用以接收输入数据,函数对输入数据进行处理,再输出结果数据;

整个软件系统由一个个函数组成,其中作为程序入口的函数称之为主函数,主函数依次调用其它函数,普通函数之间可以相互调用,实现整个系统的功能;



如,设计实现买菜、做饭、吃饭、洗碗、写代码功能的程序



(3)面向过程的缺陷

面向过程的设计,采用自顶而下的设计方式,在设计阶段就需要考虑一个模块应该分解成哪些子模块,每个子模块分为更小的子模块,如此类推,直到将模块细化为一个个函数;

a 设计不够直观,与人类的习惯思维不一致

b 系统软件适应性差、可拓展性差、维护性差

最大的问题在于随系统的膨胀,面向过程将无法应付,最终导致系统崩溃;


2 面向对象的开发

(1)面向对象

一种基于面向过程的新的编程思想;

该思想是站在对象的角度思考问题,把多个功能合理的放到不同对象中;

强调具备某些功能的对象

具备某种功能的实体,成为对象;

面向对象最小的程序单元是类;



如上例,使用面向对象的思想实现



(2)面向对象的设计

面向对象更符合常规思维方式,稳定性好、可重用性强、易于开发大型软件产品,可维护性强;

在软件工程中,面向对象可使工程更模块化,实现更低的耦合和更高的内聚;

面向对象四大特点 —— 封装、继承、多态、抽象;

封装,指将对象的实现细节隐藏起来,通过公共的方法向外暴露该对象的功能;

继承,指面向对象实现软件复用的重要手段,当子类继承父类后,子类是一种特殊的父类,能直接或间接获得父类的成员;

多态,指可直接把子类对象赋给父类变量,但运行时依然表现出子类的行为特征,表示同一类型的对象在运行时可能表现出不同的行为特征;




三、类和对象

1 抽象概念

从特定的角度出现,从已存在的一些事物中抽取我们所关注的特性、行为,从而形成一个新的事物的思维过程,是一种从复杂到简洁的思维方式;


2 类和对象的关系

(1)对象

对象object,可定义成包含状态和行为的一个实体,又称实例instance;

实体,指实际存在的个体;

对象是人们要进行研究任何事物,一切事物都可认为是对象;

对象具有状态(数据)行为(功能)


(2)类

通过对多个同类型的对象进行分析,将对象抽象成类;

类,指具有相同特性(状态)和行为(功能)的对象的抽象;

类是对象的类型/模板,创建一个对象,就是使用一个类作为构建该对象的基础;


(3)关系

对象的抽象是类,类的具体化是对象,即类的实例是对象,对象的模板的是类;

类实际上是一个数据类型;

类具有的特性称为对象的状态,用成员变量表示;

类具有的功能称为对象的行为,用方法表示;


3 类的语法定义

[修饰符] class <类名>{
	<0~N个成员变量/字段/field> // 不要叫属性,因为属性是JavaBean中一种特殊的成员
	<0~N个成员方法>
}


注:

若类使用了public修饰符,必须保证当前文件名和当前类名相同;

类表示某一类事物,因此类名使用名词表示,且首字母大写,若由多个单词组成,使用驼峰表示法,如EmployeeAdvanceSetting;

在面向对象的学习过程中,对于专门描述对象而定义的一个类中不需要main方法,而是再定义一个测试类/演示类来运行程序;


4 对象的基本操作

(1)对象的创建和使用

a 创建对象

<类名> <对象名> = new <类名>();


b 对象使用

<对象名>.<成员变量> = <值>; // 给字段设置值

<字段数据类型> <变量> = <对象名>.<成员方法>; // 获取字段的值

<对象名>.<方法名>(<实参>); // 通过对象调用方法


(2)对象的实例化过程

不同类型的成员变量的初始值(局部变量没有默认值,因此使用前必须初始化



如下给出创建对象时的内存分配图



(3)对象的打印和比较对象

a 对象的打印

打印内容包括类名、@符号、十六进制hasCode值(决定了该对象在哈希表的存储位置),如Servant@3294e4f4,

实际上,打印对象时,往往关心该对象的数据(可使用Object.toString()方法);


b 对象的比较操作

==符号,对于基本数据类型比较的是值,对于引用数据类型比较的是内存中的地址值;

每次使用new关键字表示在堆中开辟一块内存空间,不同的内存空间的地址值不同;

若希望拥有完全相同的数据的对象相等,可使用Object.equals()方法;


(4)对象的生命周期

对象的出生 —— 每次使用new关键字,就会在内存空间开辟新的空间;

对象的消亡 —— 当堆中的某个对象没有被任何变量所引用,此时该对象成为垃圾,等待垃圾回收器GC回收该垃圾,当GC回收该对象时,便销毁;(回收垃圾的目的是释放更多的内存空间)


(5)匿名对象

没有名称的对象,即创建对象后没有赋值给某一个变量,即只在堆中开辟一块新的内存空间,没有将内存空间地址赋值给任何变量,如 new Servant();

因为没有名称,匿名对象只能使用一次;

一般,把匿名对象作为方法的实参传递;


(6)学生缴费案例

a 需求

学生类Student有两个字段:name(名称)和isFee(是否交学费),有一个方法:fees(交学费);

每个学生都是通过Student类new出的一个对象,现创建一个数组存放多个学生对象,再判断数组中的学号是否已经缴费,若没有则调用学生的缴费方法;

b 代码实现

// 描述学生对象
class Student{
	String name; // 学生名称
	boolean isFee = false; // 学生缴费状态,默认未缴费

	void fee(){
		isFee = true;
	}
}

// 测试类
public class StudentDemo{
	public static void main(String[] args){
		Student s1 = new Student();
		s1.name = "赵一";
		s1.isFee = true;

		Student s2 = new Student();
		s2.name = "倩儿";
		
		Student s3 = new Student();
		s3.name = "孙三";
		s3.isFee = true;

		Student s4 = new Student();
		s4.name = "李四";

		// 创建一个数组,用于存储所有学生对象
		Student[] stus = new Student[]{s1, s2, s3, s4};

		// 使用循环迭代数组中的每一个元素
		for(Student stu : stus){
			System.out.println(stu.name + "\t" + stu.isFee);
			// 判断当前对象是否缴费,若无则调用缴费方法
			if(!isFee){
				stu.fees();
			}
		}
	}
}

c 内存分析


 



四、构造器Constructor

创建一个学生对象Student s = new Student();,特别像在调用一个方法名称为Student的无参数方法,称为构造器,又构造函数/构造子;

但在Student类中找不到该方法,且编译没有报错,因为编译器在编译源文件时,会创建一个缺省的构造器;

1 构造器作用

a 创建对象,但必须和new一起使用;

b 完成对象的初始化操作;


2 构造器特点

a 构造器名称与当前所在类的名称相同;

b 禁止定义返回类型,千万不要使用void作为返回类型(void Student()是普通方法;假设需要写返回类型,也要写Student Student();,既然所有的返回类型都和所在类名相同,何必再写?!);

c 在构造器中,不需要使用return语句(其实构造器有返回值,返回的是当前创建对象的引用);


若没有显式定义构造器,则编译器在编译时创建一个缺省构造器;若显式定义构造器,则编译器不再创建默认构造器;(某一个类至少存在一个构造器)


3 缺省构造器

a 符合构造器特点的3个特点;

b 无参数的;

c 无方法体的;

d 若类A没有使用public修饰,则编译器创建的默认构造器也没有public修饰;若类A使用public修饰,则编译器创建的默认构造器也有public修饰;



4 自定义构造器

class Person{
	String name;

	// 自定义构造器
	Person(){ // 构造器重载中的无参数
		System.out.println("无参数");
	}
	Person(String str){ // 构造器重载中的有参数
		name = str; // 初始化操作,可以给字段设置初始值,也可以调用初始化方法
		
	}
}

public class PersonDemo{
	// 创建对象,其实在调用构造器
	/*
	Person p1 = new Person(); // 表示调用Person类中无参数的构造器
	p1.name = "Will";
	*/
	Person p2 = new Person("Will"); // 表示调用Person类中有一个String类型参数的构造器
}


5 构造器重载

方法重载的目的是避免在同一个类中,相同功能的方法名称不同的问题;

判断依据:两同一不同;

构造器是一种特殊的方法,也可以存在重载;




五、static修饰符

static修饰符表示静态的,可修饰字段、方法、内部类,其修饰的成员属于类,即static修饰的资源属于类级别,而非对象级别;

static作用是用以区别字段、方法,内部类,初始化代码是属于对象还是属于类本身;

1 staitc修饰符特点

(1)static修饰的成员(字段/方法),随所在类的加载而加载;

当JVM把字节码加载进JVM,static修饰的成员已存在内存中;

(2)优先于对象的存在;

对象是手动通过new关键字创建的;

(3)static修饰的成员被该类型的所有对象所共享;

根据该类创建的任何对象都可访问static成员;

表面上对象去访问static成员,但其本质依然使用类名访问,和对象没有任何关系;

(4)直接类名访问static成员;

因为static修饰的成员直接属于类,不属于对象;


2 static成员在JVM中的存储

举例说明

// 人类
public Person{
	String name;
	int age;
	static totalNum = 5; // 不属于某个对象,属于人类
	
	Person(String name, int age){
		this.name = name;
		this.age = age;
		totalNum ++;
	}

	void die(){
		totalNum --;
		System.out.println("去世...");
	}

	static void destory(){
		totalNum = 0;
		System.out.println("人类灭亡...");
	}
}

// 演示static修饰符
public class PersonDemo{
	System.out.println(Person.totalNum); // 5
	Person p1 = new Person("Will", 18);
	System.out.println(Person.totalNum); // 6
	p1.die();
	System.out.println(Person.totalNum); // 5
	Person.destory();
	System.out.println(Person.totalNum); // 0
}


内存分析



3 类成员和实例成员的访问

类中的成员包括字段、方法、内部类;

(1)类成员

使用static修饰的成员;

类成员只能访问类成员;

类成员直接属于类,通过类访问static字段和static方法;


(2)实例成员

没有使用static修饰的成员;

实例成员只能访问实例成员;

实例成员只属于对象,通过对象访问非static字段和非static方法;

对象可访问类成员,但底层依然使用类名访问;


注:

在static方法中只能调用static成员;

非static方法中可访问静态成员、实例成员;

定义static字段/方法的情况 —— 若这一状态/行为属于整个事物(类),被所有对象所共享,直接使用static修饰符;

在开发中,往往把工具方法使用static修饰,因为不使用static修饰,则这些方法属于该类的对象,需要先创建对象才能调用这些方法;

类成员优势 —— 对对象的共享数据进行单独空间的存储,节省空间,没必要每个对象都存储一份,科直接使用类名调用;

类成员弊端—— 生命周期过长(字节码一旦加载,就永驻内存);


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值