二维数组(了解)
/**
* 二维数组
*/
public class TowArrayDemo {
public static void main(String[] args) {
//1.创建一个空数组
//数据类型[][] 数组名 = new 数据类型[行][列]
//一行相当于是一个一维数组 列相当于是一维数组存储元素的个数
int[][] arr = new int[3][5];
//2.二维数组赋值创建
int[][] arr2 ={
{1,1,1,0,1,1,1},
{1,1,0,0,0,1,1},
{1,0,0,0,0,0,1},
{1,1,0,0,0,1,1},
{1,1,1,0,1,1,1}
};
//如何遍历
//二维数组的遍历必须是一个双层for循环
//外层数组主要数确定函数,存储了多少个一维数组
for(int i =0 ; i<arr2.length;i++){
//内层循环相当于获取一维数存储的数据【获取列】
for(int j = 0 ;j<arr2[i].length;j++){//arr1[i]获取了存在二维数组中一维数组
//取值或赋值操作
//arr2[i][j]
if(arr2[i][j] == 0){
System.out.print("*");
}else{
System.out.print(" ");
}
}
System.out.println();
}
}
}
作业
1.定义一个数组,数组成员10个,找出数组中最大数连同下标一起输出
/*
思路: 因为10个元素【谁也不知道谁是最大值】
进行假设 假设数组中第一个元素最大 max = arr[0] 这是一个假设,不能确定
验证: 遍历数组 --》 普通for循环 和 增强for循环
要求下标: 使用普通for循环
线性遍历 --> 从第一个下标位置开始找到最后一个位置结束
int index = 0 ; 存储下标
if(arr[i] > max){
max = arr[i];
index= i;
}
循环完成之后 max 和index 最大值和下标
*/
2.B哥去参加青年歌手大奖赛,有10个评委打分,(去掉一个最高一个最低)求平均分?
/*
思路: 因为10个元素【谁也不知道谁是最大值,谁最小】
进行假设 假设数组中第一个元素最大 max = arr[0]
假设数组中第一个元素最小 min = arr[0]
这是一个假设,不能确定
验证: 遍历数组 --》 普通for循环 和 增强for循环
要求下标: 使用普通for循环
线性遍历 --> 从第一个下标位置开始找到最后一个位置结束
int sum = 0 ; 存储下标
if(arr[i] > max){
max = arr[i];
}
if(min > arr[i]){
min = arr[i];
}
sum += arr[i]
循环完成之后 max 和 min 一定是最大和最小
( sum - max-min)/arr.length-2
*/
3.给定一个整型数组,数组成员10个,求该数组中第二大的数的下标(不考虑特殊情况,相同)
/*
因为要找第二大的值
先定义两个变量 max 和 maxtow
进行假设 这个假设进行进行了判断
if(arr[0] > arr[1]){
max = arr[0]
maxtow = arr[1];
}else{
max = arr[1];
maxtow = arr[0];
}
//判断数组剩余8个元素和这个两个数据关系
if(arr[i] > max){
maxtow = max
max = arr[i]
}else if(arr[i] > maxtow){
maxtow = arr[i]
}
打印maxtow
*/
地址作为参数进行传递
Java中面向对象
伟大的程序员都有三个优点:懒惰、暴躁和自负。乍一看这三个词语没有一个是褒义词,但在程序员的世界里,这三个词有不同的意义。首先,懒惰会促使程序员去写一些省事儿的程序来辅助自己或别人更好的完成工作,这样我们就无需做那些重复和繁琐的劳动;同理能够用3行代码解决的事情,我们也绝不会写出10行代码来。其次,暴躁会让程序员主动的去完成一些你还没有提出的工作,去优化自己的代码让它更有效率,能够3秒钟完成的任务,我们绝不能容忍1分钟的等待。最后,自负会促使程序员写出可靠无误的代码,我们写代码不是为了接受批评和指责,而是为了让其他人来膜拜。
一、件生命周期:
软件生命周期: 软件的产生直到报废的整个过程.
软件生命周期内有:问题定义, 可行性分析, 总体描述, 系统设计,编码, 调试和测试, 验收与运行, 维护升级到废弃等阶段
--------------------------------------------------------------------------------------
1):问题的定义及规划: 此阶段是软件开发方与需求方共同讨论,主要确定软件的开发目标及其可行性。
2):需求分析: 在确定软件开发可行的情况下,对软件需要实现的各功能进行详细分析。需求分析阶段是一个很重要的阶段,这一阶段做得好,将为整个软件开发项目的成功打下良好的基础。
3):软件设计: 此阶段主要根据需求分析的结果,把整个软件系统划分为大大小小的多个模块,设计出每一个模块的具体结构。如系统框架设计,数据库设计等。软件设计一般分为总体设计和详细设计。
4):程序编码: 此阶段是将软件设计的结果转换成计算机可运行的程序代码。在程序编码中必须要制定统一,符合标准的编写规范。以保证程序的可读性,易维护性,提高程序的运行效率。
5):软件测试: 在软件设计完成后要经过严密的测试,以发现软件在整个设计过程中存在的问题并加以纠正。整个测试过程分单元测试(白盒)、集成测试(黑盒,功能测试、强度性能测试)以及系统测试三个阶段进行。测试的方法主要有白盒测试和黑盒测试两种。在测试过程中需要建立详细的测试计划并严格按照测试计划进行测试,以减少测试的随意性。
6):运行维护: 安装部署软件系统,修复软件中存在的bug和升级系统。在软件开发完成并投入使后,由于多方面的原因,软件不能继续适应用户的要求。要延续软件的使用寿命,就必须对软件进行维护。软件的维护包括纠错性维护和改进性维护两个方面。
二、软件设计原则:
为了提高软件的开发效率,降低软件开发成本,一个优良的软件系统应该具有以下特点:
1,可重用性:遵循DRY原则,减少软件中的重复代码。
2,可拓展性:当软件需要升级增加新的功能,能够在现有的系统架构上方便地创建新的模块,而不需要改变软件现有的结构,也不会影响以及存在的模块。
3,可维护性:当用户需求发生变化时,只需要修改局部的模块中的少量代码即可。
如何让软件系统达到上述的特点,我们对模块的要求:
1):结构稳定性:在软件设计阶段,把一个模块划分为更小的模块时,设计合理,使得系统结构健壮,以便适应用户的需求变化。
2):可拓展性:当软件必须增加新的功能时,可在现有模块的基础上创建出新的模块,该模块继承了原有模块的一些特性,并且还具有一些新的特性,从而实现软件的可重用和可拓展性。
3):可组合性:若干模块经过组合,形成大系统,模块的可组合性提高软件的可重用和可维护性,并且能简化软件开发过程。
4):高内聚性:内聚,强调一个模块内的功能联系,每个模块只完成特定的功能,不同模块之间不会有功能的重叠,高内聚性可以提高软件的可重用性和可维护性。
5):低耦合性:耦合,强调的是多个模块之间的关系,模块之间相互独立,修改某一个模块,不会影响到其他的模块。低耦合性提高了软件的可维护性。
面向对象和面向过程
之前我们说过“程序是指令的集合”,我们在程序中书写的语句在执行时会变成一条或多条指令然后由CPU去执行。当然为了简化程序的设计,我们引入了方法(函数)的概念,把相对独立且经常重复使用的代码放置到方法中,在需要使用这些功能的时候只要调用方法即可;如果一个方法的功能过于复杂和臃肿,我们又可以进一步将方法继续切分为子方法来降低系统的复杂性。但是说了这么多,不知道大家是否发现,所谓编程就是程序员按照计算机的工作方式控制计算机完成各种任务。但是,计算机的工作方式与正常人类的思维模式是不同的,如果编程就必须得抛弃人类正常的思维方式去迎合计算机,编程的乐趣就少了很多,“每个人都应该学习编程”这样的豪言壮语就只能说说而已。当然,这些还不是最重要的,最重要的是当我们需要开发一个复杂的系统时,代码的复杂性会让开发和维护工作都变得举步维艰,所以在上世纪60年代末期,“软件危机”、“软件工程”等一系列的概念开始在行业中出现。
当然,程序员圈子内的人都知道,现实中并没有解决上面所说的这些问题的“银弹”,真正让软件开发者看到希望的是上世纪70年代诞生的Smalltalk编程语言中引入的面向对象的编程思想(面向对象编程的雏形可以追溯到更早期的Simula语言)。按照这种编程理念,程序中的数据和操作数据的函数是一个逻辑上的整体【类】,我们称之为“对象”,而我们解决问题的方式就是创建出需要的对象并向对象发出各种各样的消息,多个对象的协同工作最终可以让我们构造出复杂的系统来解决现实中的问题。
Ps:银弹: 提高软件生产力的万能的方法
PS:面向对象不是一个独立的编程思想,面向对象是在原有面向过程基础上进行升华得到,所以面向对象中也会掺杂着面向过程的思维
面向过程
面向过程:是一种较早的编程思想【60时年代】,顾名思义该思想就是站在过程的角度思考问题,强调的就是功能行为,功能行为就是【先干什么,在什么】,每一个功能我们都使用【函数】(和方法是一样东西),把这些步骤一步一步实现,使用的时候依次调用
举个例子【洗袜子】:
1.倒一盆水
2.把袜子倒入盆中
3.到洗衣粉泡一泡
4.搓一搓晾起来
面向过程的设计:
最小的程序单元是函数(方法),每个函数负责完成某一个功能,用以接受输入数据,函数对输入数据进行处理,然后输出结果数据.
整个软件系统由一个个的函数组成,其中作为程序入口的函数称之为**主函数,**主函数依次调用其他函数,普通函数之间可以相互调用,从而实现整个系统功能.
面向过程的缺陷:
面向过程的设计,是采用置顶而下的设计方式,在设计阶段就需要考虑每一个模块应该分解成哪些子模块,每一个子模块有细分为更小的子模块,如此类推,直到将模块细化为一个个函数.
(真的能在一开始就把需求分的那么细吗?真不能,需求是不断的变动的)
存在的问题:
1):设计不够直观,与人类的习惯思维不一致.
(人类的思想应该是谁来吃饭,而不是吃饭谁来,谁来完成什么功能,而不是什么功能谁来参与)
2):系统软件适应性差,可拓展性差,维护性低.
面向过程最大的问题在于随着系统的膨胀,面向过程将无法应付,最终导致系统的崩溃。为了解决这一种软件危机,我们提出面向对象思想
面向对象
面向对象是一种基于面向过程的一种新的编程思想,顾名思义该思想是站在对象的角度思考问题,我们把多个功能合理的方法放到不同对象,强调的是具备某个功能对象
对象,就是具备某些功能的实体【实际存在个体】
举例子【洗袜子】
虐汪版本:找一个对象(女朋友/男朋友),只需要将袜子传递给对象等待洗干净即可
自虐版本:找一个对象(女朋友/男朋友),你女友/男友将袜子给你洗干净来取
自立更省版本: 找一个对象(洗衣机),把袜子扔到洗衣机中完成即可
面向对象更加符合我们常规思维方式,稳定性好,可重用性强,易于开发大型的软件产品,有良好的可维护性,在软件工程上,面向对象可以使工程根本更加模块化【具备某些相同功能的对象在同一个模块中,模块的分类有一个设计方式(MVC)】,实现更低耦合和更高的内聚。
在面向对象中(Java)最小的程序单元是【类】
Java中面向对象体现
面向对象的三大支柱:【封装、继承、多态】
封装:
封装是把一个事物包起来,使外界不了解它内部的具体情况,在面向对象的程序设计中,封装就是把相关数据和代码结合成一个有机的整体,形成数据和操作代码的封装体.对外部只提供一个可以操作的接口.通俗的说法:在设计一个类的时候,将所有的属性设计为私有的,并对各个私有属性设计想对应的getter/setter访问器,本质:就是属性的私有化过程
继承:
继承是从已有的类创建新类的过 程**,提供继承信息的是父类**,得到继承信息称为子类,子类和父类之间是IS-A(继承)关系,继承使得类与类之间形成了一个层次结构,在Java中没有多继承的概念.
多态:
多态允许程序中出现重名的现象,JAVA语言中含有方法重载与对象多态两种形式就是多态.
方法重载:在一个类中,允多个方法使用一个名字,但方法的参数不同,返回值不同,完成的功能也不同
对象多态:子类对象可以与父类对象进行相互转换,而且根据其使用的子类的不同,完成功能也不同
数据类型转换【自动转换、强制类型转换】
对象的向上和向下转型 instanceof
面向对象基于面向过程而言
通俗解释
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ismn5ZUn-1666441611320)(面向对象基础.assets/图片7.png)]
Java中的类和对象
什么叫做抽象?
从特定的角度出发,从已经存在的一些事物中抽取我们所关注的特性**(属性)、行为(方法),**从而形成一个新的事物思维,这种方式就叫做抽象
什么是对象?
听到,看到,摸到,想到,闻到,都可以成为对象,世间万物皆对象,能够独立并带有意义【符合客观现实规律】
对象本身是具备属性和行为,对象是可以包含状态和行为的一个实体,对象(Object)也称为实例(instance)
实例:通过抽象现实世界中属性和行为构建出来
对象是一个实际存在的个体,我们需要描述对象属性和行为,描述对象的属性和行为存储在什么位置?
类
类用来描述对象【对象中抽取出来属性和行为所存在位置】,类中所存储是所有对象共有的属性和行为
具有相同属性和行为的对象的抽象就是类
我们抽取出来属性写在类中,抽取出来的行为写在类型,相当于如果需要创建某个对象,那么就必须存在某一个类
类实际上一种数据类型,这个数据类型中封装着变量和方法,所以类是一种【引用类型】
类中封装属性和行为如何表示?
属性 在类中表示方式 定义变量【这个变量可以使用权限修饰符,可以使用static修饰符(不建议对对象使用),并且这个变量有默认值】
行为 在类中的表示方式 定义方法【这个方法可以使用权限修饰符,不写static关键字,剩余方式和定义方法一样】
用来描述对象属性 --》【成员变量】
用来描述对象行为 --》 【成员方法】
PS:成员变量还是成员方法 都不会使用static修饰
类是对象抽象,对象是类的实例化
在代码中如何创建类和对象
语法:
1.创建类
访问权限修饰符 class 类名{
成员变量
成员方法
}
PS:
"1.定义类的时候权限修饰符只能使用两个 一个是public 另外一个是default【不写就是默认】"
"2.class 是一个关键字,表示是类【一定要严格区分大小写】"
"PS:Class 和 class 都行 但是含义不同"
"外部类中没有其他修饰符"
"3.类名要有实际意义主要体现要创建对象"
"4.成员变量和成员方法是给【对象使用】,每个对象都是独立"
2.创建对象
类名 对象名 = new 类名();
PS:
"此时类名就是对象的数据类型"
案例:定义一个人类,属性有身高,体重,年龄,性别,名字 行为,吃 睡觉 打豆豆
/*
如果这个类是对 对象的描述 这个类就称之为 描述类【实体类】
这个类中是不会写main方法,就是对 对象的描述作用,不会执行【不写main方法】
*/
public class Person {
/*之前在学习变量的时候,我们说过变量有两种 一种是局部变量【定义在方法体中】
另外一种是全局变量【定义在类体中的】
这个全局变量有另外一个名字 --》 成员变量
描述是对象属性 --》成员变量 描述是类的即使用static修饰 --》 静态变量
* */
int height; // 成员变量 即 对象属性
int weight;
int age;
char gender;
String name;
//如何定义成员方法 ,不使用static关键字 --》 对象行为
/*
访问权限修饰符 返回值类型 方法名(参数列表){
执行语句
return
}
*/
public void eat(){
System.out.println("正在吃东西.....");
}
public void sleep(){
System.out.println("在睡觉.....");
}
public void palydd(){
System.out.println("打豆豆");
}
}
/**
* Person是一个描述类,所以描述类不执行main方法
* 我们就需要提供一个可以执行这个逻辑类,这个类就叫做 :测试类【执行类】
* 主要就是执行创建对象之后的逻辑,这类中必然有main方法
*/
public class PersonTest {
public static void main(String[] args) {
//1.创建对象
Person xiaoming = new Person();
//之前对成员变量叫法 叫做 全局变量原因在于,任何位置都可以访问操作
//如何使用成员变量 --> 对象名.成员变量名
//面向对象中,对象名 后面的【.】 可以翻译成 the
//所有在类中所声明的成员变量都是有默认值的,所以在外部可以直接访问
System.out.println("小明的年龄是:"+xiaoming.age);
//修改成员变量的值
xiaoming.age = 19;
System.out.println("小明的年龄是:"+xiaoming.age);
xiaoming.name = "小明";
System.out.println(xiaoming.name+"的年龄是:"+xiaoming.age);
//调用成员方法
xiaoming.eat();
Person xiaohong = new Person();
//每个对象的成员变量和成员方法都是独立的
System.out.println(xiaohong.age);
}
}
总结:
所有的成员变量都是有默认值,这个默认值是根据数据类型决定的
基本数据类型:
整数类型【0】 小数类型【0.0】 字符类型【默认不可见空字符】 boolean类型【false】
引用数据类型
所有引用数据类型的默认值都是统一为【null】,切记,切记,切记!!!在使用引用类型成员变量是,一定要去人是否赋值了,没有赋值即初始值为null一定不要使用,否则必然空指针异常
构造方法(Constructor)
构造方法的主要目的,就是帮组我们来创建对象,在创建对象的同时对属性进行初始化
构造方法只能写在类中,类在没有明确提供构造方法的前提下,默认会提供一个无参构造方法
new 类名() --> 类名() 就是无参构造方法
构造语法:
访问权限修饰符 类名(参数列表){
对成员变量进行赋值操作
}
PS:
"1.构造方法只能写在类中,并且构造方法允许和重载【根据参数的不同来进行重载操作】"
"2.构造方法可以使用的权限修饰符一个是public ,另外一个讲 单例设计模式的时候说"
"3.一定没有返回类型 ,并且构造方法的名字必须是类的名字"
"4.构造方法区分为两种方式:"
"4.1 无参构造方法 --》 指参数列表中什么都不写 ---》()"
"4.2 有参构造方法 --》 指参数列表中写需要定义形参 ---》 (int a,int b)"
PS:构造方法中心目的除了构建对象之外,另外一个目的就是对成员变量进行赋值
,所以这个形参列表,成员变量有哪些,这个形参列表写什么
强烈建议:只要创建描述类就必然提供【有参和无参构造方法】
即在创建描述类的时候
public class 类名{
定义成员变量
提供有参无参构造方法
定义成员方法
}
需求:描述一个学生,属性有名字和年龄,使用构造方法初始化这两个属性
/**
* 描述类
*/
public class Student {
int age;
String name;
//在类中没有明确提供构造方法的前提下,默认系统会提供一个无参构造方法
//但是只要在类中没明确的写出构造方法【无论是有参还是无参】,系统提供默认构造方法将无法在调用
//提供构造方法【无参构造方法】
public Student(){
//这个方法体中可以对属性进行赋值操作
//或调用其他构造方法【this关键和super关键字讲解】
age = 1;
name = "你好";
}
//有参构造方法
public Student(int a,String n ){
age = a;
name = n;
}
}
/**
* 测试类
*/
public class StudentTest {
public static void main(String[] args) {
//创建Student对象
//调用了Student类中无参构造方法创建Student对象
//构造方法只能在创建对象的时候使用无法使用其他方式调用
//只要在无参构造方法中对属性尽心赋值了,以后通过无参构造方法创建的所有对象都有这个默认值
Student stu1 = new Student();
System.out.println(stu1.age);
System.out.println(stu1.name);
//调用Student类中有参构造方法创建Student对象的同时并对属性进行初始化
/**
* 调用有参构造方法时,传递参数的必须和有参构造方法的形参列表一致
* 有参构造方法有多少个参数,调用的时候就需要传递多少个参数
* 创建对象的同时对成员变量进行初始化
*/
Student stu2 = new Student(18,"张三");
System.out.println(stu2.age);
System.out.println(stu2.name);
//注意:无参构造方法中对属性的赋值时固定,有参构造方法是动态改变的【你用什么就传什么】
// 因为无参或有参构造方法是一个方法,所以是可以存在return,但是不要写
}
}