type
status
date
slug
summary
tags
category
icon
password
数据类型
软件是用来处理数据的程序,可以把软件分为两个部分,一部分是数据;另一部分则是数据处理的逻辑,即程序=数据+逻辑。
程序开发离不开数据,在生活中数据是有类型的,例如人的姓名是字符串类型,人的年龄是正整数类型。在Java中数据也是有类型的(任何数据必然会有类型)。
Java中数据类型分为两种:
- 基本数据类型是Java语言中内置的类型,分别是整数类型、小数类型、字符类型、布尔类型;这四类基本类型是最简单、最基础的类型
- 引用数据类型是强大的数据类型,它是基于基本数据类型创建的;JavaSE中提供了一个超级类库,类库中包含了近万种引用数据类型
基本数据类型
Java中的基本数据类型分为四类八种,如下表所示:
四类 | 八种 | 字节数 | 数据表示范围 |
整型 | byte | 1 | -128~127 |
ㅤ | short | 2 | -32768~32767 |
ㅤ | int | 4 | -2147483648~2147483648 |
ㅤ | long | 8 | -263~263-1 |
浮点型 | float | 4 | -3.403E38~3.403E38 |
ㅤ | double | 8 | -1.798E308~1.798E308 |
字符型 | char | 2 | 表示一个字符,如('a','A','0','家') |
布尔型 | boolean | 1 | 只有两个值true与false |
boolea 只有两个值:true、false,可以使用1 bit来存储,但是具体大小没有明确规定;JVM 会在编译时期将boolean类型的数据转换为int,使用1来表示true,0表示false;JVM 支持boolean数组,但是是通过读写byte数组来实现的。
引用数据类型
创建变量
与定义基本数据类型变量不同,引用数据类型的变量定义及赋值有一个相对固定的步骤或格式:
数据类型 变量名 = new 数据类型();
每种引用数据类型都有其功能,可以调用该类型实例的功能:
变量名.方法名();
Scanner类
Scanner类是引用数据类型的一种,可以使用该类来完成用户键盘录入,获取到录入的数据。
使用
- 导包
- 创建键盘录入对象
- 读取键盘录入的一个整数
- 读取键盘录入的字符串
案例
Random类
Random类可以产生多种数据类型的随机数。
使用
- 导包
- 创建实例
- 调用方法
案例
数据类型转换
不同类型的变量可以在一起运算,但要先进行类型转换再运算。
转换的过程中,数据遵循一个原则:
- 范围小的数据类型值,可以直接转换为范围大的数据类型值,如byte转int
- 范围大的数据类型值,不可以直接转换为范围小的数据类型值,如int转byte
将各种数据类型按照数据范围从小到大依次列出:
byte -> short -> int -> long -> float -> double
数据类型转换有两种方式:
- 自动类型转换
表示范围小的数据类型转换成范围大的数据类型,这种方式称为自动类型转换。
自动类型转换格式:
范围大的数据类型 变量 = 范围小的数据类型值;
- 强制类型转换
表示范围大的数据类型转换成范围小的数据类型,这种方式称为强制类型转换
强制类型转换格式:
范围小的数据类型 变量 = (范围小的数据类型) 范围大的数据类型值;
流程控制
选择结构if
if语句
if语句是指如果满足某种条件,就进行某种处理。
例如,小明妈妈跟小明说“如果你考试得了100分,星期天就带你去游乐场玩”。这句话可以通过下面的一段伪代码来描述:
在上面的伪代码中,“如果”相当于Java中的关键字if,“小明考试得了100分”是判断条件,需要用()括起来,“妈妈星期天带小明去游乐场”是执行语句,需要放在{}中。修改后的伪代码如下:
上面的例子就描述了if语句的用法,在Java中,if语句的具体语法格式如下:
上述格式中,判断条件是一个布尔值,当判断条件为true时,{}中的执行语句才会执行。if语句的执行流程如下图所示:
if…else语句
书写格式:
上述格式中,判断条件是一个布尔值;当判断条件为true时,if后面{}中的执行语句1会执行;当判断条件为false时,else后面{}中的执行语句2会执行。
if…else语句的执行流程如下图所示:
if…else if…else语句
书写格式:
if…else if…else语句的执行流程如下图所示:
选择结构if语句与三元运算转换
三元运算符会得到一个结果,通常用于对某个变量进行赋值,当判断条件成立时,运算结果为表达式1的值,否则结果为表达式2的值。
使用if语句还是三元表达式:
- 判断条件多,使用if
- 三元,必须有结果的, if 可以没有结果的
选择结构switch
switch 条件语句也是一种很常用的选择语句,它和if条件语句不同,它只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码。
switch语句的基本语法格式:
在上面的格式中,switch语句将表达式的值与每个case中的目标值进行匹配,如果找到了匹配的值,会执行对应case后的语句,如果没找到任何匹配的值,就会执行default后的语句。
switch语句中的break关键字将在后面的做具体介绍,此处,我们只需要知道break的作用是跳出switch语句即可。
注意:在switch语句中的表达式只能是byte、short、char、int类型的值,如果传入其它类型的值,程序会报错。但上述说法并不严谨,实际上在JDK5.0中引入的新特性enum枚举也可以作为switch语句表达式的值,在JDK7.0中也引入了新特性,switch语句可以接收一个String类型的值。
在使用switch语句的过程中,如果多个case条件后面的执行语句是一样的,则该执行语句只需书写一次即可,这是一种简写的方式。
循环语句while
while循环语句和选择结构if语句有些相似,都是根据条件判断来决定是否执行大括号内的执行语句;区别在于,while语句会反复地进行条件判断,只要条件成立,{}内的执行语句就会执行,直到条件不成立,while循环结束。
while循环语句的语法结构如下:
在上面的语法结构中,{}中的执行语句被称作循环体,循环体是否执行取决于循环条件,当循环条件为true时,循环体就会执行;循环体执行完毕时会继续判断循环条件,如条件仍为true则会继续执行,直到循环条件为false时,整个循环过程才会结束。
while循环的执行流程如下图所示:
循环语句for
for循环语句是最常用的循环语句,一般用在循环次数已知的情况下。
for循环语句的语法格式如下:
在上面的语法结构中,for关键字后面()中包括了三部分内容:初始化表达式、循环条件和操作表达式,它们之间用“;”分隔,{}中的执行语句为循环体。
接下来分别用①表示初始化表达式、②表示循环条件、③表示操作表达式、④表示循环体,通过序号来具体分析for循环的执行流程;具体如下:
- 第一步,执行①
- 第二步,执行②,如果判断结果为true,执行第三步,如果判断结果为false,执行第五步
- 第三步,执行④
- 第四步,执行③,然后重复执行第二步
- 第五步,退出循环
循环语句do…while
do…while循环语句和while循环语句功能类似,其语法结构如下:
在上面的语法结构中,关键字do后面{}中的执行语句是循环体;do…while循环语句将循环条件放在了循环体的后面,这也就意味着,循环体会无条件执行一次,然后再根据循环条件来决定是否继续执行。
do…while循环的执行流程如下图所示:
注意:如果循环条件在循环语句开始时就不成立,那么while循环的循环体一次都不会执行,而do…while循环的循环体还是会执行一次。
无限循环
最简单无限循环格式:
无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环。
循环嵌套
嵌套循环是指在一个循环语句的循环体中再定义一个循环语句的语法结构,while、do…while、for循环语句都可以进行嵌套,并且它们之间也可以互相嵌套。
最常见的在for循环中嵌套for循环格式如下:
跳转语句:break、continue
跳转语句用于实现循环执行过程中程序流程的跳转,在Java中的跳转语句有break语句和continue语句。
break语句
在switch条件语句和循环语句中都可以使用break语句。
当它出现在switch条件语句中时,作用是终止某个case并跳出switch结构;当它出现在循环语句中,作用是跳出循环语句,执行后面的代码。
当break语句出现在嵌套循环中的内层循环时,它只能跳出内层循环,如果想使用break语句跳出外层循环则需要对外层循环添加标记。
continue语句
continue语句用在循环语句中,它的作用是终止本次循环,执行下一次循环。
在嵌套循环语句中,continue语句后面也可以通过使用标记的方式结束本次外层循环,用法与break语句相似。
猜数字案例
案例介绍
游戏操作如下:
- 后台预先生成一个1-100之间的随机数,用户键盘录入猜数字
- 如果猜对了,打印“恭喜您,答对了”
- 如果猜错了
- 猜大了:打印“sorry,您猜大了!”
- 猜小了:打印“sorry,您猜小了!”
- 直到数字猜到为止
需求分析
- 通过Random类中方法nextInt(),生成一个1-100之间的随机数
- 输入猜的数字
- 通过while循环,进行猜数字对错判断
- 猜对,跳出循环,游戏结束
- 猜错了,根据结果,给出提示,接着猜数字,游戏继续
- 如果猜大了,打印sorry,您猜大了!继续下一次循环
- 如果猜小了,打印sorry,您猜小了!继续下一次循环
实现代码
数组
定义
数组是指一组数据的集合,数组中的每个数据被称作元素。在数组中可以存放任意类型的元素,但同一个数组里存放的元素类型必须一致。
在Java中,可以使用以下格式来定义一个数组,如下:
内存
JVM对自己的内存划分为5个区域:
- 寄存器:内存和CUP之间
- 本地方法栈:JVM调用了系统中的功能
- 方法和数据共享:运行时期class文件进入的地方
- 方法栈:所有的方法运行的时候进入内存
- 堆:存储的是容器和对象
将上面的一句代码分成两句来写:
接下来,通过两张内存图来详细地说明数组在创建过程中内存的分配情况。
第一行代码 int[] x; 声明了一个变量x,该变量的类型为int[],即一个int类型的数组。变量x会占用一块内存单元,它没有被分配初始值。内存中的状态如下图所示:
第二行代码 x = new int[100]; 创建了一个数组,将数组的地址赋值给变量x;在程序运行期间可以使用变量x来引用数组,这时内存中的状态会发生变化,如下图所示:
在上图中描述了变量x引用数组的情况。该数组中有100个元素,初始值都为0。
索引
数组中的每个元素都有一个索引(也可称为角标),要想访问数组中的元素可以通过“x[0]、x[1]、……、x[98]、x[99]”的形式。
注意:数组中最小的索引是0,最大的索引是 数组的长度-1
length属性
在Java中,为了方便我们获得数组的长度,提供了一个length属性,在程序中可以通过“数组名.length”的方式来获得数组的长度,即元素的个数。
赋值
当数组被成功创建后,数组中元素会被自动赋予一个默认值,根据元素类型的不同,默认初始化的值也是不一样的,具体如下表所示:
数据类型 | 默认初始化值 |
byte、short、int、long | 0 |
float、double | 0.0 |
char | 一个空字符(空格),即’\u0000’ |
boolean | false |
引用数据类型 | null,表示变量不引用任何对象 |
如果在使用数组时,不想使用这些默认初始值,也可以显式地为这些元素赋值。
初始化
- 动态初始化:在定义数组时只指定数组的长度,由系统自动为元素赋初值
- 静态初始化:在定义数组的同时就为数组的每个元素赋值
数组的静态初始化有两种方式,具体格式如下:
遍历
在操作数组时,经常需要依次访问数组中的每个元素,这种操作称作数组的遍历。
常见问题
最值
在操作数组时,经常需要获取数组中元素的最值。
异常
数组越界异常(ArrayIndexOutOfBoundsException)
每个数组的索引都有一个范围,即0~length-1;在访问数组的元素时,索引不能超出这个范围,否则程序会报错。
空指针异常(NullPointerException)
在使用变量引用一个数组时,变量必须指向一个有效的数组对象,如果该变量的值为null,则意味着没有指向任何数组,此时通过该变量访问数组的元素会出现空指针异常。
二维数组
二维数组是多维数组的一种,多维数组可以简单地理解为在数组中嵌套数组。
定义
二维数组的定义有三种形式,分别为:
int[][] arr = new int[3][4];
上面的代码相当于定义了一个3*4的二维数组,即二维数组的长度为3,二维数组中的每个元素又是一个长度为4的数组。
外层数组在内存开辟连续的3个大的内存空间,每一个内存空间都对应的有地址值,每一个大内存空间里又开辟连续的4个小的内存空间。
接下来通过一个图来表示这种情况,如下图所示:
// 不推荐 int[][] arr = new int[3][];
第二种方式和第一种类似,只是数组中每个元素的长度不确定。
接下来通过一个图来表示这种情况,如下图所示:
int[][] arr = {{1,2},{3,4,5,6},{7,8,9}};
上面的二维数组中定义了三个元素,这三个元素都是数组,分别为{1,2}、{3,4,5,6}、{7,8,9}
接下来通过一个图来表示这种情况,如图所示:
访问
对二维数组中元素的访问也是通过角标的方式。
元素遍历与数组元素累加和
公司销售总和练习
要统计一个公司三个销售小组中每个小组的总销售额以及整个公司的销售额,如下所示:
- 第一小组销售额为{11, 12}万元
- 第二小组销售额为{21, 22, 23}万元
- 第三小组销售额为{31, 32, 33, 34}万元
随机点名器案例
随机点名器,即在全班同学中随机的打印出一名同学名字。
需求分析
- 存储全班同学名字
- 打印全班同学每一个人的名字
- 在班级总人数范围内,随机产生一个随机数,查找该随机数所对应的同学名
在存储同学姓名时,如果对每一个同学都定义一个变量进行姓名存储,则会出现过多孤立的变量,很难一次性将全部数据持有;此时,可以使用数组解决多个数据的存储问题。
实现代码
方法
在Java中,方法就是用来完成解决某件事情或实现某个功能的办法。
方法实现的过程中,会包含很多条语句用于完成某些有意义的功能,例如处理文本,控制输入或计算数值等,可以通过在程序代码中引用方法名称和所需的参数,实现在该程序中执行(调用)该方法;方法一般都有一个返回值,用来作为事情的处理结果。
定义
- 修饰符:方法的修饰符比较多,有对访问权限进行限定的,有静态修饰符static,还有最终修饰符final等
- 返回值类型:用于限定方法返回值的数据类型
- 方法名:符合命名规则即可。方便我们的调用
- 参数:
- 实际参数:就是实际参与运算的
- 形式参数;就是方法定义上的,用于接收实际参数的
- 参数类型:用于限定调用方法时传入参数的数据类型
- 参数名:是一个变量,用于接收调用方法时传入的数据
- return关键字:用于结束方法以及返回方法指定类型的值
- 返回值:被return语句返回的值,该值会返回给调用者
方法中的“参数类型 参数名1,参数类型 参数名2”被称作参数列表,用于描述方法在被调用时需要接收的参数;如果方法不需要接收任何参数,则参数列表为空,即()内不写任何内容;方法的返回值必须为方法声明的返回值类型,如果方法中没有返回值,返回值类型要声明为void,此时,方法中return语句可以省略。
注意事项
- 方法不能定义在另一个方法的里面
- 写错方法名字
- 写错了参数列表
- 方法返回值是void,方法中可以省略return 不写,若写了,则return 下面不能有代码
- 方法返回值类型,和return 后面数据类型必须匹配
- 方法重复定义问题
- 调用方法的时候,返回值是void, 不能写在输出语句中
调用
可以在main函数中调用方法,从而执行方法。
- 方法的形参:方法要什么参数就给什么类型的参数
- 方法的返回值:方法返回什么类型的值就用对应的数据类型的变量来接收
- 调用方法执行流程:
- 方法的定义是没有顺序的,写在main函数的上边或者下边都可以
- 方法的执行,是把实参传递给形参,从而来执行的
- 方法只有被调用才会执行
getArea()方法的整个调用过程,如下图所示:
从上图中可以看出,在程序运行期间,参数x和y相当于在内存中定义的两个变量;当调用getArea()方法时,传入的参数3和5分别赋值给变量x和y,并将x*y的结果通过return语句返回,整个方法的调用过程结束,变量x和y被释放。
重载
假设要在程序中实现一个对数字求和的方法,由于参与求和数字的个数和类型都不确定,因此要针对不同的情况去设计不同的方法。
从上述代码不难看出,程序需要针对每一种求和的情况都定义一个方法,如果每个方法的名称都不相同,在调用时就很难分清哪种情况该调用哪个方法;为了解决这个问题,Java允许在一个类中定义多个名称相同的方法,但是参数的类型或个数必须不同,这就是方法的重载。
方法的重载与返回值类型无关,它只有两个条件,一是方法名相同,二是参数个数或参数类型不相同。
注意事项
- 重载方法参数必须不同:
- 参数个数不同,如method(int x)与method(int x,int y)不同
- 参数类型不同,如method(int x)与method(double x)不同
- 参数顺序不同,如method(int x,double y)与method(double x,int y)不同
- 重载只与方法名与参数类型相关与返回值无关,如void method(int x)与int method(int y)不是方法重载,不能同时存在
- 重载与具体的变量标识符无关,如method(int x)与method(int y)不是方法重载,不能同时存在
参数传递
当要调用一个方法时,把指定的数值,传递给方法中的参数,这样方法中的参数就拥有了这个指定的值,可以使用该值在方法中运算;这种传递方式,称为参数传递。
- 定义方法时,参数列表中的变量,称为形式参数
- 调用方法时,传入给方法的数值,称为实际参数
- 当调用方法时,如果传入的数值为基本数据类型(包含String类型),形式参数的改变对实际参数不影响
- 当调用方法时,如果传入的数值为引用数据类型(String类型除外),形式参数的改变对实际参数有影响
随机点名器
随机点名器,即在全班同学中随机的打印出一名同学名字,它具备以下3个内容:
- 存储所有同学姓名
- 总览全班同学姓名
- 随机点名其中一人,打印到控制台
需求分析
- 存储全班同学名字
- 打印全班同学每一个人的名字
- 在班级总人数范围内,随机产生一个随机数,查找该随机数所对应的同学名字
随机点名器明确地分为了三个功能,如果将多个独立功能的代码写到一起,则代码相对冗长,可以针对不同的功能可以将其封装到一个方法中,将完整独立的功能分离出来;而在存储同学姓名时,如果对每一个同学都定义一个变量进行姓名存储,则会出现过多孤立的变量,很难一次性将全部数据持有,可以使用数组解决多个数据的存储问题。
实现代码
库存管理
需求分析
管理员能够进行的操作有3项(查看、修改、退出),菜单可以采用switch的方式来完成;每一项功能操作,采用方法进行封装,这样,可使程序的可读性增强。
实现代码
- 作者:青山🌊
- 链接:http://cxuan.me/article/java-se-grammar
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。