关键字和保留字
关键字
java语言赋予了特殊含义,用做专门用途的字符串(单词)
特点:关键字中的所有字母都是小写
class | interface | enum | byte | short |
int | long | float | double | char |
boolean | void |
if | else | switch | case | default |
while | do | for | break | continue |
return |
private | protected | public |
abstract | final | static | synchronized |
extends | implements |
new | this | super | instansceof |
try | catch | finally | throw | throws |
package | import |
native | strictftp | transient | volatile | assert |
true | false | null |
保留字
尚未使用的关键字:
- goto
- const
标识符
定义:
java对各种变量、方法和类等要素命名时使用的字符序列称为标识符(自己起名的地方)
定义的规则:
- 由26个英文字母大小写,0-9,_或$组成
- 数字不可以开头
- 不可以使用关键字和保留字,但能包含关键字和保留字
- java中严格区分大小写,长度无限制
- 标识符不能包含空格
涉及到的结构:
包名、类名、接口名、变量名、方法名、常量名
Java中的名称命名规范:
包名:
多单词组成时所有字母都小写:xxxzzz
类名、接口名:
多单词组成时,所有单词的首字母大写:XxxZzz
变量名、方法名:多字母组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz
常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ
见名知意
变量
变量结构:变量的数据类型、变量名和储存的值
数据类型 变量名 = 变量值
使用变量注意点:
- Java中每个变量必须先声明,后使用
- 使用变量名来访问这块区域的数据
- 变量的作用域:其定义所在的一对{}内
- 变量只有在其作用域内才有效
- 同一个作用域内,不能定义重名的变量
Java中定义的数据类型:
补充
变量在类中的声明的位置:
成员变量 vs 局部变量
在方法体外,类体内声明的变量称为成员变量。
在方法体内部声明的变量称为局部变量。
注意1:
二者在初始化值方面的异同:
同:都有生命周期
异:局部变量除形参外,需显式初始化。
注意2:
字符序列出现输出乱码现象:编码和解析(解码)的字符集(编码集)不一致。
转义字符前多加一个\就表示不是转义字符,原样输出即可。
String属于引用数据类型
String可以与8种基本数据类型变量做运算,但运算只能是连接运算:+,运算的结果仍然是String类型
基本数据类型(除boolean)之间运算规则:
1.自动类型提升:
当数的表示范围小的数据类型变量与表示范围大的数据类型变量间做运算时,自动提升为表示范围大的数据类型。
byte、char、short->int->long->float->double
2.强制类型转换(自动类型提升运算逆运算):
用法: 数据类型 变量名1 = (数据类型) 变量名0
例如 :
double d1 = 12.9;
int i1 = (int)d1;//截断操作,():强转符
注意:强制类型转换可能导致精度损失。
String转换成int:
int num = Integer.parseInt(str);
获取字符串中字符使用charAt()方法
String m = "hello,world!"
char n = m.charAt(x);//x:字符串中的位序
进制间转换:
二进制:以0b或0B开头
十进制:
八进制:以数字0开头表示
十六进制:以0x或0X开头表示。
int num1 = 0b110;
int num2 = 110;
int num3 = 0127;
int num4 = 0x110A;
System.out.println("num1="+num1);
System.out.println("num2="+num2);
System.out.println("num3="+num3);
System.out.println("num4="+num4);
原码:
反码:
补码:
计算机底层都已补码的方式来储存数据!
练习1
char c = 'a';
int num =10;
String str = "hello";
System.out.println(c + num + str);//107hello
System.out.println(c + str + num);//ahello10
System.out.println(c + (num + str));//a10hello
System.out.println((c + num) + str);//107hello
System.out.println(str + num + c);//hello10a
练习2
//控制台输出* *样
System.out.println("* *");
System.out.println('*'+('\t'+"*"));
System.out.println('*'+"\t"+'*');
练习3
String str1 = 4;//判断对错:false
String str2 = 3.5f + "";//判断str2对错:true
System.out.println(str2);//输出:3.5
System.out.println(3+4+"Hello");//输出:7Hello
System.out.println("Hello"+3+4);//输出:Hello34
System.out.println('a'+1+"Hello");//输出:98Hello
System.out.println("Hello"+'a'+1);//输出:Helloa1
问题:
1.标识符的命名规则有哪些?
1.由26个英文字母大小写,0-9,_或$组成
2.数字不可以开头
3.不可以使用关键字和保留字,但能包含关键字和保留字
4.java中严格区分大小写,长度无限制
5.标识符不能包含空格
2.标识符的命名规范有哪些?
包名:多单词组成时所有字母都小写:xxxzzz
类名、接口名:多单词组成时,所有单词的首字母大写:XxxZzz
变量名、方法名:多字母组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz
常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ
3.Java变量按照数据类型怎么划分?并指出Java的基本数据类型有哪几种,并指出各自占用内存空间大小。
分为基本数据类型和引用数据类型。8种:byte(8bit,1字节),short(2字节),int(4字节),long(8字节),float(4字节),double(8字节),char(2字节),boolean(1字节)。
4.说明基本数据类型变量之间自动类型提升的运算规则。
1.自动类型提升:
当数的表示范围小的数据类型变量与表示范围大的数据类型变量间做运算时,自动提升为表示范围大的数据类型。
byte、char、short->int->long->float->double
5.说明基本数据类型变量之间强制类型转换的使用规则和强转可能出现的问题。
强制类型转换(自动类型提升运算逆运算):
用法: 数据类型 变量名1 = (数据类型) 变量名0
例如 :
double d1 = 12.9;
int i1 = (int)d1;//截断操作,():强转符
注意:强制类型转换可能导致精度损失。
运算符
定义:运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。
算术运算符
赋值运算符
比较运算符(关系运算符)
逻辑运算符
位运算符(java开发使用较少)
三元运算符
算术运算符
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
– | 负号 | b=4;-b | -4 |
+ | 加 | 5+5 | 10 |
– | 减 | 6-4 | 2 |
* | 乘 | 3*4 | 12 |
/ | 除 | 6/3 | 2 |
% | 取余(取模) | 7%5 | 2 |
++i | 自增(前),先运算后取值 | a=2;b=++a; | a=3;b=3 |
i++ | 自增(后),先取值后运算 | a=2;b=a++; | a=3;b=2 |
–i | 自减(前),先运算后取值 | a=2;b=–a; | a=1;b=1 |
i– | 自减(后),先取值后运算 | a=2;b=a–; | a=1;b=2 |
+ | 字符串连接 | “he”+”llo” | “hello6” |
练习:
public class SignTest{
public static void main(String[] args){
int i1 = 10;
int i2 = 20;
int i = i1++;
System.out.println("i="+i);
System.out.println("i1="+i1);
i = ++i1;
System.out.println("i="+i);
System.out.println("i1="+i1);
i = i2--;
System.out.println("i="+i);
System.out.println("i2="+i2);
i = --i2;
System.out.println("i="+i);
System.out.println("i2="+i2);
}
}
//i=10 i1=11
//i= 12 i1=12
//i=20 i2=19
//i=18 i2=18
赋值运算符
符号:=
;当“=”两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。(支持连续赋值)。
扩展赋值运算符:+=,-=,*=,、=,%=
比较运算符
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
== | 等于 | 4==3 | false |
!= | 不等于 | 4!=3 | true |
< | 小于 | 4<3 | false |
> | 大于 | 4>3 | true |
<= | 小于等于 | 4<=3 | false |
>= | 大于等于 | 4>=3 | true |
instanceof | 检查是否是类的对象 | “Hello” instanceof String | true |
注:比较运算符的结果都是boolean型,要么是true,要么是false。
补充:==和equals的区别?
大多数人会说前者比较地址,后者比较内容,但这种说法并不是很准确。
1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;如果作用于引用类型的变量,则比较的是所指向的对象的地址。
2)对于equals方法(注意:equals方法不能作用于基本数据类型的变量),如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
逻辑运算符
符号 | & | | | ! | && | || | ^ |
---|---|---|---|---|---|---|
释义 | 逻辑与 | 逻辑或 | 逻辑非 | 短路与 | 短路或 | 逻辑异或 |
运算规则:
a | b | a&b | a&&b | a|b | a||b | !a | a^b |
---|---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 |
1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
注:0–false;1–true
&&(短路与)与&的区别:
- 最终结果都是一样的
- &&具有短路的效果。左边是false,右边就不执行
int x1 = 3;
int y1 = 4;
System.out.println((++x1 == 3) & (++y1 == 4)); //false & false = false
System.out.println("x1 = " + x1); //x1 = 4
System.out.println("y 1= " + y1); //y1 = 5
int x2 = 3;
int y2 = 4;
System.out.println((++x2 == 3) && (++y2 == 4)); //false & false = false
System.out.println("x2 = " + x2); //x2 = 4
System.out.println("y2 = " + y2); //y2 = 4
||(短路或)与|的区别:
- 最终的效果都是一样的
- ||具有短路的效果,左边为true,右边不执行
int x1 = 3;
int y1 = 4;
System.out.println((++x1 == 3) | (++y1 == 4)); //false & false = false
System.out.println("x1 = " + x1); //x1 = 4
System.out.println("y 1= " + y1); //y1 = 5
int x2 = 3;
int y2 = 4;
System.out.println((++x2 == 3) || (++y2 == 4)); //false & false = false
System.out.println("x2 = " + x2); //x2 = 4
System.out.println("y2 = " + y2); //y2 = 5
int x3 = 3;
int y3 = 4;
System.out.println((++x3 == 4) || (++y3 == 4)); //true & false = true
System.out.println("x3 = " + x3); //x3 = 4
System.out.println("y3 = " + y3); //y3 = 4
位运算符
运算符 | 运算 | 范例 | 细节 |
---|---|---|---|
<< | 左移 | 3<<2 = 12(3 _ 2 _ 2) | 空位补0,被移除的最高位丢弃 |
>> | 右移 | 3>>1=3/2=1 | 被移位的二进制最高位是0,空位补0,最高位是1,则空位补1 |
>>> | 无符号右移 | 3>>>1=1 | 空位补0 |
& | 与运算 | 6 & 3=2 | 只有1 & 1结果是1,其余为0 |
| | 或运算 | 6 | 3=7 | 只有0 | 0结果是0,其余是1 |
^ | 异或运算 | 6 ^ 3 =5 | 相同二进制位进行^运算,结果是0;不相同二进制位,结果是1 |
~ | 取反运算 | ~6 =-7 | 各二进制码按补码按位取反 |
位运算是直接对整数的二进制进行的运算
三元运算符
格式:(条件表达式)?表达式1 : 表达式2;
true:表达式1;false:表达式2。
表达式1和表达式2为同种类型。
注:
(m > n)? 2:"n";//编译错误
String maxstr = (m > n)? "m大" : ((m==n)? "m和n一样大" : "n大");//三元运算符可有嵌套使用
三元运算符与if-else
的联系与区别:
1)三元运算符可简化if-else语句
2)三元运算符要求必须返回一个结果
3)if后的代码块可有多个语句
运算符优先级:
单目:单目运算符+ –(负数) ++ — 等
乘除:算数单目运算符* / % + –
位:位移单目运算符<< >>
关系:关系单目运算符> < >= <= == !=
逻辑:逻辑单目运算符&& || & | ^
三目:三目单目运算符A > B ? X : Y
后:无意义,仅仅为了凑字数
赋值:=
注:单目运算符是指仅对一个操作数运算的操作符
练习:
//&
int x = 1, y = 1;
if(x++==2 & ++y==2){//false & false
x = 7;
}
System.out.println("x="+x+",y="+y);//x=2,y=2
//&&
int x = 1, y = 1;
if(x++==2 && ++y==2){//false
x = 7;
}
System.out.println("x="+x+",y="+y);//x=2,y=1
//|
int x = 1, y = 1;
if(x++==1 | ++y==1){//true | false
x = 7;
}
System.out.println("x="+x+",y="+y);//x=7,y=2
// ||
int x = 1, y = 1;
if(x++==1 || ++y==1){//true
x = 7;
}
System.out.println("x="+x+",y="+y);//x=7,y=1
面试题1:
class Test{
public static void main(String[] args){
boolean x = true;
boolean y = false;
short z = 42;
//if(y==true)
if(z++==42)&&(y = true)z++;
if((x = false)||(++z==45))z++;
System.out.println("z="+z);
}
}
//if(y==true):z=43
//z=46
面试题2:
最高效的计算2 * 8?
2<<3或8<<1
练习:交换两个变量的值
int num1 = 10;
int num2 = 20;
//method1:
//常用,包括字符型
int temp = num1;
num1 = num2;
num2 = temp;
System.out.println("num1="+num1);
System.out.println("num2="+num2);
//method2:
//弊端:1.可能超出取值范围;2.有局限性:只能用于数值类型
num1 += num2;//num1 = num1 + num2;
num2 = num1 - num2;
num1 -= num2;// num1 = num1 - num2;
System.out.println("num1="+num1);
System.out.println("num2="+num2);
//method3:
//有局限性:只能用于数值类型
num1 = num1 ^ num2;
num2 = num1 ^ num2;
num1 = num1 ^ num2;
System.out.println("num1="+num1);
System.out.println("num2="+num2);
练习:如何求一个0~255范围内的整数的十六进制值,例如60的十六进制表示时3C
//method1:自动实现
String str1 = Integer.toBinaryString(60);
String str2 = Integer.toHexString(60);
//method2:手动实现
int i1 = 60;
int i2 = i1 & 15;//位运算符&
String j = (i2 > 9) ? (char)(i2 - 10 + 'A') + "": i2 + "";
int temp = i1 >>> 4;
i2 = temp & 15;
String k = (i2 > 9) ? (char)(i2 - 10 + 'A') + "": i2 + "";
System.out.println(k + "" + j);
练习:定义三个int型变量并赋值,使用三元运算符或者if-else获取这三个中较大数的实现。
class SanYuanTest {
public static void main(String[] args){
//获取两个整数的较大值
int m = 12;
int n = 5;
int max = (m > n) ? m:n;
System.out.println(max);
//获取三个数的最大值
int n1 = 12;
int n2 = -30;
int n3 = 43;
int max1 = (n1 > n2) ? n1 : n2;//if(n1 > n2)max1 = n1; else max1 = n2;
int max2 = (max1 >n3) ? max1 : n3;//if(max1 > n3)max2 = max1; else max2 = n3;
System.out.println("最大值为"+ max2);
}
}
练习:编写程序,声明2个double型变量并赋值。判断第一个数大于10.0且第二个数小于20.0,打印两数之和,否则打印两数之积。
public class IfTest {
public static void main(String[] args){
double num1 = 11.0;
double num2 = 21.2;
if(num1 > 10.0 && num2 <20.0) {
System.out.println("两数之和是" + (num1 + num2));
}else {
System.out.println("两数之积是" + (num1 * num2));
}
}
}
程序流程控制
顺序结构
选择(分支)结构
if-else结构
if语句三种格式:
1.if(条件表达式){
执行代码块;
}
2.if(条件表达式){
执行代码块1;
}else{
执行代码块2;
}
3.if(条件表达式1){
执行代码块1;
}else if(条件表达式2){
执行代码块2;
}
……
else{
执行代码块n;
}
}
说明:
1.else结构是可选的。
2.针对条件表达式:
- 如果多个条件表达式之间存在“互斥”关系,哪个判断和执行语句声明 在上面还是下面,都可以。
- 如果多个条件表达式之间存在交集关系,调换判断语句和执行语句顺序将受到影响。
- 如果多个条件表达式之间存在包含关系,一般需要将范围小的声明置于范围大的上面。否则,范围小的将不予执行。
3.只有一行执行语句时,{}可省略,并有就近原则。
Scanner类的使用及获取随机数
Scanner类的使用
使用Scanner
从键盘获取int型数据,通过导入java.util.Scanner
包实现键盘获取具体格式如下:
import java.util.Scanner;//byte、boolean、double……
class ScannerTest{
public static void main(String[] args){
Scanner sc = new Scanner(System.in)//实例化
int num = sc.nextInt();
System.out.println(num);
}
}
注:对于char型的获取,Scanner没有提供相关的方法。只能获取字符串。
随机数
获取一个随机数的方法: Math.random()
:只能生成[0.0,1.0)的数值,需要人为匹配需求数值范围
例子:
//获取一个随机整数,范围10-99
int value = (int)(Math.random() * 90 + 10)//[10,99]
匹配随机数[a,b]
的公式:
(int)(Math.random()*(b-a+1))+a
switch-case结构
格式:
switch(表达式){//byte、short、char、int、枚举类型(jdk5.0新增)、String(jdk7.0新增)。
case 常量1:
语句1;
break;
case 常量2:
语句2;
break;
...
case 常量n:
语句n;
break;
default://前面都没有时,通过此条(类似else)
语句;
break;
}
说明:
1.根据switch
表达式中的值,依次匹配各个case
中的常量。一旦匹配成功,则进入相应case
结构中,调用其执行语句。当调用完执行语句以后,则仍然继续向下执行其他case
结构中的执行语句,直到遇到break
关键词或此switch-case
结构末尾为止。
2.break
可以使用在switch-case
结构中,表示一旦执行此关键字,就跳出switch-case
结构。
3.switch
结构中的表达式只能是如下6种数据类型之一:byte、short、char、int、枚举类型(jdk5.0新增)、String(jdk7.0新增)。
4.case
之后只能声明常量,不能声明范围。
5.break
关键字可选。
6.default
:相当于if-else
中的else
;也是可选的,而且位置是可变的。
注:
1.如果switch-case结构中的多个case的执行语句相同,则可以考虑合并。
case 0:
case 1:
sout();
break;
case 2:
case 3:
.......
2.if语句和switch语句可以相互嵌套。
3.凡是可以使用switch-case的结构,都可以转换成if-else 。反之不成立。
4.当两个(if,switch)都可以使用时,并且case表达式取值不太多,此时使用switch。执行效率稍高。
例题:小写字母转换成大写(switch)
import java.util.Scanner;
public class SwitchCaseTest2 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String word = sc.next();
char c = word.charAt(0);
switch (c){
case 'a':
System.out.println("A");
break;
case 'b':
System.out.println("B");
break;
case 'c':
System.out.println("C");
break;
case 'd':
System.out.println("D");
break;
default:
System.out.println("other");
}
}
}
例题:从键盘输入2019年的“month”和“day”,要求通过程序输出是2019年的第几天。
import java.util.Scanner;
public class Switch3 {
public static void main(String[] args){
Scanner sc =new Scanner(System.in);
System.out.println("请输入月份:");
int month = sc.nextInt();
System.out.println("请输入日:");
int day = sc.nextInt();
int countfront ;
switch (month){
case 1:
countfront = 0;
break;
case 2:
countfront = 31;
break;
case 3:
countfront = 31+28;
break;
case 4:
countfront = 31+28+31;
break;
case 5:
countfront = 31+28+31+30;
break;
case 6:
countfront = 31+28+31+30+31;
break;
case 7:
countfront = 31+28+31+30+31+30;
break;
case 8:
countfront = 31+28+31+30+31+30+31;
break;
case 9:
countfront = 31+28+31+30+31+30+31+31;
break;
case 10:
countfront = 31+28+31+30+31+30+31+31+30;
break;
case 11:
countfront = 31+28+31+30+31+30+31+31+30+31;
break;
default:
countfront = 31+28+31+30+31+30+31+31+30+31+30;
}
int countdays= countfront + day;
System.out.println(month+"月"+ day + "日是2019年的第" + countdays + "天");
}
//简洁:
switch (month){
case 12:
countfront += 30;
case 11:
countfront += 31;
case 10:
countfront += 30;
case 9:
countfront += 31;
case 8:
countfront += 31;
case 7:
countfront += 30;
case 6:
countfront += 31;
case 5:
countfront += 30;
case 4:
countfront += 31
case 3:
countfront += 28;
case 2:
countfront += 31;
case 1:
countfront += day;
}
System.out.println(countfront);
}
练习:从键盘读入score,区分等级。
score >= 90 : A; 70 <= score < 90 :B; 60 <= score <70:C; score < 60:D.
import java.util.Scanner;
public class Switch4 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入成绩:");
int score = sc.nextInt();
switch (score/10){
case 10:
case 9:
System.out.println("A");
break;
case 8:
case 7:
System.out.println("B");
break;
case 6:
System.out.println("C");
break;
default:
System.out.println("D");
}
}
}
例题:遍历100以内的偶数,输出所有偶数的和,并输出偶数的个数。
public class ForTest {
public static void main(String[] args){
int sum = 0;
int count =0;
for (int i=0;i<=100;i+=2){
System.out.println(i);
sum +=i;
count++;
}
System.out.println(sum);
System.out.println(count);
}
}
例题:1-150,打印输出,并且3的倍数在后打印foo,5打印biz,7打印baz。
public class ForTest2 {
public static void main(String[] args){
for (int i = 1;i <= 150;i++){
if (i % 3 == 0){
if (i % 5 == 0){
if (i % 7 ==0){
System.out.println(i +" foo biz baz");
}else if (i % 7 == 0){
System.out.println(i + "foo baz");
}else {
System.out.println(i + "foo biz");
}
}else {
System.out.println(i + " foo");
}
}else if (i % 5 == 0){
if (i % 7 ==0) {
System.out.println(i + " biz baz");
}else
System.out.println(i + " biz");
}else if (i % 7 ==0){
System.out.println(i + " baz");
}else {
System.out.println(i);
}
}
}
}
//2:
for (int i = 1;i <= 150;i++){
System.out.print(i + " ");
if (i % 3 == 0){
System.out.print( "foo ");
}
if (i % 5 == 0){
System.out.print( "biz ");
}
if (i % 7 ==0){
System.out.print( "baz ");
}
System.out.println();
}
问题:
1.switch后面使用的表达式可以是哪些数据类型。
byte、short、char、int、枚举类型、String
2.谈一谈三元运算符、if-else和switch-case结构使用场景的理解
3.如何从控制台获取String和int型的变量,并输出。(用代码实现)
1.import java.util.Scanner;
2.Scanner sc = new Scanner(System.in);
3.String s1 = sc.next();//int n1 = sc.nextInt();
4.sout(s1/n1);
循环结构
循环结构4要素:
- 初始化条件①
- 循环条件(boolean类型)②
- 循环体③
- 迭代条件④
for循环
格式:
for(①;②;④){③}
执行过程:①->②->③->④->③->④….->!②
思考:
int num = 1;
for(System.out.print('a');num <= 3;System.out.print('a'),num++){
System.out.print('b')
}
//输出结果:abcbcbc
注:初始化条件只在()内有效,循环外失效。
while循环
格式:
①
while(②){
③;
④;
}
执行过程:①->②->③->④->②->③->④…->!②
思考:
class WhileTest{
public static void main(String[] args){
int i =1;
while(i <= 100){
if(i % 2 == 0){
System.out.println(i)
}
i++;//若无迭代条件,会陷入死循环
//算法的有限性
}
}
}
注:while循环和for循环可以相互转换。区别:for循环和while循环的初始化条件部分作用范围不同。
do-while循环
格式结构:
①
do{
③;
④;
}whlie(②);
执行过程:①->③->④->②->③->④->…->!②
说明:
1.do-while循环至少会执行一次循环体。
2.开发中,使用for和while更多一些,较少使用do-while。
思考:
class DoWhTest{
public static void main(String[] args){
//遍历100以内的偶数,并计算所有偶数的和及偶数的个数
int num =1;
int sum = 0;//记录总和
int count = 0;//记录个数
do{
if(num % 2 == 0){
System.out.println(num)
sum += num;
count++;
}
num++;//若无迭代条件,会陷入死循环
//算法的有限性
}while(num <= 100);
System.out.println(sum);
System.out.println(count);
}
}
循环语句补充说明:
1.不在循环条件部分限制次数的结构:while(true)或for(;;)
2.结束循环的几种方式:方式一,循环条件部分返回false;方式二,在循环体中执行break。
嵌套循环(多层循环)
定义:将一个循环结构A声明在另一个循环结构B的循环体中就构成了嵌套循环。
结构:
for(){//while();外层循环(B)
for(){//while();内层循环(A)
...
}
}
注:
1.内层循环结构遍历一遍,外层循环结构才执行一次。
2.假设外层循环需要执行m次,内层循环需要n次,此时内层循环的循环体一共执行了m * n次。
思考:
/*输出:
*
**
***
****
*/
for(int i = 1;i <= 4;i++){//外层循环控制行数
for(int j = 1;j <= i;j++){//内层循环控制列数;倒三角:j <= i --> j <= n-i
System.out.print("*");
}
System.out.println();
}
特殊关键字break
和continue
的使用
默认时:
关键字 | 使用范围 | 在循环中的作用(不同点) | 相同点 |
---|---|---|---|
break | swtich-case和循环结构中 | 结束当前循环(所在的子循环) | 关键字后面不能声明执行语句 |
continue | 循环结构中 | 结束本次循环(跳过本次) |
带标签时:
public class LabelBreak {
public static void main(String[] args) {
label:for (int i = 1;i <= 4;i++){
for (int j = 1;j <= 10;j++){
if (j % 4 ==0){
// break;//默认跳出包裹此关键字最近的一层循环
// continue;
//break label;//结束指定标识的一层循环结构
continue label;//结束指定标识的循环结构的当次循环
}
System.out.print(j);
}
System.out.println();
}
}
}
例题:输入两个正整数m和n,求其最大公约数和最小公倍数(12和20的最大公约数是4,最小公倍数是60;for,break)。
import java.util.Scanner;
public class ForTest3 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入两个正整数:");
int m = sc.nextInt();
int n = sc.nextInt();
//获取最大公约数
//1.获取两个数中较小值
int min = (m <= n)? m : n;
//2.遍历
for (int i = min;i >= 1;i-- )
if (m % i == 0 && n % i == 0) {
System.out.println("最大公约数是" + i);
break;//一旦在循环中执行到break,就跳出当前循环。
}
//获取最小公倍数
//1.获取两个数中较大值
int max = (m >= n) ? m:n;
for (int i = max;i <= m * n;i++ )
if (i % m == 0 && i % n ==0) {
System.out.println("最小公倍数是" + i);
break;//一旦在循环中执行到break,就跳出当前循环。
}
}
}
练习:输出所有水仙花数,所谓水仙花数是指一个三位数,其各个位上数字立方和等于其本身。
例如: 153 = 1 _ 1 _ 1 + 3 _ 3 _ 3 + 5 _ 5 _ 5
public class ForExer {
public static void main(String[] args) {
for (int i =100;i < 1000;i++){
int c = i%10;
int b = i%100/10;
int a = i/100;
if (c*c*c+b*b*b+a*a*a==i){
System.out.println(i);
}
}
}
循环语句综合例题
1.从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int pcount = 0;
int ncount = 0;
System.out.println("请输入几个整数:");
while(true){//for(;;)无限循环
int num = sc.nextInt();
if (num > 0) {
pcount++;
}else if (num <0){
ncount++;
}else break;
}
System.out.println("正数个数为" + pcount);
System.out.println("负数个数为" + ncount);
}
}
练习:
1.打印菱形
//提示:多层循环
public class Test2 {
public static void main(String[] args) {
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 5 - i; j++) {
}
for (int k = 1; k <= i; k++) {
System.out.print(" * ");
}
System.out.println();
}
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= i; j++) {
if (j == 1) {
System.out.print(" ");
}else{
System.out.print(" ");
}
}
for (int k = 1; k <= 4 - i; k++) {
System.out.print(" * ");
}
System.out.println();
}
}
}
2.打印九九乘法表
public class Test3 {
public static void main(String[] args) {
for (int i = 1;i <= 9;i++){
for (int j = 1;j <= i;j++){
System.out.print(i+"*"+j+"="+i*j+" ");
}
System.out.println();
}
}
}
3.100以内的所有素数的输出
//素数(质数):只能被1和本身整除的自然数。
//my method1
public class Test4 {
public static void main(String[] args) {
for (int i = 2;i <=100;i++){
int jcount=0;//重置计数器
for (int j = 1;j <= Math.sqrt(i);j++){//优化2
if (i % j == 0){
jcount++;
if (jcount>2) break;//优化1
}
}
if (jcount<3){
System.out.println(i);
}
}
}
}
//my method2
System.out.print("2\n3\n5\n7\n");
for (int i = 2;i <=100;i++){
if (i % 2 == 0 || i % 3 == 0 ||i % 5 == 0||i % 7 == 0){
continue;
}else{
System.out.println(i);
}
}
//
public class Test4 {
public static void main(String[] args) {
boolean isFlag = true;
for (int i = 2;i <=100000;i++){
for (int j = 2;j <= Math.sqrt(i);j++){
if (i % j == 0){
isFlag = false;
break;//优化之处
}
}
if (isFlag == true){
System.out.println(i);
}
isFlag = true;
}
}
}
问题:
1.循环结构设计如何最后退出循环的,有哪些不同的情况请说明。
①循环条件返回false
②在循环体内,执行到break,跳出循环
2.一个数如果恰好等于它的因子之和,这个数就称为“完数”。(因子除去本身)
例如:6=1+2+3
3.找出1000以内的所有完数。
public class Test5 {
public static void main(String[] args){
for(int i = 2;i<=1000;i++)//遍历10000以内的所有数
{
int count = 1;//定义为1是因为完全数的定义
for(int j=2;j<=i/2;j++)//小于等于i/2是因为每个整数的最大因子不超过它的一半
{
if(i%j==0)//如果被整除,说明j是i的因子
{
count =count + j;//因子累加
}
}
if(i==count)//判断当前数和其所有因子和是否相等
{
System.out.print(i+"、");//如果相等,打印输出
}
}
}
}
补充
衡量一个功能代码的优劣:
1.正确性
2.可读性
3.健壮性
4.高效率和低存储:时间复杂度、空间复杂度
数组
数组的概述
定义:是多个相同类型数据按一定顺序排列的集合,并通过编号的方式对这些数据进行统一管理。
数组是唯一的底层容器
数组的常见概念:
- 数组名
- 下表(索引)
- 元素
- 数组的长度(元素的个数)
数组的特点:
- 数组是有序排列的
- 数组本身是引用数据类型,而数组元素可以是任何数据类型
- 创建数组对象会在内存中开辟一块连续的空间,而数组名中引用的是这块连续空间的首地址
- 数组的长度一旦确定,就不能修改
- 可以直接通过索引方式调用指定位置的元素。
数组的分类:
- 按照维度:一维,二维……
- 按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(及对象数组)
一维数组
一维数组的使用:
- 一维数组的声明与初始化
//数组的声明+初始化
int[] ids = new int[]{1001,1002,1003};//静态初始化:数组初始化和元素赋值同时进行
String[] names = new String[4];//动态初始化:数组初始化和元素赋值分开进行
//也是正确的
int arr[] = {1,2,3}//类型推断
注:初始化完成,长度确定。
- 如何调用数组的指定位置的元素:通过索引
names[index] = "xxx";//index从0开始,从length-1结束
- 如何获取数组的长度(length属性)
Array.length
- 如何遍历数组
for(int i = 0;i < Array.length;i++){
System.out.println(Array[i]);
}
- 数组元素的默认初始化值
- 数组元素是整型:0
- 数组元素是浮点型:0.0
- 数组元素是char型:0或’\u0000’,非’0′
- 数组元素是boolean型:false
- 数组元素是引用数据类型时:null
6.数组的内存解析
练习:
1.用数组写出电话号码
public class ArraysTest {
public static void main(String[] args) {
int[] arr = new int[] {9,5,8,2,1,0,3};
int[] index = new int[] {4,6,5,3,0,2,6,1,5,6,6};
String tel = "";
for (int i = 0;i < index.length;i++){
tel += arr[index[i]];
}
System.out.println("联系方式:" + tel);
}
}
2.从键盘读入学生成绩,找出最高分,并输出学生成绩等级(数组)
public class ArrayTest2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("输入学生人数:");
int stunumber = sc.nextInt();
int[] gradearr = new int[stunumber];
int max = 0;
System.out.println("输入" + stunumber + "个成绩 ");
for (int i = 0; i < gradearr.length; i++) {
int grade = sc.nextInt();
gradearr[i] = grade;
if (gradearr[i] >= max){
max = gradearr[i];
}
}
System.out.println("最高分为:" + max);
char level;
for (int i = 0; i < gradearr.length; i++){
if (gradearr[i] >= (max-10)){
level = 'A';
}else if (gradearr[i] >= (max-20)){
level = 'B';
}else if (gradearr[i] >= (max-30)){
level = 'C';
}else {
level = 'D';
}
System.out.println("student" + i + " score is " + gradearr[i] + " grade is " + level);
}
}
}
练习:
public class ArrayTest3 {
public static void main(String[] args) {
int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
int sum = 0;
for (int i =0;i < arr.length;i++){
for (int j = 0;j < arr[i].length;j++){
sum += arr[i][j];
}
}
System.out.println("sum is: " + sum);
}
}
练习:打印10行杨辉三角
//myMethod
public class YangHuiTest {
public static void main(String[] args) {
int[][] yanghui = new int[10][];
for (int i = 0;i < yanghui.length;i++){
yanghui[i] = new int[i+1];
for (int j = 0;j < yanghui[i].length;j++){
if(j == 0 || j == i){
yanghui[i][j] = 1;
}
if (j > 0 && j < i){
yanghui[i][j] = yanghui[i-1][j-1] +yanghui[i-1][j];
}
System.out.print(yanghui[i][j]+" ");
}
System.out.println();
}
}
}
拓展笔试题:创建一个长度为6的int型数组,要求数组元素的值都在1-30之间,且是随机赋值,同时要求元素的值各不相同。
public class Test {
public static void main(String[] args) {
int[] arr = new int[6];
for (int i = 0;i < arr.length;i++){
arr[i] = (int)(Math.random()*30)+1;
for (int j = i;j > 0;j--){
if (arr[i] == arr[j-1]){
arr[i] = (int)(Math.random()*30)+1;
}
}
System.out.println(arr[i]);
}
}
}
回形数
*
练习:
定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值、最小值与和。要求所有随机数都是两位数。
public class Test2 {
public static void main(String[] args) {
int[] arr = new int[10];
int max = 0, min = 0, sum = 0;
double avg = 0.0;
for (int i = 0;i < arr.length;i++){
arr[i] = (int)(Math.random()*90+10);
if (i == 0) {
max = min = arr[0];
}else {
if (max <= arr[i]) {
max = arr[i];
}
if (min >= arr[i]) {
min = arr[i];
}
}
sum += arr[i];
avg = (double)sum/10;
System.out.println(arr[i]);
}
System.out.println("max="+ max);
System.out.println("min="+ min);
System.out.println("sum="+ sum);
System.out.println("avg="+ avg);
}
}
练习:使用简单数组
(1)创建一个名为ArrayTest的类,在main()方法中声明int型array1和array2两个数组变量;
(2)使用{},把array1初始化为8个素数:2,3,5,7,11,13,17,19;
(3)显示array1的内容
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值,打印array1
思考:array1和array2是什么关系?
拓展:实现array2对array1的复制。
public class Test3 {
public static void main(String[] args) {
int[] array1 = new int[]{2,3,5,7,11,13,17,19};
int[] array2 ;
for (int i = 0;i < array1.length;i++) {
System.out.print(array1[i]+" ");
}
System.out.println();
array2 = array1;//不是复制
for (int k = 0;k < array1.length;k++) {
if (k % 2 == 0) {
array2[k] = k;
}
System.out.print( array1[k] + " ");
}
}
}
//思考:地址值相同,都指向了堆空间的唯一的一个数组实体。
//拓展-复制
public class Test4 {
public static void main(String[] args) {
int[] array1 = new int[]{2,3,5,7,11,13,17,19};
int[] array2 = new int[array1.length];
for (int i = 0;i < array1.length;i++) {
System.out.print(array1[i]+" ");
}
System.out.println();
for (int k = 0;k < array2.length;k++) {
array2[k] = array1[k];
if (k % 2 == 0) {
array2[k] = k;
}
System.out.print( array1[k] + " ");
}
}
}
//反转
//method1
public class Test5 {
public static void main(String[] args) {
String[] arr = new String[]{"JJ","DD","MM","BB","GG","AA"};
for (int i = 0;i < arr.length/2;i++){
String tmp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = tmp;
}
for (int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
}
}
}
//method2
public class Test {
public static void main(String[] args) {
String[] arr = new String[]{"JJ","DD","MM","BB","GG","AA"};
for (int i = 0,j = arr.length-1;i < j;i++,j--) {
String tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
for (int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
}
}
}
//查找(线性查找、二分法查找)
public class Test2 {
public static void main(String[] args) {
String[] arr = new String[]{"JJ","DD","MM","BB","GG","AA"};
//线性查找
String dest = "BB";
boolean isFlag = true;
for (int i = 0;i < arr.length;i++){
if (dest.equals(arr[i])){
System.out.println("find it:" + i);
isFlag = false;
break;
}
}
if (isFlag){
System.out.println("not find");
}
//二分法查找(折半查找),前提:所要查找的序列是有序的
int[] arr1 = new int[]{-98,-34,2,34,66,79,105,210,333};
int dest1 = 34;
int head = 0,end = arr1.length - 1;
boolean isFlag1 = true;
while(head <= end){
int middle = (head + end)/2;
if (dest1 == arr1[middle]){
System.out.println("position is:" + middle);
isFlag1 = false;
break;
}else if (arr1[middle] >dest1){
end = middle - 1;
}else {
head = middle + 1;
}
}
if (isFlag1){
System.out.println("not find");
}
//移动
System.arraycopy(数组名,,,)
}
}
多维数组
二维数组的使用
- 二维数组声明与初始化
//静态初始化
int[][] arr1 = new int[][]{{1,2,3},{4,5,6}};
//动态初始化1
String[][] arr2 = new String[2][3];
//动态初始化2
String[][] arr3 = new String[2][];
//也是正确的
int arr4[][] = {{1,2,3},{4,5}}//类型推断
- 如何调用数数组指定位置的元素
//取2(1.)
arr1[0][1]
//第二行第二列
arr2[1][1]
- 如何获取二维数组的长度
arr.length
arr[0].length
- 如何遍历二维数组
for(int i = 0;i < arr.length;i++){
for(int j = 0;j < arr[i].length;j++){
System.out.print(arr[i][j])
}
System.out.println()
}
- 二维数组元素的默认初始化值
- 外层数组元素:地址值
- 内层数组元素:同一维数组
- 只指定了外层,没有指定内层时:外层元素默认值为null,内层报错
- 二维数组的内存解析
注:引用类型的元素值要么是null,要么是地址值。
数组中涉及到的常见算法
1.数组元素的赋值
2.求 max、min、avg、sum等
3.数组的复制、翻转、查找(线性查找、二分法查找)
4.数组元素的排序算法
排序的分类:
- 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
- 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于
外部存储器。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。
十大内部排序算法
- 选择排序
直接选择排序、堆排序 - 交换排序
冒泡排序、快速排序 - 插入排序
直接插入排序、折半插入排序、Shell排序 - 归并排序
- 桶式排序
- 基数排序
冒泡排序
public class BubbleSortTest {
public static void main(String[] args) {
int[] arr = new int[]{43,32,76,-98,0,64,33,-21,99};
for (int i = 0;i < arr.length - 1;i++){
for (int j = 0;j < arr.length - 1 - i;j++){
if (arr[j] > arr[j + 1]){
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
for (int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
}
}
}
快速排序
public class QuickSort {
private static int count;
/**
* 测试
* @param args
*/
public static void main(String[] args) {
int[] num = {3,45,78,64,52,11,64,55,99,11,18};
System.out.println(arrayToString(num,"未排序"));
QuickSort(num,0,num.length-1);
System.out.println(arrayToString(num,"排序"));
System.out.println("数组个数:"+num.length);
System.out.println("循环次数:"+count);
}
/**
* 快速排序
* @param num 排序的数组
* @param left 数组的前针
* @param right 数组后针
*/
private static void QuickSort(int[] num, int left, int right) {
//如果left等于right,即数组只有一个元素,直接返回
if(left>=right) {
return;
}
//设置最左边的元素为基准值
int key=num[left];
//数组中比key小的放在左边,比key大的放在右边,key值下标为i
int i=left;
int j=right;
while(i<j){
//j向左移,直到遇到比key小的值
while(num[j]>=key && i<j){
j--;
}
//i向右移,直到遇到比key大的值
while(num[i]<=key && i<j){
i++;
}
//i和j指向的元素交换
if(i<j){
int temp=num[i];
num[i]=num[j];
num[j]=temp;
}
}
num[left]=num[i];
num[i]=key;
count++;
QuickSort(num,left,i-1);
QuickSort(num,i+1,right);
}
/**
* 将一个int类型数组转化为字符串
* @param arr
* @param flag
* @return
*/
private static String arrayToString(int[] arr,String flag) {
String str = "数组为("+flag+"):";
for(int a : arr) {
str += a + "\t";
}
return str;
}
}
Arrays工具类的使用(Object)
java.util.Arrays
类即为操作数组的工具类,包含了用来操作数组的各种方法。
常见的方法:
boolean equals(int[] a,int[] b)
:判断两个数组是否相等。String toString(int[] a)
:输出数组信息。void fill(int[] a,int val)
:将指定值填充到数组中。void sort(int[] a)
:对数组进行排序。int binarySearch(int[] a,int key)
:对排序后的数组进行二分法检索指定的值。
数组中的常见异常
- 数组角标越界异常:ArrayIndexOutOfBoundsException
- 空指针异常:NullPointerException
public class ArrayExceptionTset {
public static void main(String[] args) {
//角标越界
int[] arr = new int[]{1,2,3,4,5};
for (int i = 0;i <= arr.length;i++){
System.out.println(arr[i]);
}
System.out.println(arr[-2]);//python在一定区间可以为负
//空指针异常
//情况1.
int[] arr1 = new int[]{1,2,3};
arr1 = null;
System.out.println(arr1[0]);
//情况2
int[][] arr2 = new int[4][];
System.out.println(arr2[0][0]);
//情况3
String[] arr3 = new String[]{"AA","BB","CC"};
arr3[0] = null;
System.out.println(arr3[0].toString());
}
}
暂无评论内容