Java基础语法
学习内容
-
l 关键字
-
l 标识符
-
l 注释
-
l 常量、进制和进制转换
-
l 变量
-
l 数据类型和类型转换
-
l 运算符
-
l 语句
-
| 方法
-
| 数组
一、关键字
l 关键字概述
• 被Java语言赋予特定含义的单词
l 关键字特点
• 组成关键字的字母全部小写
l 关键字注意事项
• goto和const作为保留字存在,目前并不使用
• 类似Notepad++这样的高级记事本,针对关键字有特殊的颜色标记,非常直观
二、标识符
l 标识符概述
• 就是给类,接口,方法,变量等起名字时使用的字符序列
l 组成规则
• 英文大小写字母
• 数字字符
• $和_
l 注意事项
• 不能以数字开头
• 不能是Java中的关键字
• 区分大小写
标识符(常见命名规则)
l 包(其实就是文件夹,用于解决相同类名问题)
• 单级和多级分别举例
- 单级包:小写
- 举例:liuyi,com
- 多级包:小写,并用.隔开
- 举例:cn.itcast,com.baidu
l 类或者接口
• 一个单词和和多个单词分别举例
- 一个单词:首字母大写
- 举例:Student,Demo
- 多个单词:每个单词首字母大写
- 举例:HelloWorld,StudentName
l 方法和变量
• 一个单词和和多个单词分别举例
- 一个单词:首字母小写
- 举例:name,main
- 多个单词:从第二个单词开始,每个单词首字母大写
- 举例:studentAge,showAllNames()
l 常量
• 一个单词和和多个单词分别举例
- 一个单词:大写
- 举例:PI
- 多个单词:大写,并用_隔开
- 举例:STUDENT_MAX_AGE
三、注释
l 注释概述
• 用于解释说明程序的文字
l Java中注释分类格式
• 单行注释
• 格式://注释文字
• 多行注释
• 格式:/* 注释文字 */
• 文档注释
• 格式:/** 注释文字*/
| 注释的作用
A:解释说明程序,提高了代码的阅读性。
B:可以帮助我们调试程序。
-
l 注释是一个程序员必须要具有的良好编程习惯。
-
l 初学者编写程序可以养成习惯:先写注释再写代码。
-
l 将自己的思想通过注释先整理出来,在用代码去体现。
-
l 因为代码仅仅是思想的一种体现形式而已。
| 案例
l 把HelloWorld案例加入注释写出来
l 需求:写一个程序,在控制台输出HelloWorld
l 分析:
• 写一个java程序,首先定义类。
• 程序要想能够被jvm调用,必须定义main方法。
• 程序要想有输出结果,必须用输出语句。
l 实现:
• 定义类用的是class关键字,后面跟的是类名
• main方法基本格式
• 输出语句基本格式
四、常量
l 常量概述
• 在程序执行的过程中其值不可以发生改变
l Java中常量分类
• 字面值常量
• 自定义常量(面向对象部分讲)
l 字符串常量 用双引号括起来的内容
l 整数常量 所有整数
• 12,23
l 小数常量 所有小数
• 12.34,56.78
l 字符常量 用单引号括起来的内容
• ‘a’,’A’,’0’
l 布尔常量 较为特有,只有true和false
l 空常量 null(数组部分讲解)
l Java针对整数常量提供了4种表现形式
• 二进制
• 八进制
• 十进制
• 十六进制
l 进制概述
进制:就是进位制,是人们规定的一种进位方法。对于任何一种进制--X进制,就表示某一位置上的数运算时是逢X进一位。二进制就是逢二进一,八进制是逢八进一,十进制是逢十进一,十六进制是逢十六进一。
l 不同进制的数据组成
• 二进制
• 由0,1组成。以0b开头
• 八进制
• 由0,1,…7组成。以0开头
• 十进制
• 由0,1,…9组成。整数默认是十进制的
• 十六进制
• 由0,1,…9,a,b,c,d,e,f(大小写均可)。以0x开头
l 进制转换
• 其他进制到十进制
• 通过十进制推出结论
• 把0b100,0100,0x100转换成十进制
• 十进制到其他进制
• 通过十进制推出结论
• 把52分别表示成二进制,八进制,十六进制
l 十进制和二进制的快速转换
• 8421码
• 100转成二进制
• 101101转成十进制
l 二进制和八进制,十六进制如何转换
• 以十进制作为桥梁
• 二进制到八进制 3位组合
• 100110
• 二进制到十六进制4位组合
• 100110
l 有符号数据表示法
• 在计算机内,有符号数有3种表示法:原码、反码和补码。所有数据的运算都是采用补码进行的。
• 原码
• 就是二进制定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。
• 反码
• 正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。
• 补码
• 正数的补码与其原码相同;负数的补码是在其反码的末位加1。
五、变量
l 变量概述
• 在程序执行的过程中,在某个范围内其值可以发生改变的量
• 理解:如同数学中的未知数
l 变量定义格式
A:数据类型 变量名 = 初始化值;
B:数据类型 变量名;
变量名 = 初始化值;
六、数据类型
l 使用变量注意事项:
• 作用域
• 变量定义在哪一级大括号中,哪个大括号的范围就是这个变量的作用域。相同的作用域中不能定义两个同名变量。
• 初始化值
• 没有初始化值不能直接使用
• 在一行上建议只定义一个变量
• 可以定义多个,但是不建议
| 数据类型转换
-
+是一个运算符,我们应该能够看懂,做数据的加法。
-
boolean类型不能转换为其他的数据类型
l 默认转换
• byte,short,char—int—long—float—double
• byte,short,char相互之间补转换,他们参与运算首先转换为int类型
l 强制转换
-
从大到小
-
可能会有精度的损失,一般不建议这样使用。
-
格式:目标数据类型 变量名 = (目标数据类型) (被转换的数据);
一般建议,最好不要随意使用强制类型转换,容易造成数据精度的损失。
-
(1)容量大的数据类型转换为容量小的数据类型时,要加上强制转换符,但可能造成精度降低或溢出;使用时要格外注意。
-
(2)有多种类型的数据混合运算时,系统首先自动的将所有数据转换成容量最大的那一种数据类型,然后再进行计算。
l 思考题
/*
思考题1:请问下面这个有没有问题
double d = 12.345;
float f = d;
思考题2:看看下面两个定义有没有区别呢?
float f1 = (float)12.345;
float f2 = 12.345f;
f1其实是通过一个double类型转换过来的。
而f2本身就是一个float类型。
*/
class DataTypeDemo5 {
public static void main(String[] args) {
//把double赋值给float,加了强制类型转换
double d = 12.345;
float f = (float)d;
//看看下面两个定义有没有区别呢?
float f1 = (float)12.345;
float f2 = 12.345F;
}
}
/*
面试题:
byte b1=3,b2=4,b;
b=b1+b2;
b=3+4;
哪句是编译失败的呢?为什么呢?
b = b1 + b2;是有问题的。
因为变量相加,会首先看类型问题,最终把结果赋值的也会考虑类型问题。
常量相加,首先做加法,然后看结果是否在赋值的数据类型范围内,如果不是,才报错。
*/
class DataTypeDemo6 {
public static void main(String[] args) {
//定义了三个byte类型的变量,b1,b2,b3
//b1的值是3,b2的值是4,b没有值
byte b1 = 3,b2 = 4,b;
//b = b1 + b2; //这个是类型提升,所有有问题
b = 3 + 4; //常量,先把结果计算出来,然后看是否在byte的范围内,如果在就不报错。
}
}
/*
byte b = 130;有没有问题?如果我想让赋值正确,可以怎么做?结果是多少呢?
练习:byte b = (byte)300;
*/
class DataTypeDemo7 {
public static void main(String[] args) {
//因为byte的范围是:-128到127。
//而130不在此范围内,所以报错。
//byte b = 130;
//我们可以使用强制类型转换
byte b = (byte) 130;
//结果是多少呢?
System.out.println(b);
}
}
/*
分析过程:
我们要想知道结果是什么,就应该知道是如何进行计算的。
而我们又知道计算机中数据的运算都是补码进行的。
而要得到补码,首先要计算出数据的二进制。
A:获取130这个数据的二进制。
00000000 00000000 00000000 10000010
这是130的原码,也是反码,还是补码。
B:做截取操作,截成byte类型的了。
10000010
这个结果是补码。
C:已知补码求原码。
符号位 数值位
补码: 1 0000010
反码: 1 0000001
原码: 1 1111110
*/
l 请写出下列程序结果
• System.out.println(‘a’);
• System.out.println(‘a’+1);
• System.out.println(“hello”+’a’+1);
• System.out.println(‘a’+1+”hello”);
• System.out.println(“5+5=”+5+5);
• System.out.println(5+5+”=5+5”);
/*
看程序写结果
通过字符和一个整数相加,我们给出一张表:ASCII码表。
通过看完这张表以后,我们要记住三个值:
'a' 97
'A' 65
'0' 48
*/
class DataTypeDemo8 {
public static void main(String[] args) {
//直接输出一个字符
System.out.println('a'); //a
//输出一个字符和一个整数做加法
System.out.println('a'+1); //98
}
}
/*
看程序写结果
字符串数据和其他数据做+,结果是字符串类型。
这里的+不是加法运算,而是字符串连接符。
*/
class DataTypeDemo9 {
public static void main(String[] args) {
System.out.println("hello"+'a'+1); //helloa1
System.out.println('a'+1+"hello"); //98hello
System.out.println("5+5="+5+5); //5+5=55
System.out.println(5+5+"=5+5"); //10=5+5
}
}
七、运算符
l 算术运算符
l 赋值运算符
l 比较运算符
l 逻辑运算符
l 位运算符
l 三目运算符
算术运算符
l +,-,*,/都是比较简单的操作,简单演示即可
l +的几种作用:
• 加法
• 正数
• 字符串连接符
l 除法的时候要注意一个问题:
• 整数相除,只能得到整数
• 要想得到小数,可以*1.0
l /和%的区别
-
数据做除法操作的时候,/取得是商,%取得是余数
-
整数相除,只能得到整数
-
要想得到小数,可以*1.0
l ++和--的应用
• 单独使用效果相同
• 参与运算使用,在操作数的前后效果不同
-
放在操作数的前面:先自增或者自减,再参与操作
-
int a = 10;
-
int b = ++a;
-
放在操作数的后面:先参与操作,再自增或者自减
-
int a = 10;
-
int b = a++;
| 练习题
/*
++,--的练习题
第一题:
int a = 10;
int b = 10;
int c = 10;
a = b++;
c = --a;
b = ++a;
a = c--;
请分别计算出a,b,c的值
第二题:
int x = 4;
int y = (x++)+(++x)+(x*10);
请分别计算出x,y的值
*/
class OperatorTest {
public static void main(String[] args) {
int a = 10;
int b = 10;
int c = 10;
a = b++; //a=10,b=11,c=10
c = --a; //a=9,b=11,c=9
b = ++a; //a=10,b=10,c=9
a = c--; //a=9,b=10,c=8
System.out.println("a:"+a);
System.out.println("b:"+b);
System.out.println("c:"+c);
System.out.println("--------------");
int x = 4;
int y = (x++)+(++x)+(x*10);
//4+6+60
//x=5,6
System.out.println("x:"+x);
System.out.println("y:"+y);
}
}
赋值运算符
l 符号:
• =, +=, -=, *=, /=, %=
• =为基本的赋值运算符,其他的为扩展的赋值运算符
-
扩展的赋值运算符的特点:隐含了自动强制转换
l 如下操作写出结果
• int a,b; a = b = 10;
• System.out.println(a);System.out.println(b);
• int a = 10; a += 20;System.out.println(a);
l 面试题
/*
面试题:
short s=1;s = s+1;
short s=1;s+=1;
上面两个代码有没有问题,如果有,那里有问题。
为什么第二个木有问题呢?
扩展的赋值运算符其实隐含了一个强制类型转换。
s += 1;
不是等价于 s = s + 1;
而是等价于 s = (s的数据类型)(s + 1);
*/
class OperatorTest {
public static void main(String[] args) {
//short s = 1;
//s = s + 1;
//System.out.println(s);
short s = 1;
s += 1; //好像是 s = s + 1;
System.out.println(s);
}
}
关系运算符
逻辑运算符
位运算符
/*
^的特点:一个数据对另一个数据位异或两次,该数本身不变。
*/
class OperatorDemo2 {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a ^ b ^ b); //10
System.out.println(a ^ b ^ a); //20
}
}
/*
面试题:
请自己实现两个整数变量的交换
注意:以后讲课的过程中,我没有明确指定数据的类型,默认int类型。
*/
class OperatorTest {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a:"+a+",b:"+b);
//方式1:使用第三方变量(开发中用的)
/*
int c = a;
a = b;
b = c;
System.out.println("a:"+a+",b:"+b);
System.out.println("------------");
*/
//方式2:用位异或实现(面试用)
//左边:a,b,a
//右边:a ^ b
/*
a = a ^ b;
b = a ^ b; //a ^ b ^ b = a
a = a ^ b; //a ^ b ^ a = b
System.out.println("a:"+a+",b:"+b);
*/
//方式3:用变量相加的做法
/*
a = a + b; //a=30
b = a - b; //b=10
a = a - b; //a=20
System.out.println("a:"+a+",b:"+b);
*/
//方式4:一句话搞定
b = (a+b) - (a=b); //b=30-20=10,a=20
System.out.println("a:"+a+",b:"+b);
}
}
/*
<<:左移 左边最高位丢弃,右边补齐0
>>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1
>>>:无符号右移 无论最高位是0还是1,左边补齐0
面试题:
请用最有效率的方式写出计算2乘以8的结果?
2 * 8
2 << 3
*/
class OperatorDemo3 {
public static void main(String[] args) {
//<< 把<<左边的数据乘以2的移动次幂
System.out.println(3 << 2); //3*2^2 = 3*4 = 12;
//>> 把>>左边的数据除以2的移动次幂
System.out.println(24 >> 2); //24 / 2^2 = 24 / 4 = 6
System.out.println(24 >>> 2);
System.out.println(-24 >> 2);
System.out.println(-24 >>> 2);
}
}
/*
计算出3的二进制:11
00000000 00000000 00000000 00000011
(00)000000 00000000 00000000 0000001100
>>的移动:
计算出24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
1111111111 11111111 11111111 111010(00) 补码
补码:1111111111 11111111 11111111 111010
反码:1111111111 11111111 11111111 111001
原码:1000000000 00000000 00000000 000110
结果:-6
>>>的移动:
计算出24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
0011111111 11111111 11111111 111010(00)
结果:
*/
三目运算符
l 格式
• (关系表达式)?表达式1:表达式2;
• 如果条件为true,运算后的结果是表达式1;
• 如果条件为false,运算后的结果是表达式2;
l 示例:
• 获取两个数中大数。
• int x=3,y=4,z;
• z= (x>y)?x:y;//z变量存储的就是两个数的大数。
键盘录入数据
l 键盘录入数据概述
• 我们目前在写程序的时候,数据值都是固定的,但是实际开发中,数据值肯定是变化的,所以,我准备把数据改进为键盘录入,提高程序的灵活性。
l 如何实现键盘录入数据呢?(目前先记住使用)
• 导包(位置放到class定义的上面)
• import java.util.Scanner;
• 创建对象
• Scanner sc = newScanner(System.in);
• 接收数据
• intx = sc.nextInt();
键盘录入数据练习
l 键盘录入两个数据,并对这两个数据求和,输出其结果
l 键盘录入两个数据,获取这两个数据中的最大值
l 键盘录入三个数据,获取这三个数据中的最大值
l 键盘录入两个数据,比较这两个数据是否相等
八、流程控制语句
l 在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的。也就是说程序的流程对运行结果有直接的影响。所以,我们必须清楚每条语句的执行流程。而且,很多时候我们要通过控制语句的执行顺序来实现我们要完成的功能。
l 流程控制语句分类
• 顺序结构
• 选择结构
• 循环结构
顺序结构
l 顺序结构概述
• 是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
• 总的来说:写在前面的先执行,写在后面的后执行
顺序结构
l 顺序结构图
选择结构
l 选择结构
• 也被称为分支结构。
• 选择结构有特定的语法规则,代码要执行具体的逻辑运算进行判断,逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码。
• Java语言提供了两种选择结构语句
• if语句
• switch语句
选择结构(if语句)
l if语句有三种格式
l if语句第一种格式:
• if(关系表达式){
语句体
}
l 执行流程
• 首先判断关系表达式看其结果是true还是false
• 如果是true就执行语句体
• 如果是false就不执行语句体
选择结构(if语句)
l if图1
/*
if语句的注意事项:
A:比较表达式无论简单还是复杂,结果必须是boolean类型
B:if语句控制的语句体如果是一条语句,大括号可以省略;
如果是多条语句,就不能省略。建议永远不要省略。
C:一般来说:有左大括号就没有分号,有分号就没有左大括号
*/
class IfDemo2 {
public static void main(String[] args) {
int x = 10;
if(x == 10) {
System.out.println("x等于10");
}
if((x > 5) || (x == 10)) {
System.out.println("x大于或者等于10");
}
System.out.println("-------------------");
int a = 100;
/*
if(a == 100) {
System.out.println("a的值是100");
}
*/
if(a != 100) {
System.out.println("a的值是100");
System.out.println("over");
}
System.out.println("-------------------");
int b = 100;
if(b != 100); //这里其实是有语句体的,只不过是空语句体。
//代码块
{
System.out.println("b的值是100");
System.out.println("over");
}
}
}
选择结构(if语句)
l if语句第二种格式:
• if(关系表达式){
语句体1;
}else {
语句体2;
}
l 执行流程
• 首先判断关系表达式看其结果是true还是false
• 如果是true就执行语句体1
• 如果是false就执行语句体2
选择结构(if语句)
l if图2
/*
if语句格式2:
if(比较表达式) {
语句体1;
}else {
语句体2;
}
执行流程:
首先计算比较表达式的值,看其返回值是true还是false。
如果是true,就执行语句体1;
如果是false,就执行语句体2;
注意:else后面是没有比较表达式的,只有if后面有。
*/
class IfDemo3 {
public static void main(String[] args) {
//判断两个数据是否相等
int a = 10;
int b = 20;
if(a == b) {
System.out.println("a等于b");
}else {
System.out.println("a不等于b");
}
}
}
选择结构(if语句)
l 我们前面讲解过三元运算符,它根据比较判断后,给出的也是两个结果,所以,这种情况和if语句的第二种格式很相似,他们在某些情况下应该是可以相互转换的。
l if语句第二种格式和三元运算符
• 三元运算符的操作都可以使用if语句改进,反之不成立
• 什么时候不成立呢?
• 当if语句控制的语句体是一条输出语句的时候,就不成立。因为三元运算符是一个运算符,必须要求有一个结果返回。而输出语句却不能作为一个返回结果。
/*
由于if语句的第二种格式刚才也完成了三元运算符可以完成的效果。
所以,我们就认为他们可以完成一样的操作。
但是,他们就一点区别没有吗?肯定不是。
区别:
三元运算符实现的,都可以采用if语句实现。反之不成立。
什么时候if语句实现不能用三元改进呢?
当if语句控制的操作是一个输出语句的时候就不能。
为什么呢?因为三元运算符是一个运算符,运算符操作完毕就应该有一个结果,而不是一个输出。
*/
class IfDemo4 {
public static void main(String[] args) {
//获取两个数据的最大值
int a = 10;
int b = 20;
//用if语句实现
int max1;
if(a > b) {
max1 = a;
}else {
max1 = b;
}
System.out.println("max1:"+max1);
//用三元改进
int max2 = (a > b)? a: b;
System.out.println("max2:"+max2);
System.out.println("----------");
//判断一个数据是奇数还是偶数,并输出是奇数还是偶数
int x = 100;
if(x%2 == 0) {
System.out.println("100是一个偶数");
}else {
System.out.println("100是一个奇数");
}
//用三元改进
//这种改进是错误的。
//String s = (x%2 == 0)?System.out.println("100是一个偶数");:System.out.println("100是一个奇数");;
}
}
选择结构(if语句)
l if语句第三种格式:
• if(关系表达式1){
语句体1;
}else if (关系表达式2) {
语句体2;
}
…
else {
语句体n+1;
}
选择结构(if语句)
l if图3
/*
if语句的格式3:
if(比较表达式1) {
语句体1;
}else if(比较表达式2) {
语句体2;
}else if(比较表达式3) {
语句体3;
}
...
else {
语句体n+1;
}
执行流程:
首先计算比较表达式1看其返回值是true还是false,
如果是true,就执行语句体1,if语句结束。
如果是false,接着计算比较表达式2看其返回值是true还是false,
如果是true,就执行语句体2,if语句结束。
如果是false,接着计算比较表达式3看其返回值是true还是false,
...
如果都是false,就执行语句体n+1。
*/
import java.util.Scanner;
class IfDemo5 {
public static void main(String[] args) {
//需求:键盘录入一个成绩,判断并输出成绩的等级。
/*
90-100 优秀
80-90 好
70-80 良
60-70 及格
0-60 不及格
*/
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//录入数据
System.out.println("请输入你的考试成绩:");
int score = sc.nextInt();
/*
if(score>=90 && score<=100) {
System.out.println("优秀");
}else if(score>=80 && score<90) {
System.out.println("好");
}else if(score>=70 && score<80) {
System.out.println("良");
}else if(score>=60 && score<70) {
System.out.println("及格");
}else {
System.out.println("不及格");
}
*/
//这样写已经满足我的基本要求,但是可能别人在使用的时候,不会按照你要求的数据给出了。
//在做一个程序的基本测试的时候,一定要考虑这样的几个问题:
//正确数据,错误数据,边界数据。
//而我们刚才写的程序并没有处理错误数据,所以这个程序不是很好,要改进
/*
if(score>=90 && score<=100) {
System.out.println("优秀");
}else if(score>=80 && score<90) {
System.out.println("好");
}else if(score>=70 && score<80) {
System.out.println("良");
}else if(score>=60 && score<70) {
System.out.println("及格");
}else if(score>=0 && score<60){
System.out.println("不及格");
}else {
System.out.println("你输入的成绩有误");
}
*/
//另一种判断改进
if(score<0 || score>100) {
System.out.println("你输入的成绩有误");
}else if(score>=90 && score<=100) {
System.out.println("优秀");
}else if(score>=80 && score<90) {
System.out.println("好");
}else if(score>=70 && score<80) {
System.out.println("良");
}else if(score>=60 && score<70) {
System.out.println("及格");
}else {
System.out.println("不及格");
}
}
}
选择结构(if语句练习)
/*
三种if语句分别适合做什么事情呢?
格式1:适合做单个判断
格式2:适合做两个判断
格式3:适合做多个判断
需求:
键盘录入x的值,计算出y的并输出。
x>=3 y = 2x + 1;
-1<=x<3 y = 2x;
x<=-1 y = 2x – 1;
分析:
A:由于数据要键盘录入,所以必须使用Scanner。
B:由于是三种判断,所以我们选择if语句格式3。
*/
import java.util.Scanner;
class IfTest2 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入x的值:");
int x = sc.nextInt();
//定义一个y
int y;
//用if语句格式3进行判断
if(x >= 3) {
y = 2*x + 1;
}else if(x>=-1 && x<3) {
y = 2*x;
}else {
y = 2*x - 1;
}
System.out.println("y:"+y);
}
}
/*
if语句格式2的练习:
A:获取两个数据中较大的值
B:判断一个数据是奇数还是偶数,并输出是奇数还是偶数
*/
import java.util.Scanner;
class IfTest {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//获取两个数据中较大的值
System.out.println("请输入第一个数据:");
int a = sc.nextInt();
System.out.println("请输入第二个数据:");
int b = sc.nextInt();
//定义一个变量接收最大值
int max;
if(a > b) {
max = a;
}else {
max = b;
}
System.out.println("max:"+max);
System.out.println("----------------");
//判断一个数据是奇数还是偶数
System.out.println("请输入你要判断的数据:");
int x = sc.nextInt();
if(x%2 == 0) {
System.out.println(x+"这个数据是偶数");
}else {
System.out.println(x+"这个数据是奇数");
}
}
}
/*
键盘录入月份的值,输出对应的季节。
春 3,4,5
夏 6,7,8
秋 9,10,11
冬 12,1,2
分析:
A:键盘录入月份的值,所以我们要使用Scanner。
B:我们应该判断这个月份在那个季节,而这个判断情况较多,所以,用if语句格式3。
if语句的使用场景:
A:针对表达式是一个boolean类型的判断
B:针对一个范围的判断
*/
import java.util.Scanner;
class IfTest3 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//录入数据
System.out.println("请你输入一个月份:");
int month = sc.nextInt();
//第三种格式实现即可
if(month<1 || month>12) {
System.out.println("你输入的月份有误");
}else if(month == 1) {
System.out.println("冬季");
}else if(month == 2) {
System.out.println("冬季");
}else if(month == 3) {
System.out.println("春季");
}else if(month == 4) {
System.out.println("春季");
}else if(month == 5) {
System.out.println("春季");
}else if(month == 6) {
System.out.println("夏季");
}else if(month == 7) {
System.out.println("夏季");
}else if(month == 8) {
System.out.println("夏季");
}else if(month == 9) {
System.out.println("秋季");
}else if(month == 10) {
System.out.println("秋季");
}else if(month == 11) {
System.out.println("秋季");
}else {
System.out.println("冬季");
}
System.out.println("--------------");
//这个程序确实是符合了我们的需求,但是就是看起来比较麻烦
//那么,我们能不能改进一下呢?
//month == 3
//month == 4
//month == 5
//我们发现,上面三个都是春季。
//而他们本身每一个都是一个boolean表达式
//所以,我们就可以考虑使用逻辑运算符给他们连接起来改进
if(month<1 || month>12) {
System.out.println("你输入的月份有误");
}else if(month==3 || month==4 || month==5) {
System.out.println("春季");
}else if(month==6 || month==7 || month==8) {
System.out.println("夏季");
}else if(month==9 || month==10 || month==11) {
System.out.println("秋季");
}else {
System.out.println("冬季");
}
System.out.println("--------------");
//这个时候,程序代码以及可以了。
//但是呢,假如我要求你输入一个月份,判断是上半年还是下半年。
//这个时候,我们的判断条件连接就是6个boolean表达式
//我们可能还有更多的连接
//这个时候,其实我们还有另外的一种改进方案:
//month == 3
//month == 4
//month == 5
//month>=3 && month<=5
//用范围也是可以改进的。
if(month<1 || month>12) {
System.out.println("你输入的月份有误");
}else if(month>=3 && month<=5) {
System.out.println("春季");
}else if(month>=6 && month<=8) {
System.out.println("夏季");
}else if(month>=9 && month<=11) {
System.out.println("秋季");
}else {
System.out.println("冬季");
}
System.out.println("--------------");
}
}
/*
获取三个数据中的最大值
由此案例主要是为了讲解if语句是可以嵌套使用的。而且是可以任意的嵌套。
*/
class IfTest4 {
public static void main(String[] args) {
int a = 10;
int b = 30;
int c = 20;
//三元实现
//int temp = (a>b)? a: b;
//int max = (temp>c)? temp: c;
//System.out.println("max:"+max);
//System.out.println("--------");
//用if语句实现
int max;
if(a > b) {
if(a > c) {
max = a;
}else {
max = c;
}
}else {
if(b > c) {
max = b;
}else {
max = c;
}
}
System.out.println("max:"+max);
}
}
选择结构(switch语句)
l switch语句格式:
• switch(表达式){
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
…
default:
语句体n+1;
break;
}
l 格式解释
• switch表示这是switch语句
• 表达式的取值:byte,short,int,char
• JDK5以后可以是枚举
• JDK7以后可以是String
• case后面跟的是要和表达式进行比较的值
• 语句体部分可以是一条或多条语句
• break表示中断,结束的意思,可以结束switch语句
• default语句表示所有情况都不匹配的时候,就执行该处的内容,和if语句的else相似。
| 面试题
-
switch语句的表达式可以是byte吗?可以是long吗?可以是String吗?
-
可以,不可以,JDK7以后可以
l 执行流程
• 首先计算出表达式的值
• 其次,和case依次比较,一旦有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结束。
• 最后,如果所有的case都和表达式的值不匹配,就会执行default语句体部分,然后程序结束掉。
选择结构(switch语句)
l switch语句图
l 注意事项
• case后面只能是常量,不能是变量,而且,多个case后面的值不能出现相同的
• default可以省略吗?
• 可以省略。一般不建议。除非判断的值是固定的。(单选题)
• break可以省略吗?
• 可以省略,一般不建议 会出现一个现象:case穿透。否则结果可能不是你想要的
• default的位置一定要在最后吗?
• 可以出现在switch语句任意位置。
• switch语句的结束条件
• 遇到break
• 执行到程序的末尾
选择结构(switch语句练习)
l 模拟做单项选择题,根据你的选择,给出对应的答案。(表达式是字符的情况)
l 键盘录入字符串,根据给定的字符串,来输出你选择的字符串是什么?(表达式是字符串的情况)
l 用switch语句实现键盘录入月份,输出对应的季节
l 看程序写结果
/*
看程序写结果
*/
class SwitchTest {
public static void main(String[] args) {
int x = 2;
int y = 3;
switch(x){
default:
y++;
break;
case 3:
y++;
case 4:
y++;
}
System.out.println("y="+y);
System.out.println("---------------");
int a = 2;
int b = 3;
switch(a){
default:
b++;
case 3:
b++;
case 4:
b++;
}
System.out.println("b="+b);
}
}
选择结构(各自使用场景)
l 在做判断的时候,我们有两种选择,if语句和switch语句,那么,我们到底该如何选择使用那种语句呢?
l if语句使用场景:
• 针对结果是boolean类型的判断
• 针对一个范围的判断
• 针对几个常量值的判断
l switch语句使用场景:
• 针对几个常量值的判断
循环结构
l 循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去,形成死循环。
循环结构
l 循环语句的组成
• 初始化语句:
• 一条或者多条语句,这些语句完成一些初始化操作。
• 判断条件语句:
• 这是一个boolean 表达式,这个表达式能决定是否执行循环体。
• 循环体语句:
• 这个部分是循环体语句,也就是我们要多次做的事情。
• 控制条件语句:
• 这个部分在一次循环体结束后,下一次循环判断条件执行前执行。通过用于控制循环条件中的变量,使得循环在合适的时候结束。
循环结构(for循环语句)
l for循环语句格式:
• for(初始化语句;判断条件语句;控制条件语句){
循环体语句;
}
• 执行流程
• A:执行初始化语句
• B:执行判断条件语句,看其结果是true还是false
• 如果是false,循环结束。
• 如果是true,继续执行。
• C:执行循环体语句
• D:执行控制条件语句
• E:回到B继续
循环结构(for循环语句)
l for循环语句图
循环结构(for循环语句)
l 注意事项
• 判断条件语句的结果是一个boolean类型
• 循环体语句如果是一条语句,大括号可以省略;如果是多条语句,大括号不能省略。建议永远不要省略。
• 一般来说:有左大括号就没有分号,有分号就没有左大括号
循环结构(for循环练习)
l 请在控制台输出数据1-10
l 请在控制台输出数据10-1
l 求出1-10之间数据之和
l 求出1-100之间偶数和
l 求出1-100之间奇数和
l 求5的阶乘
l 在控制台输出所有的”水仙花数”
l 统计”水仙花数”共有多少个
/*
天将降大任于斯人也,必先盗其QQ,封其微博,收其wifi,夺其手机。让其静心学习Java欧耶。
需求:在控制台输出所有的”水仙花数”
分析:
我们都不知道什么叫"水仙花数",你让我怎么做呢?
所谓的水仙花数是指一个三位数,其各位数字的立方和等于该数本身。
举例:153就是一个水仙花数。
153 = 1*1*1 + 5*5*5 + 3*3*3 = 1 + 125 + 27 = 153
A:三位数其实是告诉了我们范围。
B:通过for循环我们就可以实现获取每一个三位数
但是麻烦是如何获取这个三位数的个,十,百位上的数据
我们如何获取一个数据的个,十,百呢?
假设有个一个数据:153
ge: 153%10 = 3
shi: 153/10%10 = 5
bai:153/10/10%10 = 1
qian:x/10/10/10%10
wan: x/10/10/10/10%10
...
C:让ge*ge*ge+shi*shi*shi+bai*bai*bai和该数据比较
如果相同,就把该数据在控制台输出。
*/
class ForDemo6 {
public static void main(String[] args) {
//三位数其实是告诉了我们范围。
for(int x=100; x<1000; x++) {
int ge = x%10;
int shi = x/10%10;
int bai = x/10/10%10;
//让ge*ge*ge+shi*shi*shi+bai*bai*bai和该数据比较
if(x == (ge*ge*ge+shi*shi*shi+bai*bai*bai)) {
//如果相同,就把该数据在控制台输出。
System.out.println(x);
}
}
}
}
/*
需求:统计”水仙花数”共有多少个
分析:
A:首先必须知道什么是水仙花数
所谓的水仙花数是指一个三位数,其各位数字的立方和等于该数本身。
举例:153就是一个水仙花数。
153 = 1*1*1 + 5*5*5 + 3*3*3 = 1 + 125 + 27 = 153
B:定义统计变量,初始化值是0
C:三位数告诉了我们范围,用for循环就可以搞定
D:获取每一个三位数的个,十,百的数据
E:按照要求进行判断
F:如果满足要求就计数。
*/
class ForDemo8 {
public static void main(String[] args) {
//定义统计变量,初始化值是0
int count = 0;
//三位数告诉了我们范围,用for循环就可以搞定
for(int x=100; x<1000; x++) {
//获取每一个三位数的个,十,百的数据
int ge = x%10;
int shi = x/10%10;
int bai = x/10/10%10;
//按照要求进行判断
if(x == (ge*ge*ge+shi*shi*shi+bai*bai*bai)) {
//如果满足要求就计数。
count++;
}
}
System.out.println("水仙花数共有"+count+"个");
}
}
循环结构(for循环练习)
l 请在控制台输出满足如下条件的五位数
• 个位等于万位
• 十位等于千位
• 个位+十位+千位+万位=百位
/*
练习:
请在控制台输出满足如下条件的五位数
个位等于万位
十位等于千位
个位+十位+千位+万位=百位
分析:
A:五位数就告诉了我们范围。
B:分解每一个五位数的个,十,百,千,万位上的数据
C:按照要求进行判断即可
*/
class ForDemo7 {
public static void main(String[] args) {
//五位数就告诉了我们范围。
for(int x=10000; x<100000; x++) {
//分解每一个五位数的个,十,百,千,万位上的数据
int ge = x%10;
int shi = x/10%10;
int bai = x/10/10%10;
int qian = x/10/10/10%10;
int wan = x/10/10/10/10%10;
//按照要求进行判断即可
if((ge==wan) && (shi==qian) && (ge+shi+qian+wan==bai)) {
System.out.println(x);
}
}
}
}
l 请统计1-1000之间同时满足如下条件的数据有多少个:
• 对3整除余2
• 对5整除余3
• 对7整除余2
循环结构(while循环语句)
l while循环语句格式:
• 基本格式
while(判断条件语句){
循环体语句;
}
• 扩展格式
初始化语句;
while(判断条件语句){
循环体语句;
控制条件语句;
}
循环结构(while循环语句)
l while循环语句格式图
循环结构(for循环和while循环的区别)
l for循环语句和while循环语句可以等价转换,但还是有些小区别的
• 使用区别:控制条件语句所控制的那个变量,在for循环结束后,就不能再被访问到了,而while循环结束还可以继续使用,如果你想继续使用,就用while,否则推荐使用for。原因是for循环结束,该变量就从内存中消失,能够提高内存的使用效率。
• 场景区别:
• for循环适合针对一个范围判断进行操作
• while循环适合判断次数不明确操作
循环结构(while循环语句练习)
l 我国最高山峰是珠穆朗玛峰:8848m,我现在有一张足够大的纸张,厚度为:0.01m。请问,我折叠多少次,就可以保证厚度不低于珠穆朗玛峰的高度?
/*
我国最高山峰是珠穆朗玛峰:8848m,我现在有一张足够大的纸张,厚度为:0.01m。
请问,我折叠多少次,就可以保证厚度不低于珠穆朗玛峰的高度?
分析:
A:定义一个统计变量,默认值是0
B:最高山峰是珠穆朗玛峰:8848m这是最终的厚度
我现在有一张足够大的纸张,厚度为:0.01m这是初始厚度
C:我折叠多少次,就可以保证厚度不低于珠穆朗玛峰的高度?
折叠一次有什么变化呢?就是厚度是以前的2倍。
D:只要每次变化的厚度没有超过珠穆朗玛峰的高度,就折叠,统计变量++
E:输出统计变量。
*/
class WhileDemo5 {
public static void main(String[] args) {
//定义一个统计变量,默认值是0
int count = 0;
//最高山峰是珠穆朗玛峰:8848m这是最终的厚度
//我现在有一张足够大的纸张,厚度为:0.01m这是初始厚度
//为了简单,我把0.01变成1,同理8848就变成了884800
int end = 884800;
int start = 1;
while(start<end) {
//只要每次变化的厚度没有超过珠穆朗玛峰的高度,就折叠,统计变量++
count++;
//折叠一次有什么变化呢?就是厚度是以前的2倍。
start *= 2;
System.out.println("第"+count+"次厚度是"+start);
}
//输出统计变量。
System.out.println("要叠"+count+"次");
}
}
循环结构(do…while循环语句)
l do…while循环语句格式:
• 基本格式
do {
循环体语句;
}while((判断条件语句);
• 扩展格式
初始化语句;
do {
循环体语句;
控制条件语句;
} while((判断条件语句);
循环结构(do…while循环语句)
l do…while循环语句图:
循环结构(区别及注意事项)
l 三种循环语句其实都可以完成一样的功能,也就是说可以等价转换,但还是有小区别的:
• do…while循环至少会执行一次循环体。
• for循环和while循环只有在条件成立的时候才会去执行循环体
l 注意事项:
• 写程序优先考虑for循环,再考虑while循环,最后考虑do…while循环。
• 如下代码是死循环
• while(true){}
• for(;;){}
/*
注意死循环:
A:一定要注意控制条件语句控制的那个变量的问题,不要弄丢了,否则就容易死循环。
B:两种最简单的死循环格式
while(true){...}
for(;;){...}
*/
class DoWhileDemo3 {
public static void main(String[] args) {
int x = 0;
while(x < 10) {
System.out.println(x);
x++;
}
System.out.println("--------------");
/*
while(true) {
System.out.println("今天我很高兴,学习了死循环");
}
*/
for(;;){
System.out.println("今天我很高兴,学习了死循环");
}
//System.out.println("--------------");
}
}
循环结构(循环嵌套使用)
l 需求:请输出一个4行5列的星星(*)图案。
l 需求:请输出如下图形
*
**
***
****
*****
l 需求:在控制台输出九九乘法表。
跳转控制语句
l 前面我们已经说过了,Java中的goto是保留字,目前不能使用。虽然没有goto语句可以增强程序的安全性,但是也带来很多不便,比如说,我想在某个循环知道到某一步的时候就结束,现在就做不了这件事情。为了弥补这个缺陷,Java就提供了break,continue和return来实现控制语句的跳转和中断。
l break 中断
l continue 继续
l return 返回
跳转控制语句(break)
l break的使用场景:
• 在选择结构switch语句中
• 在循环语句中
• 离开使用场景的存在是没有意义的
l break的作用:
• 跳出单层循环
• 跳出多层循环
• 带标签的跳出
• 格式:标签名: 循环语句
• 标签名要符合Java的命名规则
跳转控制语句(continue)
l continue的使用场景:
• 在循环语句中
• 离开使用场景的存在是没有意义的
l continue的作用:
• 单层循环对比break,然后总结两个的区别
• break 退出当前循环
• continue 退出本次循环
• 也可以带标签的使用(不演示了)
• 做一个练习
/*
continue:继续
使用场景:
循环中。离开此场景无意义。
测试,找到和break的区别:
break:跳出单层循环
continue:跳出一次循环,进入下一次的执行
练习题:
for(int x=1; x<=10; x++) {
if(x%3==0) {
//在此处填写代码
}
System.out.println(“Java基础班”);
}
我想在控制台输出2次:“Java基础班“
break;
我想在控制台输出7次:“Java基础班“
continue;
我想在控制台输出13次:“Java基础班“
System.out.println(“Java基础班”);
*/
class ContinueDemo {
public static void main(String[] args) {
for(int x=0; x<10; x++) {
if(x == 3) {
//break;
continue;
}
System.out.println(x);
}
}
}
跳转控制语句(return)
l return关键字不是为了跳转出循环体,更常用的功能是结束一个方法,也就是退出一个方法。跳转到上层调用的方法。这个在方法的使用那里会在详细的讲解。
l 演示案例:
• 结束循环其实是结束了main方法
/*
return:返回
其实它的作用不是结束循环的,而是结束方法的。
*/
class ReturnDemo {
public static void main(String[] args) {
for(int x=0; x<10; x++) {
if(x == 2) {
System.out.println("退出");
//break;
//continue;
return;
}
System.out.println(x);
}
System.out.println("over");
}
}
循环语句结合break的练习
l 小芳的妈妈每天给她2.5元钱,她都会存起来,但是,每当这一天是存钱的第5天或者5的倍数的话,她都会花去6元钱,请问,经过多少天,小芳才可以存到100元钱。
/*
需求:小芳的妈妈每天给她2.5元钱,她都会存起来,但是,
每当这一天是存钱的第5天或者5的倍数的话,她都会花去6元钱,
请问,经过多少天,小芳才可以存到100元钱。
分析:
A:小芳的妈妈每天给她2.5元钱
double dayMoney = 2.5;
B:她都会存起来
double daySum = 0;
C:从第一天开始存储
int dayCount = 1;
D:经过多少天,小芳才可以存到100元钱。
double result = 100;
E:这一天是存钱的第5天或者5的倍数的话,她都会花去6元钱,
说明要判断dayCount的值,如果对5整除就减去6元钱。
daySum -= 6;
由此还隐含了一个问题,就是如果不是5的倍数天的话,钱要累加
daySum += dayMoney;
F:因为不知道是多少天,所以我用死循环,一旦超过100元我就退出循环。
*/
class WhileDemo {
public static void main(String[] args) {
//每天要存储的钱是2.5元
double dayMoney = 2.5;
//存钱的初始化值是0
double daySum = 0;
//从第一天开始存储
int dayCount = 1;
//最终存储不小于100就不存储了
int result = 100;
//因为不知道是多少天,所以我用死循环,
while(true) {
//累加钱
daySum += dayMoney;
//一旦超过100元我就退出循环。
if(daySum >= result) {
System.out.println("共花了"+dayCount+"天存储了100元");
break;
}
if(dayCount%5 == 0) {
//花去6元钱
daySum -= 6;
System.out.println("第"+dayCount+"天花了6元钱");
}
//天数变化
dayCount++;
}
}
}
l 方法
l 数组
九、方法
l 方法概述
• 假设有一个游戏程序,程序在运行过程中,要不断地发射炮弹(植物大战僵尸)。发射炮弹的动作需要编写100行的代码,在每次实现发射炮弹的地方都需要重复地编写这100行代码,这样程序会变得很臃肿,可读性也非常差。为了解决代码重复编写的问题,可以将发射炮弹的代码提取出来放在一个{}中,并为这段代码起个名字,这样在每次发射炮弹的地方通过这个名字来调用发射炮弹的代码就可以了。上述过程中,所提取出来的代码可以被看作是程序中定义的一个方法,程序在需要发射炮弹时调用该方法即可。
方法定义及格式
l 简单的说:方法就是完成特定功能的代码块
• 在很多语言里面都有函数的定义
• 函数在Java中被称为方法
l 格式:
• 修饰符返回值类型方法名(参数类型参数名1,参数类型参数名2…){
函数体;
return 返回值;
}
方法格式的解释说明
l 方法格式解释
• 修饰符比较多,后面会详细介绍。目前public static
• 返回值类型用于限定返回值的数据类型
• 方法名一个名称,为了方便我们调用方法
• 参数类型限定调用方法时传入参数的数据类型
• 参数名是一个变量,接收调用方法时传入的参数
-
参数分类:
-
实参:实际参与运算的数据
-
形参:方法上定义的,用于接收实际参数的变量
• 方法体完成功能的代码
• return 结束方法以及返回方法指定类型的值
• 返回值程序被return带回的结果,返回给调用者
方法案例
l 如何写一个方法呢?两个明确
• 返回值类型明确功能结果的数据类型
• 参数列表明确有几个参数,以及参数的类型
l 按照格式和两个明确来完成如下功能
• 求两个数据之和的案例
有明确返回值的方法调用
l 有明确返回值的方法调用:
• 单独调用,没有意义
• 输出调用,有意义,但是不够好,因为我不一定非要把结果输出
• 赋值调用,推荐方式
l 讲解完毕该案例后,画图说明方法的调用过程
方法注意事项
l 方法不调用不执行
l 方法与方法是平级关系,不能嵌套定义
l 方法定义的时候参数之间用逗号隔开
l 方法调用的时候不用在传递数据类型
l 如果方法有明确的返回值,一定要有return带回一个值
有明确返回值的方法练习
l 键盘录入两个数据,返回两个数中的较大值
l 键盘录入两个数据,比较两个数是否相等
l 键盘录入三个数据,返回三个数中的最大值
/*
键盘录入三个数据,返回三个数中的最大值
*/
import java.util.Scanner;
class FunctionTest3 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个数据:");
int a = sc.nextInt();
System.out.println("请输入第二个数据:");
int b = sc.nextInt();
System.out.println("请输入第三个数据:");
int c = sc.nextInt();
int max = getMax(a,b,c);
System.out.println("三个数据中的最大值是:"+max);
}
/*
需求;返回三个数中的最大值
两个明确:
返回值类型:int
参数列表:int a,int b,int c
*/
public static int getMax(int a,int b,int c) {
//if嵌套
/*
if(a > b) {
if(a > c) {
return a;
}else {
return c;
}
}else {
if(b > c) {
return b;
}else {
return c;
}
}
*/
//用三元改
/*
if(a > b) {
return (a>c? a: c);
}else {
return (b>c? b: c);
}
*/
//继续改进
//return (a>b)? (a>c? a: c): (b>c? b: c);
//不建议,写代码一定要注意阅读性强
int temp = ((a>b)? a: b);
int max = ((temp>c)? temp: c);
return max;
}
}
没有明确返回值的方法调用
l 没有明确返回值的函数调用:
• 其实就是void类型方法的调用
• 只能单独调用
返回值为void类型的方法练习
l 键盘录入行数和列数,输出对应的星形
l 键盘录入一个数据n(1<=n<=9),输出对应的nn乘法表
/*
键盘录入一个数据n(1<=n<=9),输出对应的nn乘法表
*/
import java.util.Scanner;
class FunctionTest5 {
public static void main(String[] args) {
//创建对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入n的值:(1~9)");
int n = sc.nextInt();
//调用
printNN(n);
}
/*
需求:输出对应的nn乘法表
两个明确:
返回值类型:void
参数列表:int n
*/
public static void printNN(int n) {
for(int x=1; x<=n; x++) {
for(int y=1; y<=x; y++) {
System.out.print(y+"*"+x+"="+y*x+"\t");
}
System.out.println();
}
}
}
方法重载
l 方法重载概述
• 在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
l 方法重载特点
• 与返回值类型无关,只看方法名和参数列表
• 在调用时,虚拟机通过参数列表的不同来区分同名方法
方法重载案例
l 比较两个数据是否相等。参数类型分别为两个byte类型,两个short类型,两个int类型,两个long类型,并在main方法中进行测试
/*
比较两个数据是否相等。参数类型分别为
两个byte类型,两个short类型,两个int类型,两个long类型,
并在main方法中进行测试
*/
class FunctionTest6 {
public static void main(String[] args) {
//测试
byte b1 = 3;
byte b2 = 4;
System.out.println("byte:"+compare(b1,b2));
//测试
short s1 = 5;
short s2 = 5;
System.out.println("short:"+compare(s1,s2));
//后面的两个自己测试
}
//byte类型
public static boolean compare(byte a,byte b) {
System.out.println("byte");
return a == b;
}
//short类型
public static boolean compare(short a,short b) {
System.out.println("short");
return a == b;
}
//int类型
public static boolean compare(int a,int b) {
System.out.println("int");
return a == b;
}
//long类型
public static boolean compare(long a,long b) {
System.out.println("long");
return a == b;
}
}
l 方法递归在IO之前详细讲解
十、数组
l 数组概述
• 需求:现在需要统计某公司员工的工资情况,例如计算平均工资、找到最高工资等。假设该公司有80名员工,用前面所学的知识,程序首先需要声明80个变量来分别记住每位员工的工资,然后在进行操作,这样做会显得很麻烦。为了解决这种问题,Java就提供了数组供我们使用。
• 那么数组到底是什么呢?有什么特点呢?通过上面的分析:我们可以得到如下两句话:
• 数组是存储多个变量(元素)的东西(容器)
• 这多个变量的数据类型要一致
数组概念
l 数组概念
• 数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器。
• 数组既可以存储基本数据类型,也可以存储引用数据类型。
l 数组的定义格式
• 格式1:数据类型[] 数组名;(推荐)
• 格式2:数据类型 数组名[];
• 注意:这两种定义做完了,数组中是没有元素值的。如何对数组的元素进如何对数组的元素进行初始化呢?
数组的初始化
l 数组初始化概述:
• Java中的数组必须先初始化,然后才能使用。
• 所谓初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋值。
l 数组的初始化方式
• 动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
• 静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。
数组的初始化
l 动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
• 格式:数据类型[] 数组名= new 数据类型[数组长度];
• 数组长度其实就是数组中元素的个数。
• 举例:
• int[] arr = new int[3];
• 解释:定义了一个int类型的数组,这个数组中可以存放3个int类型的值。
l 静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。
• 格式:
• 数据类型[] 数组名=new 数据类型[]{元素1,元素2,…};
• 举例:
• int[] arr = new int[]{1,2,3};
• 解释:定义了一个int类型的数组,这个数组中可以存放3个int类型的值,并且值分别是1,2,3。
• 其实这种写法还有一个简化的写法
• int[] arr = {1,2,3};
Java中的内存分配
l Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
• 栈存储局部变量
• 堆存储new出来的东西
• 方法区(面向对象部分讲)
• 本地方法区(和系统相关)
• 寄存器(给CPU使用)
Java中数组的内存图解
l 图解1:
• 定义一个数组,输出数组名及元素。然后给数组中的元素赋值,再次输出数组名及元素。
l 图解2:
• 定义两个数组,分别输出数组名及元素。然后分别给数组中的元素赋值,分别再次输出数组名及元素。
l 图解3:
• 定义两个数组,先定义一个数组,赋值,输出。然后定义第二个数组的时候把第一个数组的地址赋值给第二个数组。然后给第二个数组赋值,再次输出两个数组的名及元素。(两个栈变量指向同一个堆内存)
数组操作常见的两个小问题
l 数组索引越界
• ArrayIndexOutOfBoundsException
• 访问到了数组中的不存在的索引时发生。
l 空指针异常
• NullPointerException
• 数组引用没有指向实体,却在操作实体中的元素时。
数组练习(常见操作)
l 数组遍历(依次输出数组中的每一个元素)
//方式1:
public static void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
System.out.println(arr[x]);
}
}
//方式2:
public static void printArray(int[] arr) {
System.out.print("[");
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]+"]");
}else {
System.out.println(arr[x]+", ");
}
}
}
l 数组获取最值(获取数组中的最大值最小值)
//最大值:
public static int getMax(int[] arr) {
int max = arr[0];
for(int x=1; x<arr.length; x++) {
if(arr[x] > max) {
max = arr[x];
}
}
return max;
}
//最小值:
public static int getMin(int[] arr) {
int min = arr[0];
for(int x=1; x<arr.length; x++) {
if(arr[x] < min) {
min = arr[x];
}
}
return min;
}
l 数组元素逆序(就是把元素对调)
//方式1:
public static void reverse(int[] arr) {
for(int x=0; x<arr.length/2; x++) {
int temp = arr[x];
arr[x] = arr[arr.length-1-x];
arr[arr.length-1-x] = temp;
}
}
//方式2:
public static void reverse(int[] arr) {
for(int start=0,end=arr.length-1; start<=end; start++,end--) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
}
l 数组查表法(根据键盘录入索引,查找对应星期)
public static String getString(String[] strArray,int index) {
return strArray[index];
}
l 数组元素查找(查找指定元素第一次在数组中出现的索引)
/*
需求:查找指定数据在数组中第一次出现的索引
两个明确:
返回值类型:int
参数列表:int[] arr,int value
*/
public static int getIndex(int[] arr,int value) {
//遍历数组,依次获取数组中的每一个元素,和已知的数据进行比较
for(int x=0; x<arr.length; x++) {
if(arr[x] == value) {
//如果相等,就返回当前的索引值。
return x;
}
}
//目前的代码有一个小问题
//就是假如我要查找的数据在数组中不存在,那就找不到,找不到,你就对应的返回吗?
//所以报错。
//只要是判断,就可能是false,所以大家要细心。
//如果找不到数据,我们一般返回一个负数即可,而且是返回-1
return -1;
}
//方式2:
public static int getIndex(int[] arr,int value) {
int index = -1;
for(int x=0; x<arr.length; x++) {
if(arr[x] == value) {
index = x;
break;
}
}
return index;
}
l 数组排序和二分查找(后面在数组高级部分讲解)
二维数组概述
l 二维数组概述
• 每个班有很多个学生,所以,可以用数组来存储,而我们又同时有很多个班。这个也应该用一个数组来存储。如何来表示这样的数据呢?Java就提供了二维数组供我们使用。
• 由此可见:其实二维数组其实就是一个元素为一维数组的数组。
二维数组定义格式
l 格式1
• 数据类型[][] 变量名=new 数据类型[m][n];
• m表示这个二维数组有多少个一维数组
• n表示每一个一维数组的元素个数
• 举例:
• int[][] arr = newint[3][2];
• 定义了一个二维数组arr
• 这个二维数组有3个一维数组,名称是arr[0],arr[1],arr[2]
• 每个一维数组有2个元素,可以通过arr[m][n]来获取
• 表示获取第m+1个一维数组的第n+1个元素
/*
二维数组:就是元素为一维数组的一个数组。
格式1:
数据类型[][] 数组名 = new 数据类型[m][n];
m:表示这个二维数组有多少个一维数组。
n:表示每一个一维数组的元素有多少个。
注意:
A:以下格式也可以表示二维数组
a:数据类型 数组名[][] = new 数据类型[m][n];
b:数据类型[] 数组名[] = new 数据类型[m][n];
B:注意下面定义的区别
int x;
int y;
int x,y;
int[] x;
int[] y[];
int[] x,y[];
*/
class Array2Demo {
public static void main(String[] args) {
//定义一个二维数组
int[][] arr = new int[3][2];
//定义了一个二维数组arr
//这个二维数组有3个一维数组的元素
//每一个一维数组有2个元素
//输出二维数组名称
System.out.println(arr); //地址值 [[I@175078b
//输出二维数组的第一个元素一维数组的名称
System.out.println(arr[0]); //地址值 [I@42552c
System.out.println(arr[1]); //地址值 [I@e5bbd6
System.out.println(arr[2]); //地址值 [I@8ee016
//输出二维数组的元素
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
}
}
二维数组定义格式
l 格式2
• 数据类型[][] 变量名=new 数据类型[m][];
• m表示这个二维数组有多少个一维数组
• 这一次没有直接给出一维数组的元素个数,可以动态的给出。
• 举例:
• int[][] arr = newint[3][];
• arr[0] = new int[2];
• arr[1] = new int[3]
• arr[2] = new int[1];
/*
格式2:
数据类型[][] 数组名 = new 数据类型[m][];
m:表示这个二维数组有多少个一维数组。
列数没有给出,可以动态的给。这一次是一个变化的列数。
*/
class Array2Demo2 {
public static void main(String[] args) {
//定义数组
int[][] arr = new int[3][];
System.out.println(arr); //[[I@175078b
System.out.println(arr[0]); //null
System.out.println(arr[1]); //null
System.out.println(arr[2]); //null
//动态的为每一个一维数组分配空间
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[1];
System.out.println(arr[0]); //[I@42552c
System.out.println(arr[1]); //[I@e5bbd6
System.out.println(arr[2]); //[I@8ee016
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
//ArrayIndexOutOfBoundsException
//System.out.println(arr[0][2]); //错误
arr[1][0] = 100;
arr[1][2] = 200;
}
}
二维数组定义格式
l 格式3
• 数据类型[][] 变量名=new 数据类型[][]{{元素…},{元素…},{元素…}};
• 简化版格式:
• 数据类型[][] 变量名={{元素…},{元素…},{元素…}};
• 举例:
• int[][] arr = {{1,2,3},{4,6},{6}};
/*
格式3:
基本格式:
数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};
简化版格式:
数据类型[][] 数组名 = {{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};
举例:
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
int[][] arr = {{1,2,3},{4,5},{6}};
*/
class Array2Demo3 {
public static void main(String[] args) {
//定义数组
int[][] arr = {{1,2,3},{4,5},{6}};
System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[0][0]); //1
System.out.println(arr[1][0]); //4
System.out.println(arr[2][0]); //6
System.out.println(arr[0][1]); //2
System.out.println(arr[1][1]); //5
//越界
System.out.println(arr[2][1]); //错误
}
}
二维数组练习
l 二维数组遍历
/*
需求:二维数组遍历
外循环控制的是二维数组的长度,其实就是一维数组的个数。
内循环控制的是一维数组的长度。
*/
class Array2Test {
public static void main(String[] args) {
//定义一个二维数组
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
//请问谁代表{1,2,3}
//arr[0]就是第一个数组
//arr[0] = {1,2,3};
for(int x=0; x<arr[0].length; x++) {
System.out.println(arr[0][x]);
}
System.out.println("--------------");
for(int x=0; x<arr[1].length; x++) {
System.out.println(arr[1][x]);
}
System.out.println("--------------");
for(int x=0; x<arr[2].length; x++) {
System.out.println(arr[2][x]);
}
System.out.println("--------------");
//用循环改进
for(int x=0; x<3; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
System.out.println("--------------");
//这个时候,注意了,3是我们根据上面的代码得出来的
//但是,它不能针对任何的数组都可以这样
//所以,我们应该想办法改进
//其实,外面的这个循环的长度就是二维数组的长度
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
System.out.println("--------------");
//用方法改进
//调用方法
printArray2(arr);
System.out.println("--------------");
//我们再来一个列数是变化的
int[][] arr2 = {{1,2,3},{4,5},{6}};
printArray2(arr2);
}
/*
需求:遍历二维数组
两个明确:
返回值类型:void
参数列表:int[][] arr
*/
public static void printArray2(int[][] arr) {
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
}
}
l 公司年销售额求和
• 某公司按照季度和月份统计的数据如下:单位(万元)
• 第一季度:22,66,44
• 第二季度:77,33,88
• 第三季度:25,45,65
• 第四季度:11,66,99
/*
公司年销售额求和
某公司按照季度和月份统计的数据如下:单位(万元)
第一季度:22,66,44
第二季度:77,33,88
第三季度:25,45,65
第四季度:11,66,99
分析:
A:把题目的数据用二维数组来表示
int[][] arr = {{22,66,44},{77,33,88},{25,45,65},{11,66,99}};
B:如何求和呢?
求和其实就是获取到每一个元素,然后累加即可。
C:定义一个求和变量sum,初始化值是0。
D:通过遍历就可以得到每一个二维数组的元素。
E:把元素累加即可。
F:最后输出sum,就是结果。
*/
class Array2Test2 {
public static void main(String[] args) {
//把题目的数据用二维数组来表示
int[][] arr = {{22,66,44},{77,33,88},{25,45,65},{11,66,99}};
//定义一个求和变量sum,初始化值是0。
int sum = 0;
//通过遍历就可以得到每一个二维数组的元素。
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
//把元素累加即可。
sum += arr[x][y];
}
}
//最后输出sum,就是结果。
System.out.println("一年的销售额为:"+sum+"万元");
}
}
l 打印杨辉三角形(行数可以键盘录入)
/*
需求:打印杨辉三角形(行数可以键盘录入)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
分析:看这种图像的规律
A:任何一行的第一列和最后一列都是1
B:从第三行开始,每一个数据是它上一行的前一列和它上一行的本列之和。
步骤:
A:首先定义一个二维数组。行数如果是n,我们把列数也先定义为n。
这个n的数据来自于键盘录入。
B:给这个二维数组任何一行的第一列和最后一列赋值为1
C:按照规律给其他元素赋值
从第三行开始,每一个数据是它上一行的前一列和它上一行的本列之和。
D:遍历这个二维数组。
*/
import java.util.Scanner;
class Array2Test3 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//这个n的数据来自于键盘录入。
System.out.println("请输入一个数据:");
int n = sc.nextInt();
//定义二维数组
int[][] arr = new int[n][n];
//给这个二维数组任何一行的第一列和最后一列赋值为1
for(int x=0; x<arr.length; x++) {
arr[x][0] = 1; //任何一行第1列
arr[x][x] = 1; //任何一行的最后1列
}
//按照规律给其他元素赋值
//从第三行开始,每一个数据是它上一行的前一列和它上一行的本列之和。
for(int x=2; x<arr.length; x++) {
//这里如果y<=x是有个小问题的,就是最后一列的问题
//所以这里要减去1
//并且y也应该从1开始,因为第一列也是有值了
for(int y=1; y<=x-1; y++) {
//每一个数据是它上一行的前一列和它上一行的本列之和。
arr[x][y] = arr[x-1][y-1] + arr[x-1][y];
}
}
//遍历这个二维数组。
/*
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+"\t");
}
System.out.println();
}
*/
//这个时候,要注意了,内循环的变化必须和曾经讲过的九九乘法表类似
for(int x=0; x<arr.length; x++) {
for(int y=0; y<=x; y++) {
System.out.print(arr[x][y]+"\t");
}
System.out.println();
}
}
}
综合小练习(思考题)
l 看程序写结果,并总结基本类型和引用类型参数的传递问题
l 数据加密问题
/*
某个公司采用公用电话传递数据信息,数据是小于8位的整数,为了确保安全,
在传递过程中需要加密,加密规则如下:
首先将数据倒序,然后将每位数字都加上5,再用和除以10的余数代替该数字,
最后将第一位和最后一位数字交换。 请任意给定一个小于8位的整数,
然后,把加密后的结果在控制台打印出来。
题目要求:
A:数据是小于8位的整数
定义一个int类型的数据
int number = 123456;
B:加密规则
a:首先将数据倒序
结果 654321
b:然后将每位数字都加上5,再用和除以10的余数代替该数字
结果 109876
c:最后将第一位和最后一位数字交换
结果 609871
C:把加密后的结果输出在控制台
通过简单的分析,我们知道如果我们有办法把这个数据变成数组就好了。
不是直接写成这个样子的:
int[] arr = {1,2,3,4,5,6};
如何把数据转成数组呢?
A:定义一个数据
int number = 123456;
B:定义一个数组,这个时候问题就来了,数组的长度是多少呢?
int[] arr = new int[8]; //不可能超过8
在赋值的时候,我用一个变量记录索引的变化。
定义一个索引值是0
int index = 0;
C:获取每一个数据
int ge = number%10
int shi = number/10%10
int bai = number/10/10%10
arr[index] = ge;
index++;
arr[index] = shi;
index++;
arr[index] = bai;
...
*/
class JiaMiDemo {
public static void main(String[] args) {
//定义一个数据
int number = 123456;
//定义一个数组
int[] arr = new int[8];
//把数据中每一位上的数据获取到后存储到数组中
/*
int index = 0;
arr[index] = number%10; //arr[0]=6;
index++;
arr[index] = number/10%10; //arr[1]=5;
index++;
arr[index] = mumber/10/10%10; //arr[2]=4;
*/
//通过观察这个代码,我们发现应该是可以通过循环改进的
int index = 0;
while(number > 0) { //number=123456,number=12345,number=1234,number=123,number=12,number=1,number=0
arr[index] = number%10; //arr[0]=6,arr[1]=5,arr[2]=4,arr[3]=3,arr[4]=2,arr[5]=1
index++;//index=1,index=2,index=3,index=4,index=5,index=6
number/=10;//number=12345,number=1234,number=123,number=12,number=1,number=0
}
//然后将每位数字都加上5,再用和除以10的余数代替该数字
for(int x=0; x<index; x++) {
arr[x] += 5;
arr[x] %= 10;
}
//最后将第一位和最后一位数字交换
int temp = arr[0];
arr[0] = arr[index-1];
arr[index-1] = temp;
//输出数据
for(int x=0; x<index; x++) {
System.out.print(arr[x]);
}
System.out.println();
}
}
*
把刚才的代码改进一下:
A:把数据改进为键盘录入
B:把代码改进为方法实现
另一个数据的测试:
number:1234567
第一步:7654321
第二步:2109876
第三步:6109872
知识点:
变量
数据类型
运算符
键盘录入
语句
方法
数组
*/
import java.util.Scanner;
class JiaMiDemo2 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//请输入一个数据
System.out.println("请输入一个数据(小于8位):");
int number = sc.nextInt();
//写功能实现把number进行加密
//调用
String result = jiaMi(number);
System.out.println("加密后的结果是:"+result);
}
/*
需求:写一个功能,把数据number实现加密。
两个明确:
返回值类型:String 做一个字符串的拼接。
参数列表:int number
*/
public static String jiaMi(int number) {
//定义数组
int[] arr = new int[8];
//定义索引
int index = 0;
//把number中的数据想办法放到数组中
while(number > 0) {
arr[index] = number%10;
index++;
number /= 10;
}
//把每个数据加5,然后对10取得余数
for(int x=0; x<index; x++) {
arr[x] += 5;
arr[x] %= 10;
}
//把第一位和最后一位交换
int temp = arr[0];
arr[0] = arr[index-1];
arr[index-1] = temp;
//把数组的元素拼接成一个字符串返回
//定义一个空内容字符串
String s = "";
for(int x=0; x<index; x++) {
s += arr[x];
}
return s;
}
}