本篇文章重点对于Java的环境搭建以及Java的基础语法进行了知识点整理,对于一些琐碎的知识点进行了系统化总结,并且加入了我个人在学习过程中的一些理解。希望对大家的Java学习有所帮助。
(今天是2024年高考,祝高三学子们旗开得胜,高考加油!)
文章目录
一.Java开发环境搭建
常用的Windows组合键
-
win+D 回到桌面
-
win+E 打开资源管理器
-
win+R
-
win+L 锁屏
-
alt+tab 应用切换
常用的dos命令
- dir 列出当前目录和文件
- cls 清屏
- exit 退出dos
- 切换盘符 D: / C:
- 删除一个或者多个文件 del [文件名]
del *.txt
-
ipconfig 网卡信息
- ipconfig /all 更全
-
ping 网络连通
- ping [ip] -t 一直ping
- CTRL + C 强行终止
-
上下方向键翻出历史记录
-
mkdir 创建目录
-
rd 删除目录
- rd abc
-
ren 重命名
- ren abc xyz 将abc目录修改为xyz
-
cd 切换目录change directory
- cd [路径](包括相对路径和绝对路径)
- 绝对路径:在Windows当中以盘符开始的都是绝对路径
- 相对路径:以当前所在的位置为基准,从当前所在的位置开始找
- cd … 回到上级目录(在Windows里面两个点代表上级目录。一个点代表当前路径)
- cd / 回到根目录(正反斜杠都可以)
- 注意:tab 能够自动补全,切换可以一直按tab
-
在路径上方框子里面输入cmd能够直接进入该路径
-
新建并编辑文件 copy con [文件名],CTRL+Z保存
-
type [文件名] 查看文件内容
-
shutdown 关机
- shutdown -s -t 3600 一小时后自动关机(3600是秒)
批处理文件(多数为.bat)
c: //要先切换盘符
cd C:\root
del *.java
通用文本编辑快捷键
ctrl+c 复制
ctrl+v 粘贴
ctrl+x 剪切
ctrl+s 保存
ctrl+z 撤销
ctrl+y 重做
ctrl+a 全选
home 光标回到行首
end 光标回到行尾
ctrl + home 光标回到文章开始
ctrl + end 光标回到文章末尾
shift + home 或 end 选中一行
鼠标双击 (选中一个单词)
ctrl + shift + 右箭头或左箭头 (选中一个单词)
ctrl + f 查找
editplus配置(p5)
jdk安装
-
bin目录:存放命令
-
java命令:负责运行
-
javac:负责编译
-
-
lib:存放类库
- srczip:jdk源码
Java的加载与运行
-
编译阶段
-
源代码:.java
-
javac命令检查语法规则
-
字节码文件:.class
A.class:A是一个类,A是类名
-
-
运行阶段
-
java命令运行: java A (java后面跟的是A,不是A.class)
运行后jvm开始运行类加载器(classloader),找A.class字节码文件,装载进去,解释为二进制文件,进行底层交互
[外链图片转存中…(img-cPhugW45-1717761894783)]
-
-
注意点
jdk:Java工具箱(自带jre和jvm)
jre:Java运行环境
jvm:Java虚拟机
path环境变量
- path环境变量不是java的,隶属于windows操作系统
- path环境变量的作用是什么?
- 在path中有很多路径,路径和路径之间采用 分号 隔开
- 在DOS命令窗口中输入一个DOS命令之后,windows会先从当前路径下找这个命令,如果找不到,则会去环境变量PATH的路径中查找该命令,找到则执行,找不到,则报错。
- PATH环境变量实际上就是给windows操作系统指路的。
编写第一个Java程序
//class表示定义一个类
//helloworld是给这个类起个名
public class helloword{
//类体
//1.这是main方法,也叫做主方法
//2.main方法是jvm规定的固定写法,照抄就行了。这是程序的入口
//3.对于mian方法来说,能修改的就是args这个变量名
//4.public表示公开的
//5.static表示静态的
//6.void表示mian方法执行结束后不返回任何数据
//7.除定义变量之外,类体当中不能编写Java语句
public static void main(String[] args){
//方法体
//1.方法体当中由一行一行的Java语句组成
//2.任何一条Java语句必须以";"结尾
//3.方法体当中的代码是有执行顺序的,遵循自上而下的顺序依次逐行执行
System.out.println("Hello World!");
//这行代码的作用是将字符串"Hello World!"打印输出到控制台,并且println会换行(print不换行)
//\t是制表符(tab键)
}
//类体
}
编译第一个Java程序
- 使用javac命令来编译。首先确保javac命令能用。
- javac命令怎么用,语法是什么?
- javac java源文件的路径
- javac java源文件的相对路径
- javac java源文件的绝对路径
- javac *.java
运行第一个Java程序
-
使用java命令来运行程序,首先确保java命令可以用。
-
java命令怎么用?语法格式是什么?
- java 类名
- 切记切记切记~!!!!!!!!! java命令后面跟的不是文件路径。java命令后面跟的是类名
-
什么是类名?
- A.class,类名是A
- HelloWorld.class,类名是HelloWorld
- Test.class,类名是:Test
-
这里先死记硬背,后面就明白了。要使用java命令,首先DOS命令窗口中的当前路径必须切换到class文件所在的位置。
掌握环境变量CLASSPATH
-
classpath环境变量是隶属于Java语言的。不是windows操作系统的。和PATH环境变量完全不同。
-
classpath环境变量是给classloader(类加载器)指路的。
-
java A。执行后。先启动JVM,JVM启动classloader,classloader去硬盘上通过classpath找A.class文件。找到则执行,找不到则报错。
-
如果classpath没有配置的话,默认从当前路径下找class字节码文件。
-
如果classpath配置了,例如配置到桌面上了:C:\Users\Administrator\Desktop,那么classloader以后就只会去桌面上找字节码文件了,不再从当前路径下找了。
-
注意,如果classpath配置为:classpath=.;C:\Users\Administrator\Desktop 是什么意思呢?
- 先让类加载器从当前路径下找,如果找不到的话,去C:\Users\Administrator\Desktop找。
-
但是对于目前来说,我们还没有必要这样配置。所以目前classpath大家是可以不配置的。
关于编译时的乱码问题
-
当java源文件中有中文时,采用老杜给的editplus工具写代码,最后会出现中文乱码问题,为什么?
- editplus默认是简体中文GBK。
- java21的javac编译器采用的是UTF-8的编码方式进行编译。
- 编码不一致,所以乱码了。
-
怎么解决?
- 第一种方案:
- javac -encoding GBK HelloWorld2.java
- 第二种方案:
- 将editplus的字符集修改为UTF-8
- 将editplus的字符集修改为UTF-8
- 第一种方案:
-
不管哪一种解决方案,都是让两边的字符编码方式一致。
java中的三种注释
// 单行注释
// 单行注释
// 单行注释
// 单行注释
/*
多行注释
多行注释
*/
/**
* javadoc注释,可以给javadoc命令解析提取并生成帮助文档
* @author dujubin
* @version 1.0
* @since 1.0
*/
使用以下命令可以提取生成帮助文档:
javadoc -d docs -author -version -encoding utf-8 HelloWorld.java
public class与class的区别
- 一个Java源文件中可以定义多个class
- 编译之后,一个class就会对应生成一个class字节码文件
- 如果一个类是public的,类名必须和源文件名保持一致。
- public的类可以没有。如果有的话,也只能有一个。
- 每个类中都可以编写入口main方法。想执行X类的main方法怎么办?java X
- 这里只是测试一下语法,在实际的开发中,对于一个软件来说,一般入口只有1个。
二.Java基础语法
标识符
-
程序员有权利自己命名的单词都叫标识符,可以标识变量/方法/类/包
-
标识符的命名规则和规范
-
规则(语法级别)
-
字母、数字、下划线、美元符号,不能含有其他字符
(这里的“字母”代表的是任何一个国家的文字,Java是采用的Unicode编码,支持全球任何一个国家的语言)
-
标识符不能以数字开头
-
标识符严格区分大小写
-
关键字不能做标识符(紫色显示的,如public,class)
-
标识符理论上没有长度限制,但是最好不要太长
public class IdentifierTest01{ public static void main(String[] args){ //定义一个变量,用来存储一个人的年龄 //age是一个变量名,是一个标识符 int age = 20; int age_ = 20; int $_age = 20; int $_age123 = 50; int 年龄 = 20; int a = 100; int A = 100; } } //学生类是一个标识符 class 学生类{ }
-
-
规范(约定俗成)
- 见名知意
- 遵循驼峰式命名方式。StudentService,BankService…
- 类名,接口名:首字母大写,后面每个单词首字母大写。StudentService,BankService…
- 变量名,方法名:首字母小写,后面每个单词首字母大写。doSome,productPrice…
- 常量名:全部大写,每个单词之间采用“_”分隔。LOGIN_ERROR,LOGIN_SUCCESS…
- 包名:全部小写。powernode…
-
关键字
-
在Java语言中具有特殊含义的单词叫做关键字,每个关键字都已经被Java语言本身占用了,不能用作标识符
-
所有的关键字都是小写(50个,有两个保留字goto,const也不能用)
字面量
-
**程序中的的数据就是字面量。**字面量是Java中最基本的表达式,无需转换,直接使用
-
字面量包括那些类型
整数型
浮点型
布尔型
字符型
字符串型
public class ConstTest01 {
public static void main(String[] args){
//整数型的字面量
System.out.println(10);
System.out.println(-100);
//浮点型
System.out.println(3.14);
//布尔型
System.out.println(true);
System.out.println(false);
//字符型(单个字符)
//所有字符型字面量必须使用单引号括起来
System.out.println('A');
System.out.println('中');
//System.out.println('AB');编译报错
//字符串型
//所有字符串型字面量必须使用双引号括起来
System.out.println("Hello World!");
System.out.println("中文输入");
System.out.println("A");
System.out.println("10");
System.out.println(10);//二者区别
System.out.println("true");
System.out.println(true);//二者区别
}
}
加号运算符
- +的两个作用
- 求和:两边都是数字
- 字符串拼接:+两边只要有一个是字符串,一定会做字符串拼接工作,并且拼接完之后的结果还是一个字符串
- 一个表达式当中出现多个+,如果没有小括号,遵循从左到右
public class PlusTest01{
public static void main(String[] args){
//求和
System.out.println(10 + 20);//30
//字符串拼接
System.out.println("10" + 20);//"1020"
//第一个 + 是求和
//第二个 + 是字符串拼接
System.out.println(10 + 20 + "30");//"3030"
//添加了小括号优先级比较高
//这两个+都是字符串拼接
System.out.println(10 + (20 + "30"));//102030
System.out.println("10" + 20 + 30);//102030
System.out.println("10" + (20 + 30));//1050
}
}
变量
概述
-
变量是内存中的一块空间。是计算机中存储数据的最基本单元。
变量是用来解决数据存储问题的。
先把数据存储起来,后续的程序需要使用的时候,可以从变量中取来用
-
三要素:
-
数据类型(决定空间大小):int,double,String…
-
变量名
-
值
注意:
数据类型是决定空间和大小的
数据类型 和 值的数据类型要一致
-
变量的声明、赋值和访问
-
声明语法格式
数据类型 变量名;
int 整数型
double 浮点型
String 字符串型
…
-
赋值的语法格式
变量名 = 变量值;
-
访问怎么做?(包括两种情况:一种是读,一种是修改)
- 读:System.out.println(变量名);
- 修改:变量名 = 变量值;
public class VarTest01{
public static void main(String[] args){
int age;//声明
age = 20;//赋值
//读
System.out.println("年龄=" + age);
//改(重新赋值)
age = 30;
System.out.println("年龄=" + age);
//age = "50";String无法转换成int
double Π = 3.14;
System.out.println("圆周率:" + Π);
//声明和赋值可以一起完成
String name = "jack";
System.out.println("name:" + name);
}
}
变量的作用
- 便于代码的维护
- 增强代码的可读性
public class VarTest02{
public static void mian(String[] args){
//修改只要改num就可以了
int num = 100;
System.out.println(num + 456);
System.out.println(num + 123);
//需求:计算半径是10.0的圆的面积
//不用变量
System.out.println(3.14 * 10.0 * 10.0);
//使用变量
double Π = 3.14;
double r = 10.0;
System.out.println(Π * r * r);
}
}
变量使用的小细节
-
变量必须先声明,再赋值,才能访问
-
方法体中的代码代码自上而下,先访问再赋值肯定是不行的
-
一行代码上可以同时声明多个变量
int a,b,c = 300; //声明了a,b,c。a,b没赋值,c赋值300 int a = 500,b = 600,c = 700;
-
在一个作用域中,变量名不能重名,可以重新赋值
作用域就是有效范围。在Java中,一个{}就是一个作用域
int i = 100; int i = 200;//错误 int i = 100; i = 200;//正确
变量的作用域
在Java程序中通常一个{}就是一个作用域
记住一句话:出了大括号就不认识了
public class VarTest04{
public static void main(String[] args){
//age是main方法声明的,所以作用域是整个main方法
int age = 20;
System.out.println("age = " + age);
int num = 100;
if(num > 50){
int i = 666;
System.out.println("i = "+ (i + age));
//这个i只在这个打括号里面起作用
}
}
//另一个方法
public static void doSome(){
//错误:找不到符号
System.out.println("age = " + age);
}
}
变量的分类
- 局部变量
- 成员变量
- 静态变量
- 实例变量
public class VarTest05{
public static void mian(String[] args){
//凡是在方法体当中定义的变量,一定是局部变量
//局部变量只在当前方法体中有效
int a = 100;
}
//在类体当中定义的变量叫做成员变量
//实例变量
int b = 200;
//静态变量
static int c = 300;
}
进制
二进制
二进制 | 0 | 1 | 10 | 11 | 100 | 101 | 110 | 111 | 1000 | 1001 | 1010 |
---|---|---|---|---|---|---|---|---|---|---|---|
十进制 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
权值
1,2,4,8就是权值(20,21,22,23)
二进制与十进制的转换
-
十进制转二进制:除2取余,一直到商0为止,最后将所有的余数逆输出
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b6f6ca55826a4095b767b1f0c2cb30cc.png)public class BinaryTest01{ public static void mian(String[] args){ //输出75,0b后面看作是二进制,二进制的字面量以0b开头 System.out.println(0b1001011) } }
-
二进制转十进制:每一位与权数相乘,最后求和
八进制和十六进制
八进制:满8进1
-
Java中规定,以0开始的字面量是一个八进制的字面量
System.out.println(0211);
-
1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20
-
与十进制的转换:和二进制一样
-
十转八:除8取余,逆序输出
-
八转十:先平方后求和
-
十六进制
-
Java中规定,以0x开始的字面量是一个十六进制的字面量
System.out.println(0x146);//326
-
1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
-
转换(和之前的一样)
-
10转16
-
16转10
-
进制总结和补充
//十进制
System.out.println(10);//10
//二进制
System.out.println(0b10);//2
//八进制
System.out.println(010);//8
//十六进制
System.out.println(0x10);//16
-
二进制和十六进制转换:四个四个转,不足四位左侧补0
1011 1111 = bf 0xb1e2 = 1011 0001 1110 0010
原码反码补码
byte与bit
-
byte(字节):八个二进制位就是一个字节
-
bit(比特):一个二进制位就是一个比特
-
二者关系:1 byte = 8 bit
-
在计算机中,通常以字节(byte)为最小单位进行存储和传输,而比特(bit)则是用来表示数据的最小单位
-
1KB = 1024 byte
1MB = 1024 KB
1GB = 1024 MB
1 TB = 1024 GB
原码反码补码:是计算机二进制的三种表现形式,计算机底层存的是补码
正数的原码反码补码
- 正数的原码反码补码都是相同的
- 127的原码反码补码是 0111 1111 (128-1)
负数的原码反码补码
-
原码:将绝对值转换为二进制后,最高位改为1(最高位是符号位,1代表负数,0代表正数)
//-6的原码 6 = 0000 0110 -6 = 1000 0110 20 = 0001 0100 -20 = 1001 0100
-
反码(原则是:以原码作为参考,符号位不变,其他位取反)
-20 = 1110 1011
-
补码(原则是:以反码作为参考,符号位不变,加1)
-20 = 1110 1100
-
补码转原码:符号位不变,取反再加1
-
特殊:-128 原码和补码相同
128 = 1000 0000 -128 = 1000 0000 //原码 -128 = 1111 1111 //反码 -128 = 1000 0000 //补码
-
1byte的取值范围:1000 0000 ~ 0111 111(-128~127)共256种情况
数据类型
概述
- 分类(如下图)
要记的:
-
关于八种基本数据类型的默认值:(记住)
byte short int long float double boolean char 0 0 0 0L 0.0F 0.0 false \u0000 -
所有的引用数据类型,默认值是:null
-
语法规则:在Java中,成员变量如果没有手动赋值的话,系统会赋默认值
public class DefaultValueTest{ static int k; static boolean sex; static String name; public static void main(String[] args){ int i = 100; //局部变量必须要赋值 System.out.println(i); // System.out.println("k = " + k); //输出0 System.out.println("sex = " + sex); //输出false System.out.println("name = " + name); //输出null } }
整数型(byte,short,int,long)
四种表现形式
int a = 10; //10
int b = 0b10; //2
int c = 010; //8
int d = 0x10; //16
自动类型转换
- Java中任何一个“整数型字面量”都会默认被当做int类型来处理
- Java中允许小容量的数据直接赋值给大容量的变量
byte < short < int < long < float < double
- 如果在整数型字面量后面添加 L 或者 l ,那么这个整数型字面量被当做long类型来处理了(建议使用大写L,否则容易跟1混淆)
//= 是赋值运算符,=右边先执行
//右边先执行,默认给100当做int型,分配四个字节。a变量正好也是4个字节,所以不存在类型转换
int a = 100;
//右边先执行,默认给100当做int型,分配四个字节,b变量为8个字节,小的容量自动转换为大的容量。这个被称为自动类型转换
long b = 100;
//100L一上来就是分配8个字节。所以这个代码不存在类型转换
long c = 100L;
//2147483647被当做int处理,4个字节,存在类型转换
long d = 2147483647;
//错误:整数太大(不是long存不下)
//原因是:2147483648默认被当做int来处理,分配4个字节
//解决方法:添加一个L long e = 2147483648L;
long e = 2147483648;
强制类型转换
- Java中大容量不能直接赋值给小容量(大容量是不能自动转换成小容量的)
long x = 1000L;
//错误:不兼容的类型:从long转换到int可能会有损失
int y = x;
- 大容量转换成小容量的时候,想让其编译通过的话,必须由程序员手动添加“强制类型转换符来操作”(有可能会精度损失)
long x = 1000L;
//强制类型转换
int y = (int)x;
long a = 55L;
int b = (int)a;
System.out.println("b =" + b); //55
//long 00000000 00000000 00000000 00000000 00000000 00000000 00110111
//int 00000000 00000000 00000000 00110111
//int将前面的直接去掉,输出还是55(正数的补码是它本身)
int k = 128;
byte e = (byte)k;
System.out.println("e = " + e); //-128
//int 00000000 00000000 00000000 10000000
//byte 10000000
// 10000000的补码为10000000,十进制为-128
int m = 129;
byte n = (byte)m;
System.out.println("n = " + n); //-127
//int 00000000 00000000 00000000 10000001
//byte 10000001
// 10000001的补码为11111111,十进制为-127
(特殊)请记住这个语法规则:当一个整数型字面量没有超出 byte 和 short 取值范围的时候,可以直接赋值给 byte 和 short 类型的变量。
public class IntTest04{
public static void mian(String[] args){
//可以直接赋值,不需要强制类型转换
byte b = 1;
byte a = 127;
//编译出错,128超出byte取值范围
byte c = 128;
//如果想编译通过,只能做强制类型转换
byte c = (byte)128;
System.out.println("c = " + c); //-128精度损失
}
}
//short取值范围-32768~32767
short s = 32767;
//编译报错,必须进行强制转换
//short s1 = 32768;
short s1 = (short)32768;
System.out.println(s1); //-32768精度损失
当两个int类型的数据进行运算之后,结果还是int类型
注意:多种数据类型在混合运算的时候,先各自转换成容量最大的,再做运算。
public class IntTest05{
public static void main(String[] args){
int a = 10;
int b = 3;
//应该是这样的结果:3.333333333333......
//但Java中不是,结果是:int类型的3
System.out.println(a / b); //输出结果为3
byte x = 10;
int y = 3;
long z = 100L;
//编译出错 X + y + z转换成了long类型
int result = x + y + z;
//修改
long result = x + y + z;
System.out.println(result);
}
}
编译器的小心思:byte和short混合运算的时候,各自先转换成int再做计算
byte + byte = int
byte + short = int
short + short = int
public class IntTest06{
public static class void main(String[] args){
short m = 10;
byte n = 10;
int result = m + n; //最后结果是int类型
System.out.println(result);
byte b = 10 / 3; //编译优化:编译阶段会直接算出来3,在class文件中时就已经是byte b = 3;了
System.out.println(b);
byte x = 10;
byte y = 3;
//编译报错,类型不兼容
byte c = x / y;编译阶段只知道结果是int类型,不知道具体的结果
//修改
int c = x / y;
//编译出错
byte e = 3;
byte f = 10 / e; //只要有一个变量在,就不会计算,只知道e是int
//第一种修改方式
int f = 10 / e;
//第二种修改方式
byte = (byte)(10 / e);
}
}
浮点型(float,double)
-
包括两个类型
float(4个字节):单精度,可以精确到7位小数
double(8个字节):双精度,可以精确到15位小数
-
double是常用的
-
浮点型的字面量默认都会被当做double类型来处理,如果想让其当做float类型来处理的话,需要在字面量后面添加F/f
public class FloatTest01{ public static void main(String[] args){ //不存在类型转换 double d = 3.14; //编译出错,3.14默认是double类型,大容量不能直接转换成小容量 float f = 3.14; //修改 //第一种方案:不存在类型转换 float f = 3.14F; //第二种方案:强制类型转换 float f = (float)3.14 } }
-
double精度要高
double x = 1.5656856894; //输出为1.5656856894 float y = 1.5656856894f; //输出为1.5656856(精度损失)
-
浮点型数据两种表现形式(整数型为四种进制)
-
十进制(实际开发中就是用它)
double x = 1.23;
double x =0.23;
double x =.23; //就是0.23
-
科学计数法
double x = 0.123E2; //0.123 * 10^2
double x =123.34E-2; //123.34 / 10^2
-
-
浮点型数据存储原理
-
一旦有浮点型数据参与运算得出的结果,一定不要用“==”与其他数字进行“相等比较”
主要原因是:任何浮点型数据,在计算机底层存储的都是它的近似值(仅限于浮点型)
public class DoubleTest05{ public static void main(String[] args){ double a = 6.9; double b = 3.0; double c = a / b; System.out.println("c = " + c); //c = 2.3000000000000003 if(c == 2.3){ System.out.println("相等"); //不输出 } //一般做法 if(c - 2.3 < 0.00000001){ System.out.println("相等"); } }
-
字符型(char)
char类型概述:
-
char类型是字符型
-
char类型占用2个字节
-
char类型取值范围:0~65535
char和short都是2个字节
char可以取到更大的正整数(short有负数)
char和short所能表示的数量是一样的
-
在java中,字符char类型的字面量必须使用单引号括起来:
‘A’,‘a’,‘中’
-
在Java中,char类型统一采用的字符编码方式:Unicode编码
-
在Java中,char可以存储一个汉字
-
char的默认值是:\u0000(\u后面数字默认为16进制编码)
public class CharTest01{
public static void main(String[] args){
char c1 = 'A';
char c2 = 'B';
char c3 = 'a';
char c4 = '中';
//错误:String无法转换成char,"中"为String类型,加了双引号
char c5 = "中";
//错误:char类型只能存储一个字
char c6 = 'ab';
//错误:空字符文字(不是空格)
char c7 = '';
}
}
8.当整数型字面量没有超出char的取值范围,可以直接将其赋值给char类型的变量,且会直接将这个整数当成ASCII码
当整数型字面量没有超出byte short char的范围,可以直接赋值给它们的变量
char c1 = 97; //当做ASCII码,输出a
char c2 = 65536; //报错
转义字符
\t: 表示制表符,相当于按下 Tab 键
\n: 表示换行符
“: 表示双引号(”)
‘: 表示单引号(’)
\: 表示反斜线(\)本身
\u:后面是一个16进制的数字,对应Unicode码
public class CharTest02{
public static void main(String[] args){
// 这是一个普通的t字符
char c1 = 't';
// 按说应该编译报错。因为看到的是一个字符串。不是字符。
// 但是编译通过了,说明这是1个字符。
// 这个字符叫做:制表符。tab
// \ 反斜杠在java语言中具有转义功能。把普通的t字符转义成了制表符tab。
char c2 = '\t';
System.out.println("abc" + c2 + "def");
// \n 换行符
System.out.print("hello\n");
System.out.print("world\n");
System.out.print("test\n\n\n\n\n\n");
// \"
// 需求:输出一个双引号到控制台。
//System.out.println("""); //编译报错
System.out.println("\"");
System.out.println("\"\"");
System.out.println('"');
// 需求:输出一个单引号到控制台
System.out.println("'");
// 编译错误
//System.out.println(''');
System.out.println('\'');
// 字符char只能是单个字符。
//System.out.println('\'\'');
// 需求:输出一个反斜杠到控制台。 \
//System.out.println("\"); // 编译错误
// 在java中两个 \\ ,最终转换完成之后是一个普通的 \ 字符。
System.out.println("\\");
//输出两个\
System.out.println("\\\\");
}
}
字符编码(在写转码工具:jsons.cn)
-
ASCII码(占用1个字节):包含了键盘上所有的键。程序员要记住以下几个(注意都是字符,0不是数字0,而是字符"0")
a A 0 97(b是98,以此类推) 65(B是66,以此类推) 48(1是49,以此类推) 乱码出现的原因:编码(Encoding)和解码(Decoding)用的不是同一套码表,但是ASCII码是计算机最基本的编码方式,其它编码方式兼容。
-
Lantin-1编码(ISO 8859-1):1个字节,支持256字符,向上兼容ASCII。表示欧洲语言。
-
ANSI编码:1个字节,两个ANSI能表示一个汉字。
-
Unicode编码(Java使用):16进制表示,占用2个或4个字节,可以表示所有语言(浪费空间,'a’采用一个字节就够了)
char c = '\u0041'; //'\u0041'是一个字符,表示A
-
UTF-8编码(web开发常用):基于Unicode编码的可变长度字符编码,使用1~4个字节来表示一个字符。
-
UTF-16编码:2或4个字节。
-
UTF-32编码:固定长度4个字节。
-
GB2312编码(小):2个字节表示一个汉字,是GBK编码的前身。
-
GBK(Guo Biao Ku)(中):2个字节。
-
GB18030编码(大)
-
Big5编码(大五码):2个字节,台湾地区用于表示繁体中文。
-
char类型变量定义有三种方式
char c = 'A'; //直接定义 char c = '\u0041'; //Unicode码 char c = 65; //ASCII码
-
char参与的运算
byte short char 在混合运算的时候,各自先转换成int再做运算
Systm.out.println('a' + 1); //98 char c = 'a' + 1; //98 System.out.println(c); //98的值赋给了c,输出b
布尔类型(boolean)
-
布尔型:boolean
- 在Java中,boolean值只有两个true false,没有0和1这一说(C语言是0和1)
- boolean类型主要用于:逻辑判断,条件判断等
public class BooleanTest01{ public static void main(String[] args){ //不兼容的类型:int无法转换为boolean //boolean flag = 1; boolean flag = true; boolean gender = false; if(gender){ System.out.println("男士"); }else{ System.out.println("女士"); } int a = 1000; int b = 200; System.out.println(a > b); //输出true if(a > b){ //a > b 是boolean类型 System.out.println(a + ">" + b); }else{ System.out.println(a + "<" + b); } } }
总结:基本数据类型转换规则
1.八种基本数据类型中除了boolean类型之外,剩下7个都是可以互相转换的。
2.小容量可以自动转换成大容量,称为自动类型转换,容量从小到大排序:
byte < short < int < long < float < double
char <
3.大容量不能自动转换成小容量,必须添加强制类型转换符,编译才能通过。但是运行时可能损失精度。
4.当整数型字面量没有超出byte short char的范围时,可以直接将其赋值给byte short char类型的变量。
5.byte short char混合运算时,各自先转换成int再做运算。
6.多种数据类型混合运算时,各自先转换成最大的容量,再做运算。
public class DataTypeHomework03{
public static void main(String[] args){
// 通过
short s = 100;
// 报错:大容量不能直接赋值给小容量
s = s - 99;
// 通过
byte b = 100;
// 报错
b = b + 1;
// 通过
char c = 'a';
// 通过
int i = 20;
// 通过
float f = .3F;
// 通过
double d = c + i + f;
// 通过
byte b1 = 11;
// 通过
short s1 = 22;
// 报错
short x = b1 + s1;
}
}
运算符
算数运算符
-
包括:
+:求和;字符串拼接;表示正数
-:相减;负数
*:乘积
/:商(除以)
%:取模(求余数)
取模公式:x - (x / y) * y
10 % 3 = -10 - (-10) / 3 * 3
= -10 - (-3) * 3
= -10 + 9
= -1
++:让变量自身加1
–:让变量自身减1
public class OperatorTest01{
public static void main(String[] args){
int a = 10;
int b = +3;
int c = a + b;
System.out.println(a + "+" + b + "=" + c);
int d = 10;
int e = -3;
int f = d - e;
System.out.println(d + "-(" + e + ")=" + f);
/*
int x = 10;
int y = 3;
System.out.println(x + "*" + y + "=" + x * y);
*/
int m = 10;
int n = 3;
System.out.println(m + "/" + n + "=" + m / n);
int x = 10;
int y = 3;
System.out.println(x % y); // 1
// x - x / y * y
// -10 - (-10) / 3 * 3
// -10 - (-3) * 3
// -10 - (-9)
// -10 + 9
// -1
x = -10;
System.out.println(x % y); // -1
// x - x / y * y
// 10 - 10 / (-3) * (-3)
// 10 - (-3) * (-3)
// 10 - 9
// 1
x = 10;
y = -3;
System.out.println(x % y); // 1
int i = 10;
// 一元运算符
i++;
System.out.println("i = " + i); // 11
i = 100;
i--;
System.out.println("i = " + i); // 99
}
}
-
++ 自加1;-- 自减1
-
可以出现在变量前,也可以出现在变量后
++i;
i++;
像++这种运算符,只有一边有操作数,我们把这种运算符称为:一元运算符
a + b,这里的+两边都有操作数,我们把这种运算符称为:二元运算符
-
无论++出现在变量前,还是变量后,执行结束后,都会让变量中的值自加一
int i = 10; i++; ++i;
-
当++出现在变量后:先做赋值运算,后自加1
int k = 10; int f = k++; //先将k中的值赋值给f,后自加1 System.out.println(k); //11 System.out.println(f); //10
-
当++出现在变量前:先做自加1运算,然后再做赋值运算
int e = 100; int x = ++k; //e先自加1,后赋值给x System.out.println(e); //101 System.out.println(x); //101
//注意!!! int y = 100; System.out.println(y++); //100 System.out.println(y); //101 //根据源码, y++ 传给了源码中的x //实现原理:int x = y++ //public void println(int x){ int z = 100; System.out.println(++z); //101
-
练习题
- 经典面试题(实际开发中用不上)
public class OpeartorHomework03{ public static void mian(String[] args){ int i = 10; i = i++; System.out.println(i); //10 } }
-
从键盘上接收一个整数三位数,请分别输出它的个位、十位、百位
public class OperatorHomework04{ public static void main(String[] args){ java.util.Scanner scanner = new java.util.Scanner(System.in); System.out.print("请输入一个三位数:"); int num = Scanner.nextInt(); System.out.println("个位:" + num % 10); System.out.println("十位:" + num / 10 % 10); System.out.println("百位:" + num / 100); } }
-
681分钟是多少个小时+多少分钟
int total = 681; int h = 681 / 60; int m = 681 % 60;
-
(补充)栈数据结构(Stack)
- 栈结构特点:
- 先进后出
- 后进先出
- 相关术语
- 入栈、压栈、push
- 出栈、弹栈、pop
- 栈帧
- 栈顶、栈底
(补充)字节码解读
-
查看以下程序的字节码,命令是:
javap -c ReadClass01.class
-
举个例子:
public class ReadClass01{ public static void main(String[] args){ int i = 10; } }
//字节码文件 Compiled from "ReadClass01.java" public class ReadClass01 { public ReadClass01(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: return }
-
在Java语言中,任何一个方法执行时,都会专门为这个方法分配所属的内存空间。供这个方法使用。每个方法都有自己独立的内存空间,这个内存空间中有两块比较重要的内存空间:
一块叫做:局部变量表(存储局部变量的)
另一块叫做:操作数栈(存储程序运行过程中参与运算的数据)
-
重点要解读的字节码是
bipush 10 :将10这个字面量压入操作数栈当中
istore_1 :将操作数栈顶元素弹出,然后将其存储到局部变量表的1号槽位上。
-
-
例2
public class ReadClass02{ public static void main(String[] args){ int i = 10; int j = i; } }
Compiled from "ReadClass02.java"
public class ReadClass02 {
public ReadClass02();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 10
2: istore_1
3: iload_1
4: istore_2
5: return
}
iload_1 :将局部变量表1号槽位上的数据复制一份,压入操作数栈
istore_2 :将操作数栈元素弹出,存储到局部变量表的2号槽位上
-
例3
public class ReadClass03{ public static void main(String[] args){ int i = 10; int j = i; j++; } }
Compiled from "ReadClass03.java" public class ReadClass03 { public ReadClass03(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: iload_1 4: istore_2 5: iinc 2, 1 8: return }
iinc 2, 1 :将局部变量表2号槽位上的值加1
-
例4
public class ReadClass04{ public static void main(String[] args){ int i = 10; int j = ++i; } } /* Compiled from "ReadClass04.java" public class ReadClass04 { public ReadClass04(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: iinc 1, 1 6: iload_1 7: istore_2 8: return } */ class ReadClass05{ public static void main(String[] args){ int i = 10; int j = i++; } } /* class ReadClass05 { ReadClass05(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: iload_1 4: iinc 1, 1 7: istore_2 8: return } */
关系运算符(又叫比较运算符)
- 包括:>、>=、<、<=、==、!=
- 所有关系运算符的运算结果都是布尔型,不是true,就是false
逻辑运算符
-
包括:
& 逻辑与(并且):全真才为真 5 > 1 & 5 >4 true
| 逻辑或(或者):有一真结果即为true
^ 逻辑异或:左右不一样,结果就是true(true+false)
! 逻辑非:结果取反(!false = true)
&& 短路与(并且):和逻辑与运算结果相同,只不过存在短路现象。效率比&更高,大多数情况下使用&&(左边是false时发生短路现象)
int x = 99; int y = 100; System.out.println(x > y & x > ++y); //不管左边是真是假,右边一定会执行 System.out.println("y = " + y); //101 int x = 99; int y = 100; System.out.println(x > y && x > ++y); //左边即可判断出值,右边不执行 System.out.println("y = " + y); //100
|| 短路或(或者):原理与&&相同(左边是true时发生短路现象),优先使用||
-
特点:逻辑运算符两边操作数要求是布尔类型
并且最终运算结果也是一个布尔类型
public class OperatorTest04{
public static void main(String[] args){
int a = 100;
int b = 99;
System.out.println(a > b & a > ++b); //false
}
}
按位运算符(操作的都是补码)
注意:按位运算符的操作数要求必须是整数,否则会出现编译错误
左移 <<
-
将二进制数左移n位,相当于将数值乘于2的n次方
-
左移运算符不会改变操作数的符号。左移后,右补0
-
左移运算符会对溢出进行截断
-
注意:任何位运算符,操作的都是补码
/*
原码: 00000000 00000000 00000000 00000001
反码: 00000000 00000000 00000000 00000001
补码: 00000000 00000000 00000000 00000001
左移3位: (000)00000 00000000 00000000 00000001000 (补码)
*/
int a = 1;
System.out.println(a << 3); //8 (1 * 2的3次方)
/*
原码: 00000000 00000000 00000000 10000000
反码: 00000000 00000000 00000000 10000000
补码: 00000000 00000000 00000000 10000000
左移2位 (00)00000000 00000000 00000100 00000000
*/
int b =128;
System.out.println(b << 2); //128 * 2^2 = 512
/*
原码: 10000000 00000000 00000000 01100100
反码: 11111111 11111111 11111111 10011011
补码: 11111111 11111111 11111111 10011100
左移2位: 111111 11111111 11111111 1001110000(补码)
左移后的原码:100000 00000000 00000000 0110010000 (-400 = -100 * 2^2)
*/
int c = -100;
System.out.println(c << 2);
//经典面试题:怎么让2快速变成8?
int x = 2;
System.out.println(x << 2);
右移 >>
-
将二进制数右移n位,相当于将数值除以2的n次方
-
右移运算符对正数、负数和0的处理方式不同
对于正数,符号位不变,右移时左补0
对于负数,符号位不变,右移时左补1
对于0,右移运算符操作后结果仍为0
-
右移运算符会对溢出进行截断
/* 原码: 00000000 00000000 00000000 00000001 反码: 00000000 00000000 00000000 00000001 补码: 00000000 00000000 00000000 00000001 右移1位: 00000000 00000000 00000000 00000000 */ int a = 1; System.out.println(a >> 1); //0 /* 原码: 00000000 00000000 00000000 10000000 反码: 00000000 00000000 00000000 10000000 补码: 00000000 00000000 00000000 10000000 右移4位: 00000000 00000000 00000000 00001000 */ int b = 128; System.out.println(b >> 4); //8 /* 原码: 10000000 00000000 00000000 10000000 反码: 11111111 11111111 11111111 01111111 补码: 11111111 11111111 11111111 10000000 右移4位: 111111111111 11111111 11111111 1000 右移后原码: 100000000000 00000000 00000000 1000(取反再加1) */ int b = -128; System.out.println(b >> 4); //-8
无符号右移 >>>
-
溢出后的截断。
-
无符号右移之后,最终的结果一定是0或者正整数。
-
无符号右移之后,左侧补0.(不管是正数还是负数,都是补0)
public class OperatorTest07{ public static void main(String[] args){ /* 原码:10000000 反码:11111111 补码: 10000000 00100000(无符号右移2位) */ byte b = -128; /* 为什么输出结果不是32? b >>> 2。 byte和int混合运算。会先将byte转换成int,再做运算。 int b = -128; 原码:10000000 00000000 00000000 10000000 反码:11111111 11111111 11111111 01111111 补码:11111111 11111111 11111111 10000000 右移:0011111111 11111111 11111111 100000(补码) */ System.out.println(b >>> 2); // 1073741792 System.out.println(0b00111111111111111111111111100000); // 1073741792 // 11100000(补码) // 10100000(原码) System.out.println((byte)(b >>> 2)); // -32 /* 原码:10000000 00000000 00000000 01011010 反码:11111111 11111111 11111111 10100101 补码:11111111 11111111 11111111 10100110 右移:00011111111 11111111 11111111 10100 */ int x = -90; System.out.println(x >>> 3); System.out.println(0b00011111111111111111111111110100); /* 00000000 00000000 00000000 01011010 00000000000 00000000 00000000 01011 */ int y = 90; System.out.println(y >>> 3); // 11 } }
按位与 & (区别逻辑运算符的方式:逻辑运算符左右两边都是布尔型,但是按位运算符是整数)
-
运行机制(有一个1结果才为1)
1 & 1 --> 1
1 & 0 --> 0
0 & 1 --> 0
0 & 0 --> 0
public class OperatorTest08{
public static void main(String[] args){
// 00100011
int a = 35;
// 00011010
int b = 26;
/*
00100011
& 00011010
---------------
00000010
*/
System.out.println(a & b); // 2
/*
怎么判断一个数字是否为奇数?
法1:对2取模,结果!=0,为奇数
法2:与1按位与,结果是1,为奇数(只有第一位是奇数1)
*/
int num = 35;
/*
00100011
& 00000001
----------------
00000001
*/
if((num & 1) == 1){ //注意运算符优先级问题
System.out.println(num + "是奇数");
}
}
}
按位或 |
-
运行机制:都为0才为0,否则结果为1
1 | 0 : 1
0 | 1 : 1
1 | 1 : 1
0 | 0 : 0
// 00100011 int a = 35; // 00011011 int b = 27; /* 00100011 | 00011011 -------------- 00111011 */ System.out.println(a | b); //59
-
具体应用:设置标志位
将0这个数字的二进制位低位第4个二进制位设置为1
int flag = 0; flag = flag | (1 << 3); System.out.println(flag); // 8
按位异或 ^
-
操作机制:不同为1,相同为0
1 ^ 1 : 0
0 ^ 0 : 0
1 ^ 0 : 1
0 ^ 1 : 1
-
具体应用:按位异或运算符具有自反性(加密解密)
a ^ b ^ b ==> a
//00001010
int a = 10;
//00000011
int b = 3;
/*
00001010
^ 00000011
--------------
00001001
*/
System.out.println(a ^ b); // 9
/*
00001001
^ 00000011
--------------
00001010
*/
System.out.println(a ^ b ^ b); // 10
int data = 2147483647; //原始数据
//对以上的data进行加密
//秘钥(私人的,只有我知道这个钥匙)
int key = 483;
//加密
int password = data ^ key;
System.out.println(password); //2147483164
//解密
int num = password ^ key;
System.out.println(a ^ b ^ b); //2147483647
按位取反 ~
-
运行机制
~1 : 0
~0 : 1
// 00000000 00000000 00000000 00001010 int a = 10; // 11111111 11111111 11111111 11110101(补码) // 10000000 00000000 00000000 00001011(原码)-11 System.out.println(~a); // -11
-
具体应用:位清除操作,将某个二进制位清0
int value = 0b1111111111; //将低位第4个清0
int flag = (1 << 3);
// 00000000 00000000 00000000 00001000
// 11111111 11111111 11111111 11110111
//&00000000 00000000 00000011 11111111
//--------------------------------------
// 00000000 00000000 00000011 11110111
value = value & (~flag);
System.out.println(value);
赋值运算符
-
基本的赋值运算符:
=
-
扩展的赋值运算符:(不能使用空格)
+=
-=
*=
/=
以下的很少用:>>=、<<=、>>>=、&=、|=、^=、~=
//基本的赋值运算符 int i = 10; i = 20; //重新赋值 //+=累加 int k = 100; k += 200; //300。等同于k = k + 200; int x = 10; x *= 3; // 30 x = 10; x /= 3; // 3 x = 10; x %= 3; // 1 x -= 100; // -99
-
扩展类的赋值运算符都会自动强转(看原来的类型)
对于扩展的赋值运算符来说,永远都不会改变运算结果类型,哪怕精度损失
byte m = 10; //错误:不兼容的类型 m = m + 10; m += 20; //底层实际上对应的是:m = (byte)(m + 100);
条件运算符
语法格式
布尔表达式 ? 表达式1 : 表达式2
运算原理
为true执行1,false执行2
注意:常见的错误
10;
‘男’;
……都不是Java语句
sex ? '男' : '女'; //编译不通过
System.out.println(sex ? '男' : '女'); //可以通过
char c1 = sex ? '男' : "女"; //类型不兼容,c1是char,不能接收String
char c = sex ? '男' : '女'; //可以通过
System.out.println(sex ? '男' : "女"); //可以通过,println可以输出任何类型
例
//使用三目运算符筛选两个数字中较大的
int a = 100;
int b = 200;
System.out.println(a > b ? a : b);
运算符作业题
-
编写 Java 代码,输入一个半径值,计算圆的面积和周长,并输出结果。注意:圆的面积公式为 π * r * r,周长公式为 2 * π * r,其中 π 取 3.14
public class Test01{ public static void main(String[] args){ java.util.Scanner s = new java.util.Scanner(System.in); System.out.println("请输入一个半径值:"); int r = s.nextInt(); System.out.println("圆的面积为:" + (3.14 * r * r)); System.out.println("圆的周长为:" + (2 * 3.14 * r)); } }
-
假设变量 a、b、c 分别为 6、9、10,请编写 Java 代码输出它们的最大值
public class Test02{ public static void main(String[] args){ int a = 6; int b = 9; int c = 10; int d = a > b ? a : b; int e = d > c ? d : c; //法2:int max = a > b ? (a > c ? a : c) : (b > c ? b : c); System.out.println(e); } }
-
假设变量 n 为整数,请编写 Java 代码判断它是不是一个偶数
public class Test03{ public static void main(String[] args){ java.util.Scanner s = new java.util.Scanner(System.in); System.out.println("请输入一个整数:"); int n = s.nextInt(); System.out.println(((n & 1) == 1) ? n + "不是偶数" : n + "是偶数"); } }
-
编写 Java 代码,输入三个整数,分别判断第一个数是否大于 0,第二个数是否小于 10,第三个数是否是偶数。如果都满足条件,则输出“三个条件都满足”,否则输出“不满足所有条件”
public class Test04{ public static void main(String[] args){ java.util.Scanner s = new java.util.Scanner(System.in); System.out.println("请输入3个整数:"); int a = s.nextInt(); int b = s.nextInt(); int c = s.nextInt(); System.out.println(((a > 0) && (b < 10) && (c & 1 == 0)) ? "三个条件都满足" : "不满足所有条件"); } }
-
编写 Java 代码,输入一个年份,判断它是否是闰年。若该年份能被 4 整除且不能被 100 整除,或者能被 400 整除,则该年份为闰年。输出结果为“该年是闰年”或“该年不是闰年”
public class Test05{ public static void main(String[] args){ java.util.Scanner s = new java.util.Scanner(System.in); System.out.println("请输入一个年份:"); int year = s.nextInt(); System.out.println(((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)) ? "改年是闰年" : "该年不是闰年"); } }
补充:接收用户键盘输入(暂时死记硬背,四个方法)
public class KeyInput{
public static void main(String[] args){
//创建一个键盘扫描器对象
//以下代码中s是变量名,也可以叫做键盘扫描器
java.util.Scanner s = new java.util.Scanner(System.in);
System.out.println("请输入一个数字:");
//程序执行到这里就会停下来,键盘输入、回车后继续运行
//nextInt()方法只能接收整数数字,输入其他的字符串会报错
int num = s.nextInt();
System.out.println("您输入的数字是:" + num);
System.out.println("请输入一个浮点型数据:");
double num2 = s.nextDouble(); //浮点型数据的接收
System.out.println("您输入的浮点型数据是:" + num2);
System.out.println("请输入一个字符串:");
//从键盘上接收一个字符串,但是接收的是第一个空格之前的内容
//输入jackson,输出jackson。输入jack son,输出jack。
String username = s.next();
System.out.println("您输入的字符串是:" + username);
System.out.println("请输入一个字符串:");
//从键盘上接收一个字符串,但是接收的是第一个换行符(\n)之前的内容。(接收一行)
s.nextLine(); //第一次调用这个方法,读取缓存中的回车符(\r)
String name = s.nextline();
System.out.println("您输入的字符串是:" + name);
}
}
//求和运算
public class Compute{
public static void main(String[] args){
//创建键盘扫描器对象
java.util.Scanner s = new java.util.Scanner(System.in);
//输出欢迎信息
System.out.println("欢迎使用计算器1.0版本!我现在只能帮你进行加法运算");
System.out.println("请输入第一个数字:");
int num1 = s.nextInt();
System.out.println("请输入第二个数字:");
int num2 = s.nextInt();
int result = num1 + num2;
System.out.println("num1 + "+" + num2 "=" + result");
}
}
-
第二种写法
import java.util.Scanner; punlic class KeyInput{ Scanner s = new Scanner(System.in); int a = s.nextInt(); }
控制语句
分支语句
if语句
-
第一种写法
if(布尔表达式){
分支语句;
}
注意:如果分支中只有一条Java语句,大括号可以省略
- 例子
1.编写一个程序,输入一个人的年龄age,如果他的年龄大于等于18岁,则输出"你已经成年了",否则不输出任何东西。
import java.util.Scanner; public class IfTest01{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入年龄:"); int age = s.nextInt(); if(age > 18){ System.out.println("你已经成年了"); } } }
2.编写一个程序,输入一个学生的分数score(百分制),如果学生的分数大于等于60,则输出"你已经及格了",否则不输出任何东西。
import java.util.Scanner; public class IfTest02{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入分数:"); int score = s.nextInt(); if(score >= 60){ System.out.println("你已经及格了"); } } }
3.编写一个程序,输入一个学生的分数score(百分制),如果学生的分数大于等于60,则输出"你已经及格了",如果学生的分数小于60,则输出“很抱歉,你不及格”。
import java.util.Scanner; public class IfTest03{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入分数:"); double score = s.nextDouble(); if(score >= 60){ System.out.println("你已经及格了"); } if(score < 60){ System.out.println("很抱歉,你不及格"); } } } //以上程序的效率比较低,判断了两次 //像这种只有两种情况的,建议使用if else语句
-
第二种写法
if(布尔表达式){
分支1;
}else{
分支2;
}
注意:一条语句大括号可以省略
-
例子
-
编写一个程序,输入一个数字num,判断它是否为7的倍数。如果是,则输出"num是7的倍数",否则输出"num不是7的倍数"。
import java.util.Scanner; public class IfTest04{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入一个数字:"); int num = s.nextInt(); if(num % 7 == 0){ System.out.println(num + "是7的倍数"); }else{ System.out.println(num + "不是7的倍数"); } } }
-
编写一个程序,输入一个数字num,判断它是否同时为3的倍数和5的倍数。如果是,则输出"num既是3的倍数又是5的倍数",否则输出"num不同时是3的倍数和5的倍数"。
import java.util.Scanner; public class IfTest05{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入一个数字:"); int num = s.nextInt(); if((num % 3 == 0) && (num % 5 == 0)){ System.out.println(num + "既是3的倍数又是5的倍数"); }else{ System.out.println(num + "不同时是3的倍数和5的倍数"); } } }
-
编写程序模拟用户登录,用户名和密码正确则登录成功,反之则登录失败。
注意:字符串的比较不能使用“==”,必须手动调用equals方法来进行比较(先死记硬背)
if(name == “admin”){} 这种写法是不专业的,错误的,不建议的。
应该这样写:
if(name.equals(“admin”)){}
import java.util.Scanner; public class IfTest06{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入用户名:"); String name = s.next(); System.out.println("请输入密码:"); String passwd = s.next(); if((name.equals("admin")) && (passwd.equals("abc123"))){ System.out.println("登录成功。欢迎进入系统," + name); }else{ System.out.println("用户名不存在或者密码错误,登录失败"); } } }
-
-
-
第三种写法(从上往下执行,只会执行一个分支,只要遇到true即执行,整个if结束,后面就不执行了)
if(布尔表达式){
分支1;
}else if(布尔表达式){
分支2;
}else if(布尔表达式){
分支3;
}
-
第四种写法
if(布尔表达式){
分支1;
}else if(布尔表达式){
分支2;
}else if(布尔表达式){
分支3;
}else{
分支4;
}
-
例子
1.编写一个程序,输入一个学生的分数score(百分制),根据成绩的不同输出不同的评价。如果学生的分数大于等于90分,则输出"你的成绩是优秀";如果分数大于等于80分但小于90分,则输出"你的成绩是良好";如果分数大于等于70分但小于80分,则输出"你的成绩是中等";如果分数大于等于60分但小于70分,则输出"你的成绩是及格";否则输出"你的成绩不及格"。
import java.util.Scanner; public class IfTest07{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.print("请输入您的考试成绩:"); double score = s.nextDouble(); // 百分制(如果输入的成绩小于0,或者大于100,认为不合法的成绩,程序直接退出。) if(score < 0 || score > 100){ System.out.println("对不起,您输入的成绩不合法!"); // 直接结束当前方法。 return; } // 程序如果能够执行到这里,说明成绩一定是合法的。 if(score >= 90){ 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){ System.out.println("你的成绩是优秀"); }else if(score >= 80){ System.out.println("你的成绩是良好"); }else if(score >= 70){ System.out.println("你的成绩是中等"); }else if(score >= 60){ System.out.println("你的成绩是及格"); }else{ System.out.println("你的成绩不及格"); } // 第二次改进 String str = "你的成绩不及格"; if(score >= 90){ str = "你的成绩是优秀"; }else if(score >= 80){ str = "你的成绩是良好"; }else if(score >= 70){ str = "你的成绩是中等"; }else if(score >= 60){ str = "你的成绩是及格"; } System.out.println(str); } }
2.编写一个程序,输入一个年份year和一个月份month,判断这个月份有多少天。判断方法如下:
-
如果month为1、3、5、7、8、10、12中的一个,输出"month有31天";
-
如果month为4、6、9、11中的一个,输出"month有30天";
-
如果month为2并且year为闰年,输出"month有29天";(如果一个年份能够被4整除但不能被100整除,或者能够被400整除,那么它就是闰年)
-
如果month为2并且year不是闰年,输出"month有28天"。
//我写的 import java.util.Scanner; public class IfTest08{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入一个年份:"); int year = s.nextInt(); System.out.println("请输入一个月份:"); int month = s.nextInt(); if(((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))){ if(month == 2){ System.out.println(month + "有29天"); }else{ System.out.println(month + "有28天"); } }else{ if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12){ System.out.println(month + "有31天"); }else if(month == 4 || month == 6 || month == 9 || month == 11){ System.out.println(month + "有30天"); } } } } //老杜写的 import java.util.Scanner; public class IfTest07{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请告诉我一个年份,以及一个月份,我可以告诉你这一年的这个月有多少天。"); System.out.print("请输入年份:"); int year = s.nextInt(); System.out.print("请输入月份:"); int month = s.nextInt(); if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12){ System.out.println(year + "年" + month + "月有31天"); }else if(month == 4 || month == 6 || month == 9 || month == 11){ System.out.println(year + "年" + month + "月有30天"); }else{ // 程序执行到这里,月份一定是2月。 // if语句嵌套是可以的。 if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){ System.out.println(year + "年" + month + "月有29天"); }else{ System.out.println(year + "年" + month + "月有28天"); } }
-
-
if语句的使用注意事项:
- 对于任何一个if语句来说,最多只能有一个分支执行。
- 分支中如果只有一条Java语句,大括号可以省略。
- 对于以上第2种和第4种,这两种写法是可以保证一定会有一个分支执行的。因为这两种写法都有else分支。
- 对于以上第1种和第3种,这两种写法可能会没有分支执行。在if选择结构中还可以嵌套别的选择结构或循环结构。
switch语句
-
完整格式
-
expression是一个表达式,执行完之后是一个值(int、枚举、String这三种类型)
当然,也可以把byte short char 放进去,会进行自动类型转换(char可以通过ASCII码转成int)
-
value也是int、枚举、String三种类型,判断expression是否与value相等
-
default可以不写,不是必须的,建议写上,这样程序更加健壮
-
break; 语句只要执行,switch就会结束
/* switch语句的完整格式: switch(表达式){ case 值1: 分支1; break; case 值2: 分支2; break; case 值3: 分支3; break; case 值4: 分支4; break; default: 默认分支; } 1. 表达式最后执行完是一个值,这个值要求类型是:int,枚举类型,字符串类型。 当然,也可以直接把byte short char放进去,会进行自动类型转换。 2. default语句不是必须的。建议写上,这样程序更加健壮。 3. break;语句只要执行,switch语句就会结束。 */ import java.util.Scanner; public class SwitchTest01{ public static void main(String[] args){ // 编译报错,long类型是不允许的。 /* long x = 100L; switch(x){} */ // 修改 long x = 100L; switch((int)x){} // byte可以自动转换成int类型。 byte b = 1; switch(b){} short s = 1; switch(s){} char c = 'a'; switch(c){} //String season = "春季"; //switch(season){} // 不支持boolean类型。 /* boolean sex = true; switch(sex){} */ //编写一个程序,根据输入的月份,输出该月份所属的季节 // 3 4 5 春季 // 6 7 8 夏季 // 9 10 11 秋季 // 12 1 2 冬季 Scanner scanner = new Scanner(System.in); System.out.print("请输入月份:"); int month = scanner.nextInt(); switch(month){ case 3: System.out.println("春季"); break; case 4: System.out.println("春季"); break; case 5: System.out.println("春季"); break; case 6: System.out.println("夏季"); break; case 7: System.out.println("夏季"); break; case 8: System.out.println("夏季"); break; case 9: System.out.println("秋季"); break; case 10: System.out.println("秋季"); break; case 11: System.out.println("秋季"); break; case 12: System.out.println("冬季"); break; case 1: System.out.println("冬季"); break; case 2: System.out.println("冬季"); break; } //case是可以合并的。 switch(month){ case 3: case 4: case 5: System.out.println("春季!"); break; case 6: case 7: case 8: System.out.println("夏季!"); break; case 9: case 10: case 11: System.out.println("秋季!"); break; case 12: case 1: case 2: System.out.println("冬季!"); break; } switch(month){ case 3: case 4: case 5: System.out.println("春季!"); break; case 6: case 7: case 8: System.out.println("夏季!"); break; case 9: case 10: case 11: System.out.println("秋季!"); break; case 12: case 1: case 2: System.out.println("冬季!"); break; default: System.out.println("您输入的月份不存在!"); } // break;语句缺少的话,可能会发生case穿透现象。 switch(month){ case 3: case 4: case 5: System.out.println("春季!"); case 6: case 7: case 8: System.out.println("夏季!"); case 9: case 10: case 11: System.out.println("秋季!"); break; case 12: case 1: case 2: System.out.println("冬季!"); break; default: System.out.println("您输入的月份不存在!"); } String season = "您输入的月份不存在!"; switch(month){ case 3: case 4: case 5: season = "春季!"; break; case 6: case 7: case 8: season = "夏季!"; break; case 9: case 10: case 11: season = "秋季!"; break; case 12: case 1: case 2: season = "冬季!"; break; } System.out.println(season); // 请在控制台接收输入:A B C D // 当A时,输出优秀 // 当B时,输出良好 // 当C时,输出及格 // 当D时,输出不及格 System.out.print("请输入等级:"); int grade = scanner.nextInt(); char ccc = 'A'; // case后面只能是字面量这样的值,不能使用变量。 switch(grade){ case 'A': //case ccc: System.out.println("优秀"); break; case 'B': System.out.println("良好"); break; case 'C': System.out.println("及格"); break; case 'D': System.out.println("不及格"); break; default: System.out.println("您输入的有误!"); } } }
/* 编写一个程序,根据输入的运算符符号,输出两个数的运算结果。 例如输入符号为“+”,则输出两个数的和;输入符号为“-”,则输出两个数的差,以此类推 */ import java.util.Scanner; public class SwitchTest02{ public static void main(String[] args){ System.out.println("欢迎使用简易版的计算器。"); Scanner s = new Scanner(System.in); System.out.print("请输入第一个数字:"); int num1 = s.nextInt(); System.out.print("请输入运算符 + - * / % 中的一个:"); String oper = s.next(); System.out.print("请输入第二个数字:"); int num2 = s.nextInt(); int result = 0; switch(oper){ case "+": result = num1 + num2; break; case "-": result = num1 - num2; break; case "*": result = num1 * num2; break; case "/": result = num1 / num2; break; case "%": result = num1 % num2; break; default : System.out.println("不支持此运算!"); return; } System.out.println(num1 + oper + num2 + "=" + result); } }
-
-
switch语句的小技巧
/* 编写一个程序,根据输入的成绩,输出对应的等级。例如 输入成绩为 90~100,则输出“优秀”; 输入成绩为 70~89,则输出“良好”, 输入成绩为 60~69,则输出“及格”, 输入成绩为 0~59,则输出“不及格”, 必须用switch,不能用if。 */ import java.util.Scanner; public class SwitchTest03{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入考试成绩:"); double score = s.nextDouble(); // 这是一个算法,经过这个算法之后,数就变少了。 int grade = (int)(score / 10); String result = "不及格"; switch(grade){ case 9:case 10: result = "优秀"; break; case 7: case 8: result = "良好"; break; case 6: result = "及格"; break; } System.out.println("result"); } }
-
switch语句使用注意事项:
-
switch 语句适用于判断固定值。if语句适用于判断范围或区间时使用。switch能做的if肯定能做,if能完成的switch不一定能完成。
-
JDK7之前,switch只支持int类型、枚举类型,在JDK7之后,增加了对字符串类型的支持。
-
case 语句中的值必须是字面量,不能是变量。
-
case 语句中的值必须和switch后面的值是同一类型,或者能够相互转换。
-
case可以合并
-
在每个 case 分支中要加上 break 语句,以避免case穿透现象。
-
在 switch 语句中,一般都应该有一个 default 分支,用于处理一些特殊情况,以避免程序出错。 (当然,default语句不写,也不会编译报错。)
-
switch 语句中的 default 分支可以放在 switch 块的任意位置,但是通常建议将 default 分支放在所有 case 分支的最后面。(可读性好)
-
-
例题(月份程序的优化)
/* 编写一个程序,输入一个年份year和一个月份month,判断这个月份有多少天。判断方法如下: 如果month为1、3、5、7、8、10、12中的一个,输出"month有31天"; 如果month为4、6、9、11中的一个,输出"month有30天"; 如果month为2并且year为闰年,输出"month有29天";(如果一个年份能够被4整除但不能被100整除,或者能够被400整除,那么它就是闰年) 如果month为2并且year不是闰年,输出"month有28天"。 */ import java.util.Scanner; public class IfTest07{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请告诉我一个年份,以及一个月份,我可以告诉你这一年的这个月有多少天。"); System.out.print("请输入年份:"); int year = s.nextInt(); System.out.print("请输入月份:"); int month = s.nextInt(); switch(month){ case 1:case 3:case 5:case 7:case 8:case 10:case 12: System.out.println(year + "年" + month + "月有31天"); break; case 4:case 6:case 9:case 11: System.out.println(year + "年" + month + "月有30天"); break; default: if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){ System.out.println(year + "年" + month + "月有29天"); }else{ System.out.println(year + "年" + month + "月有28天"); } }
-
Java12新特性
Java12中switch引入了新特性,代码变得更加简洁:
但是不能新旧混用
switch(x){ case 1 -> System.out.println(1); //不需要break了,也不会有穿透现象 case 2 -> System.out.println(2); default -> System.out.println("default"); } switch(x){ case 1, 2, 3 -> System.out.println("123"); } switch(x){ case 1 -> { System.out.println(1); System.out.println(1); } //只有一条Java语句时,大括号可以省略 }
上述程序的改进:
import java.util.Scanner; public class IfTest07{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请告诉我一个年份,以及一个月份,我可以告诉你这一年的这个月有多少天。"); System.out.print("请输入年份:"); int year = s.nextInt(); System.out.print("请输入月份:"); int month = s.nextInt(); //java12新特性 switch(month){ case 1,3,5,7,8,10,12 -> System.out.println(year + "年" + month + "月有31天!!!"); case 4,6,9,11 -> System.out.println(year + "年" + month + "月有30天!!!"); default -> { if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){ System.out.println(year + "年" + month + "月有29天!!!"); }else{ System.out.println(year + "年" + month + "月有28天!!!"); } } } } }
循环语句
当某代码片段需要频繁多次执行时,可以采用循环语句
for循环(循环次数固定)
语法结构
for(初始化表达式; 条件表达式; 更新表达式){
循环体;
}
执行原理
-
初始化表达式:最先执行,并且只执行一次
-
条件表达式:的执行结果必须是一个布尔类型的值
-
更新表达式:一般是负责更新某个变量值的(只有更新了某个变量值,条件表达式才有机会变成false,循环终止)
注意点
-
for后面小括号中的三个表达式都不是必须的
死循环
for(;😉{
循环体;
}
-
可以将括号里面的表达式拿出来,改变作用域
for(int i = 0; i < 10; i ++){} //循环结束后访问不了i变量 int i = 0; //循环结束后仍然可以访问到i for(; i < 10; i ++){}
for循环基础练一练
-
输出1~10
public class ForTest01{ public static void main(String[] args){ for(int i = 1; i <= 10; i++){ System.out.println(i); } } }
-
输出1~100中所有的偶数
public class ForTest02{ public static void main(String[] args){ for(int i = 2; i <= 100; i += 2){ System.out.println(i); } } }
-
输出100,97,94,91…1
public class ForTest03{ public static void main(String[] args){ for(int i = 100; i >= 1; i -= 3){ System.out.println(i); } } }
-
计算1~100所有奇数的和。
public class ForTest04{ public static void main(String[] args){ int sum = 0; for(int i = 1; i <= 100; i += 2){ sum += i; } System.out.println(sum); } }
-
计算n的阶乘。
import java.util.Scanner; public class ForTest05{ public static void main(String[] args){ Scanner s = new Scanner(System.in); System.out.println("请输入一个整数:"); int n = s.nextInt(); int result = 1; for(; n >= 1; n--){ result *= n; } System.out.println(result); } }
for循环嵌套
九九乘法表
public class ForTest06{
public static void main(String[] args){
for(int i = 1; i <= 9; i++){
for(int j = 1; j <= i; j++){
System.out.print(j + "*" + i + "=" + i*j + " ");
}
System.out.println(); //换行
}
}
}
for循环嵌套练一练
-
找出1~1000的所有质数,输出时每8个换一行
先学会如何判断一个数是否为质数
两种思想:boolean标记,计数器
public class ForTest{ public static void main(String[] args){ //计数器思想。定义一个计数器 int count = 0; for(int j = 2; j <= 1000; j++){ int num = j; //一种思想,boolean标记 boolean isPrime = true; //只要判断 num/2 即可,大于 num/2 的数肯定除不尽,最好的方法是num开平方根 //用math方法开平方根 for(int i = 2; i <= num/2; i++){ if(num % i == 0){ isPrime = false; } } if(isPrime){ count++; System.out.println(num + " "); if(count % 8 == 0){ System.out.println(); /* 法二: if(count == 8){ System.out.println(); count = 0; */ } } } } }
/* 输入一个正整数n,计算1-2+3-4+5-6+…-(n-1)+n的和 */ public class ForTest08{ public static void main(String[] args){ int n = 6; int result = 0; for(int i = 1; i <= n; i++){ //System.out.println(i); if(i % 2 == 0){ result -= i; }else{ result += i; } } System.out.println("result = " + result); } }
/* 输出1到1000之间既能被5整除又能被3整除的数,并且每行输出5个 */ public class ForTest09{ public static void main(String[] args){ int count = 0; for(int i = 1; i <= 1000; i++){ if(i % 5 == 0 && i % 3 == 0){ System.out.print(i + " "); count++; } if(count == 5){ System.out.println(); count = 0; } } } }
/* 求100到999之间的水仙花数。水仙花数的每个位上的数字的3次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153) */ public class ForTest10{ public static void main(String[] args){ for(int i = 100; i <= 999; i++){ int num = i; // 判断153这个数字是否为水仙花数 int 个位 = num % 10; int 十位 = num / 10 % 10; int 百位 = num / 100; if(个位 * 个位 * 个位 + 十位 * 十位 * 十位 + 百位 * 百位 * 百位 == num){ System.out.println(num + "是水仙花数"); } } } }
/* 找1~100之间的质数,并输出两两相邻的质数差值等于 2 的质数对,例如(3,5),(5,7),(11,13),(17,19)等等 */ public class ForTest11{ public static void main(String[] args){ for(int j = 2; j <= 98; j++){ //j <= 98 防止溢出问题 // 判断num是否为质数 int num = j; boolean isPrime = true; for(int i = 2; i <= num / 2; i++){ if(num % i == 0){ isPrime = false; } } if(isPrime){ // 如果第一个数字是质数。才有必要继续判断。 num += 2; boolean isPrime2 = true; for(int i = 2; i <= num / 2; i++){ if(num % i == 0){ isPrime2 = false; } } if(isPrime2){ System.out.println("(" + (num-2) + "," + num + ")"); } } } } }
/* ******** ******** ******** ******** ******** ******** 1-->4 ******** 2-->3 ******** 3-->2 ******** 4-->1 ******** 5-->0 * 1->4 *** 2->3 ***** 3->2 ******* 4->1 ********* 5->0 */ public class ForTest12{ public static void main(String[] args){ for(int i = 1; i <= 5; i++){ for(int j = 1; j <= 8; j++){ System.out.print("*"); } System.out.println(); } System.out.println("==================================="); for(int i = 1; i <= 5; i++){ for(int k = 5 - i; k > 0; k--){ System.out.print(" "); } for(int j = 1; j <= 8; j++){ System.out.print("*"); } System.out.println(); } System.out.println("==================================="); int n = 10; for(int i = 1; i <= n; i++){ for(int k = n - i; k > 0; k--){ System.out.print(" "); } for(int j = 1; j <= i * 2 - 1; j++){ System.out.print("*"); } System.out.println(); } } }
while循环(循环次数不固定)
语法结构
while(布尔表达式){
循环体;
}
循环次数是0~n次(适合循环次数不固定的情况)
public class WhileTest01{
public static void main(String[] args){
/*
while(true){
System.out.println("死循环");
}
*/
int i = 0;
while(i < 10){
System.out.println("i = " + i);
i++;
}
}
}
猜数字小游戏
import java.util.Scanner;
import java.util.Random;
public class WhileTest02{
public static void main(String[] args){
//专门生成随机数的一个类
Random random = new Random();
int num = random.nextInt(100) + 1;
Scanner scanner = new Scanner(System.in);
//计数器
int count = 0;
while(true){
count++;
System.out.println("请输入你猜的数字:");
int guess = scanner.nextInt();
if(guess == num){
System.out.println("猜对了!");
System.out.println("您一共猜了" + count + "次");
//终止程序执行
return;
}else if(guess > num){
System.out.println("猜大了");
}else{
System.out.println("猜小了");
}
}
}
}
do while循环
do{
循环体; //至少循环一次
}while(布尔表达式); //括号里面的变量大括号里面找不到,变量定义一般在外面
/*
求平均数:要求用户输入一组数字,用 -1 表示输入结束,使用 do-while 循环计算这些数字的平均数并输出。
要使用一个计数器来记录输入的数字个数,遇到 -1 则终止输入并计算平均数
*/
import java.util.Scanner;
public class DoWhileTest02{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
/*
while(true){
int num = scanner.nextInt();
System.out.println("您输入的数字是:" + num);
if(num == -1){
System.out.println("再见!");
return;
}
}
*/
// 计数器
//int count = 0;
// 求和的结果
//int sum = 0;
/*
do{
count++;
int num = scanner.nextInt();
sum += num;
System.out.println("您输入的数字是:" + num);
if(num == -1){
System.out.println("您一共输入了" + (--count) + "个数字");
int avgValue = (sum + 1) / count;
System.out.println("平均值是:" + avgValue);
System.out.println("再见!");
return;
}
}while(true);
*/
//优化
// 计数器
int count = 0;
// 求和结果
int sum = 0;
// 用户输入的数字(默认值是0)
int num = 0;
do{
sum += num;
System.out.print("请输入数字:");
num = scanner.nextInt();
count++;
}while(num != -1);
System.out.println("平均值:" + sum / (--count));
}
}
跳转语句
break语句
-
break;语句可以使用在switch当中,终止switch的执行。
-
break;可以使用在循环中,用来终止循环的执行。
for
while
do while
这些循环中都可以使用break; -
默认情况下,单独使用“break;”语句,终止的是离它最近的循环。
public class BreakTest01{ public static void main(String[] args){ /* for(int i = 1; i <= 10; i++){ if(i == 5){ break; } System.out.println("i = " + i); } */ /* for(int j = 0; j < 2; j++){ for(int i = 1; i <= 10; i++){ if(i == 5){ break; } System.out.println("i = " + i); } } */ f1:for(int j = 0; j < 2; j++){ f2:for(int i = 1; i <= 10; i++){ if(i == 5){ break f1; } System.out.println("i = " + i); } } System.out.println("Hello World!"); } }
continue语句
-
continue;语句翻译为:继续
-
也是使用在循环语句当中。
-
作用:终止当前本次循环,直接进入下一次循环继续执行。
public class ContinueTest01{ public static void main(String[] args){ /* i = 0 i = 1 i = 2 i = 3 i = 4 */ for(int i = 0; i < 10; i++){ if(i == 5){ break; } System.out.println("i = " + i); } System.out.println("==================================="); for(int i = 0; i < 10; i++){ if(i == 5){ continue; } System.out.println("i = " + i); } System.out.println("==================================="); f1:for(int j = 0; j < 2; j++){ f2:for(int i = 0; i < 10; i++){ if(i == 5){ continue f1; } System.out.println("i = " + i); } } } }
控制语句作业
-
请设计一个程序,不断的从键盘上接收一个正整数或者负整数,要求计算所有正整数的和,如果接收到0,则程序退出。
import java.util.Scanner; public class ControlHonework01{ public static void main(String[] args){ Scanner s = new Scanner(System.in); int num = 0; int sum = 0; do{ System.out.println("请输入一个整数:"); num = s.nextInt(); if(num > 0){ sum += num; } }while(num != 0); System.out.println("sum = " + sum); } }
-
请编写一个程序,打印1~100所有的奇数,但是跳过所有以数字 3 结尾的数字
public class ControlHomework02{ public static void main(String[] args){ for(int i = 1; i <= 100; i+=2){ if(i % 10 == 3){ continue; } System.out.println("i = " + i); } } }
-
韩信点兵,三人一组余两人,五人一组余三人,七人一组余四人,请问最少需要多少士兵
public class ControlHomework03{ public static void main(String[] args){ int i = 1; /* while(true){ i++; if(i % 3 == 2 && i % 5 == 3 && i % 7 == 4){ System.out.println("至少" + i + "个士兵"); break; } } */ while(!(i % 3 == 2 && i % 5 == 3 && i % 7 == 4)){ i++; } System.out.println("至少" + i + "个士兵"); } }
方法(重要,在C语言里面叫函数)
方法的本质就是一段可以被重复利用的代码片段,并且每一个方法都是一个独立的封装好的功能。
方法只定义,不去调用,是不会执行的。
方法要执行的话,肯定是有一个位置调用了这个方法。
public class MethodTest01{
// 入口
public static void main(String[] args){
// 调用sum方法,完成求和功能。
// 请编写程序计算100和200的和。
sum(100, 200); // 方法的调用。
// 请编写程序计算666和888的和。
sum(666, 888); // 方法的调用。
// 请编写程序计算123和456的和。
sum(123, 456); // 方法的调用。
}
// 单独定义一个方法,这个方法完成一个具体的功能。求和功能。
// 方法的定义。
public static void sum(int a, int b){
int c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
}
方法的定义与调用
-
方法的定义
-
语法格式:
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}
-
修饰符列表:目前统一写 public static
-
返回值类型:
可以是java语言中任何一种数据类型,可以是基本数据类型,也可以是应用数据类型
例如:byte short int long float double boolean char String…
如果方法执行结束后没有返回任何数据给调用者,返回值类型写 void(main方法的调用者是jvm,不要返回任何数据给jvm)
切记:不能空着不写
例如:返回值类型是int表示:方法结束的时候会返回一个整数给调用者。
返回值类型是String表示:方法结束的时候会返回一个字符串给调用者。
返回值类型是void表示:方法结束的时候不返回任何数据给调用者。 -
当返回值类型不是void的时候,方法在结束的时候必须使用“return 值;”语句来完成数据的返回。
-
return语句有两种写法:
第一种:return 值;
第二种:return;
不管是哪一种,只要return语句执行,方法必然结束。 -
当返回值类型是void的时候:
不能编写"return 值;" 这样的语句。
但是可以编写"return;"语句,主要是用来终止方法的执行。也可以不编写“return;”,这个要看具体的业务。 -
当调用一个返回值类型不是void的方法时,方法结束的时候会返回值,这个值可以采用变量接收。注意变量的类型。
变量的类型一定要和返回值类型一致。或者能够自动类型转换,或者强制类型转换。 -
方法执行结束有返回值,但是对于调用者来说,可以选择接收,也可以选择不接收。
-
方法名:只要是合法的标识符即可。首字母小写,后面每个单词首字母大写。(一般方法都是一个行为,所以方法名一般都是动词。)
方法名最好是反映了这个方法所实现的功能。
deleteUser
saveUser
login
logout
… -
形式参数列表一般简称为:形参。形参个数是:0-N个。多个的话,使用逗号隔开。
形参是局部变量。形参中起决定性作用的是:形参的类型。形参名随意。
-
方法体:任何一个方法都有一个方法体。方法体用大括号括起来:
在大括号中编写“java语句;”
并且方法体中的代码有执行顺序,遵循自上而下。
-
-
方法的调用
当这个方法修饰符列表有static关键字的时候:
调用的语法格式:
类名.方法名(实际参数列表);实际参数列表简称为:实参。
实参和形参列表必须一一对应:
类型要一一对应。
个数要一一对应。public class MethodTest03{ public static void main(String[] args){ // 调用方法 int result = add(1, 2); System.out.println(result); // 这个过程就存在自动类型转换。 long result2 = add(200, 300); System.out.println(result2); // concat方法结束后返回的是String值,必须使用String类型变量接收这个值。 String content = concat("hello,", "jack"); System.out.println(content); add(1111, 2222); // 错误 //add(false, 1); // 错误 //add(1); // 用完整语法调用一次方法。 String retValue = MethodTest03.concat("abc", "def"); System.out.println(retValue); } // 求和的一个方法。 public static int add(int a, int b){ System.out.println("add.........."); //int z = x + y; //return z; return a + b; } public static String concat(String x, String y){ //String z = x + y; //return z; return x + y; } // 报错原因:因为返回值类型是int,那么结束时就必须要返回一个整数。但是没有写 return 返回语句来完成数据的返回 /* public static int sum(int a, int b){ } */ // 解决错误:添加了返回语句。 public static int sum(int a, int b){ //int c = a + b; //return c; return 0; } public static boolean m1(){ // 不兼容的类型: int无法转换为boolean //return 1; // 修改 return true; } // 缺少返回语句 /* public static String m2(){ } */ // 修改 public static String m2(){ return "say hello"; } public static void m3(){ } // 编译报错:言行不一。 /* public static void m4(){ return 100; } */ //作用:整个方法结束 public static void m5(){ return; } // 缺少返回值 /* public static int m6(){ return; } */ }
-
调用方法时,类名. 什么时候可以省略
调用者和被调用者在同一个类中时,可以省略
public class MethodTest04{ public static void main(String[] args){ // 调用方法m1 MethodTest04.m1(); // 省略 类名. m1(); // 调用m2方法 A.m2(); // 编译报错。 //m2(); } public static void m1(){ System.out.println("m1方法执行了"); } } class A{ public static void m2(){ System.out.println("m2方法执行了"); } }
-
常见的错误
public class MethodTest05{ // 缺少返回语句 //return 1; 可能不执行 /* public static int m1(){ int i = 100; if(i > 99){ return 1; } } */ // 可以 /* public static int m1(){ int i = 100; if(i > 99){ return 1; }else{ return 0; } } */ //在同一个域中:return语句后面的代码是无法执行的。请不要写。 public static int m1(){ int i = 100; if(i > 99){ System.out.println("位置1"); return 1; //错误:无法访问的语句 //System.out.println("位置2"); } System.out.println("位置3"); return 0; //错误:无法访问的语句 //System.out.println("位置4"); } }
判断质数的方法
找出1-100所有的质数。请使用方法。
public class MethodTest06{
public static void main(String[] args){
for(int i = 2; i <= 100; i++){
if(isPrime(i)){
System.out.println(i);
}
}
}
public static boolean isPrime(int num){
for(int i = 2; i <= num / 2; i++){
if(num % i == 0){
return false;
}
}
return true;
}
}
实现登录的方法
系统可以接收用户名和密码,判断用户名和密码,如果用户名是admin,密码是123,则登录成功。
如果用户名或密码不对,请继续让用户输入用户名和密码,直到登录成功。
import java.util.Scanner;
public class MethodTest07{
public static void main(String[] args){
login();
}
public static void login(){
Scanner s = new Scanner(System.in);
while(true){
System.out.print("请输入用户名:");
String username = s.next();
System.out.print("请输入密码:");
String password = s.next();
if((check(username,password))){
System.out.println("账号名或密码不正确,请重新输入!");
}else{
System.out.println("登录成功!");
}
}
public static boolean check(String username, String password){
//后面这里链接数据库
return (username.equals("admin") && password.equals("123"));
}
}
方法执行时内存的变化
- 方法如果只定义,不掉用,是不会分配内存空间的。(从Java8开始,方法的字节码指令存储在元空间metaspace当中。元空间使用的是本地内存。)
- 方法调用的瞬间,会在jvm的栈内存当中分配活动场所,此时发生压栈操作。
- 方法一旦结束,给该方法分配的内存空间就会释放。此时发生弹栈动作。
public class MethodTest08{
public static void main(String[] args){
System.out.println("main begin");
m1();
System.out.println("main over");
}
public static void m1(){
System.out.println("m1 begin");
m2();
System.out.println("m1 over");
}
public static void m2(){
System.out.println("m2 begin");
m3();
System.out.println("m2 over");
}
public static void m3(){
System.out.println("m3 begin");
System.out.println("m3 over");
}
}
/*
main begin
m1 begin
m2 begin
m3 begin
m3 over
m2 over
m1 over
main over
*/
方法重载机制(overload)
方法重载是编译阶段的机制,在编译阶段已经确定要用哪个方法了
- 当前代码先不使用方法重载
缺点:1.代码不美观
2.不方便调用,程序员需要记忆很多方法名
public class OverloadTest01{
public static void main(String[] args){
//调用方法
sumInt(10, 20);
sumLong(10L, 20L);
sumDouble(3.0, 2.0);
}
public static void sumInt(int a, int b){
int c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
public static void sumLong(long a, long b){
long c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
public static void sumDouble(double a, double b){
double c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
}
- 在java语言中,允许在一个类中定义多个方法,这些方法的名字可以一致(全部变成sum)
public class OverloadTest02{
public static void main(String[] args){
//调用方法
sum(10, 20);
sum(10L, 20L);
sum(3.0, 2.0);
}
public static void sum(int a, int b){
int c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
public static void sum(long a, long b){
long c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
public static void sum(double a, double b){
double c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
}
-
构成条件:
-
在同一个类中
-
方法名一致
-
形式参数(跟变量名无关)列表不同(类型、顺序、个数不同)
public class OverloadTest03{ public static void main(String[] args){ m1(); m1("abc"); m2(10, 20); m2(10L, 20L); m3("x", 10); m3(10,"x"); } //构成方法重载 //形参的个数不同 public static void m1(){} public static void m1(String s){} //形参的类型不同 public static void m2(int a, int b){} public static void m2(long a, long b){} //形参的顺序不同 public static void m3(String s, int a){} public static void m3(int a, String s){} //以下两种未够成,是一样的方法,编译报错 /* public static void doSome(int a, int b){} public static void doSome(int x, int y){} */ }
-
-
什么时候使用?
在以后的开发中,在一个类中,功能类似的情况下,建议将方法类似的方法名定义成一样。
-
实例(println)
System.out.println();
这个println方法是PrintStream类中的方法
在java.io.PrintStream类中有很多println方法,这些方法都已经构成了方法的重载
方法的递归调用
-
什么事方法的递归调用?
方法自己调用自己
public class RecursionTest01{ public static void main(String[] args){ recursion(); } public static void recursion(){ System.out.println("recursion begin"); recursion(); System.out.println("recursion over"); } }
-
以上程序一直在压栈,不会弹栈,会导致栈内存溢出错误
java.lang.StackOverflowError
-
所有的递归调用必须要有结束条件
也有可能在结束条件执行之前就出现栈内存溢出错误,递归太深,栈内存不够
-
原则:能用循环解决的尽量不要用递归调用
-
在实际开发中,如果因为递归调用发生了栈内存溢出错误,如何解决?
首先可以调整栈内存的大小,扩大栈内存。
如果扩大之后运行一段时间还是出现了栈内存溢出错误,可能是因为递归结束条件不对,需要进行代码的修改。
-
举个栗子(以及内存图):
先不使用递归调用,计算1~n的和
public class RecursionTest02{ public static void main(String[] args){ int n = 5; System.out.println(sum(n)); } //计算1~n的和 public static int sum(int n){ int sum = 0; for(int i = 1; i <= n; i++){ sum += i; } return sum; } }
使用递归调用:
public class RecursionTest03{ public static void main(String[] args){ int n = 5; System.out.println(sum(n)); } //计算1~n的和 public static int sum(int n){ if(n == 1){ return 1; } return n + sum(n - 1); } }
使用递归计算n的阶乘
public class RecursionTest04{ public static void main(String[] args){ int n = 5; System.out.println(jieCheng(n)); } public static int jieCheng(int n){ if(n == 1){ return 1; } return n * jiecheng(n - 1); } }
斐波那契数列
假如有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长大后到第3个月后每个月又生一对兔子,假如兔子都不死,请问第n个月后的兔子有多少对。
如下规律:
当前数字 = 前两个相邻数字之和
当月兔子总数 = 上个月兔子总数 + 上上个月兔子总数
1
1
2
3
5
8
13
21
34
55
89
144 12月时兔子总对数
public class Rabbit{ public static void main(String[] args){ int n = 12; System.out.println(n + "月得时候兔子总数:" + rabbit(n)); } public static int rabbit(int n){ if(n == 1 || n == 2){ //递归的结束条件 return 1; } return rabbit(n - 2) + rabbit(n - 1); } }
package和import
package包机制
-
包机制作用:便于代码管理。
-
怎么定义包:在java源码第一行编写 package 语句。注意:package语句只能出现在java代码第一行。
package 包名;
-
如果带包编译:(也可以不带包编译,可以编译之后手动创建目录)
语法:javac -d 编译后的存放目录 java源文件路径
package com; public class PackageTest01{}
以上程序的带包编译
javac -d . PackageTest01.java //编译。在当前路径下生成com文件夹,里面是class文件
-
有了包机制后,完整类名是包含包名的,运行的时候一定要加上包名。例如类名是:com.powernode.javase.chapter02.PackageTest
java com.powernode.javase.chapter02.PackageTest
java com.PackageTest01 //运行
-
包名的命名规范:
- 包名命名规范中要求是全部小写。
- 包名命名规范:公司域名倒序 + 项目名 + 模块名 + 功能名。例如:com.powernode.oa.empgt.service
package com;
public class PackageTest01{ //类名为:com.PackageTest01,放在com文件夹下
public static void main(String[] args){
System.out.println("Java语言中的包机制!");
}
}
import语句详解
-
import语句只能出现在package和class定义之间
-
import语句可以编写多个
-
什么时候使用import语句?
A类中使用B类,当A和B类不在同一个包下。并且B类也不属于java.lang包,必须使用import导入
-
import语句可以模糊导入:
import java.util.Scanner;
import java.util.*;
不能这样:import *; *是类名
-
import静态导入(不常用):
import static java.lang.System.*; //将System类中的所有静态变量和静态方法全部导入 import static java.lang.Math.*; out.println("1"); abs("-110"); //求绝对值
package com;
//导入其他类
import com.powernode.oa.empgt.service.UserService;
public class PackageTest01{
public static void main(String[] args){
System.out.println("Java语言中的包机制!");
com.PackageTest03.doSome();
//在同一个com包下面,可以不加com
PackageTest03.doSome();
com.powernode.oa.empgt.service.UserService.delUser();
//使用import导入以后
UserService.delUser();
//java.long.String name = "jackson";
String name = "jackson";
}
}
Intellij IDEA 的使用
IDEA工具的安装
如何新建空工程
如何设置JDK以及编译器版本
如何新建模块
如何新建包,新建类
如何运行Java程序
如何设置字体大小
常用的IDEA快捷操作(包括以上所有问题)
- alt+insert(新建/新增任何东西)
- 退出任何窗口:ESC
- 编写源码的窗口最大化:ctrl+shift+F12
- psvm生成main方法
- 快速生成输出语句:sout
- IDEA会自动保存,自动编译
- 打开Project窗口:alt+1
- 查找某个类:敲两次shift,选择classes,输入类名
- 切换选项卡:alt + 左右方向键
- 自动生成变量:变量.var
- 删除一行:ctrl+y
- 复制一行:ctrl+d
- 在一个类当中查找方法:ctrl+F12
- 生成for循环:fori
- 自动生成if语句.if
- 单行注释:ctrl + /
- 多行注释:ctrl + shift + /
- 查看源码:按ctrl别松手,鼠标移动到对应的类名下方,出现下划线,点击过去,可以查看类源码。
- 多行编辑:按alt别松手,鼠标拖动多行,完成多行编辑。
- 怎么快速生成创建对象语句:类名.new.var
- 怎么快速生成if语句:布尔类型值.if
- 怎么快速生成setter和getter方法:alt + insert,然后选择setter and getter生成。
- 怎么快速生成构造方法:alt + insert,然后选择Constructor。
- 在IDEA当中如何自动纠错:将光标移动到错误的位置,按atl + enter。会有提示,根据提示进行纠错。
- 移动代码到上一行:alt + shift + 上/下方向
- 怎么快速重写方法?alt + insert,选择Override…
- 怎么快速重写方法?ctrl + o
- 快速向下转型,并同时生成变量名:变量名.castvar
- 快速查看方法的参数:ctrl + p
- 返回上一步:ctrl + alt + 左方向键。 下一步:ctrl + alt + 右方向键。
- 代码格式化:ctrl + alt + L。
- 查看继承结构:ctrl + H
- 自动代码包裹:ctrl + alt + t