02【IDEA、数据类型转换、运算符、方法】
一、开发工具IntelliJ IDEA
1.1 开发工具概述
IDEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超常的。IDEA是JetBrains公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。它的旗舰版本还支持HTML,CSS,PHP,MySQL,Python等。免费版只支持Java,Kotlin等少数语言。

1.2 安装IntelliJ IDEA
参考IntellIJ IDEA安装和破解手册
1.3 创建项目和模块
1)创建项目
1)点击Create New Project:

2)创建一个空项目,选择项目的磁盘位置及填写项目名称

2)创建模块
1)在弹出的对话框中,点击"+",然后点击New Module创建一个新的模块:

2)创建一个Java模块:

4)模块创建成功(自带了一个Main.java文件):

5)目录介绍:

3)编写代码
- 编写HelloWorld代码:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
4)运行代码:

查看控制台输出:

1.4 IDEA的项目目录
- .idea:该文件夹是IntelliJ IDEA项目的配置信息文件夹,主要存储了项目本身的一些编译配置、文件编码信息、jar包的数据源和相关的插件配置信息。
- out:目录是存储编译后的.class文件
- *.iml:该文件是idea自动创建的模块文件,用于存储一些模块开发相关的信息,一个.iml文件通常会存储一个Java组件、插件组件、Maven组件等的相关信息,还可能会存储一些模块路径信息、依赖信息以及其他的设置。它们记录了模块之间的依赖关系和路径信息

1.5 IDEA基本设置
1.5.1 字体设置
点击菜单栏上的 File->Settings->Editor->Font 修改字体

1.5.2 代码模板
1)修改代码模板:

2)新建代码模板:

我们在src目录右击查看菜单时,发现多了一个"HelloWorld"选项:

1.5.3 快捷键模板
idea提供了很多快捷键,可以帮助我们快速生成很多代码,比如输入psvm可以帮助我们快速生成打印语句,同时我们也可以自定义快捷键来生成我们的模板代码。


1.5.3 提示忽略大小写
idea具备代码提示功能,但是是严格匹配大小写的,例如我们输入Sy,idea会提示System,但是如果输入的是sy(小写)则不会提示,我们可以通过设置来忽略大小写提示;

1.6 IDEA快捷键
1.6.1 修改快捷键
1) 代码提示快捷键
在IDEA工具中, Ctrl+空格的快捷键,可以帮助我们补全代码,但是这个快捷键和Windows中的输入法切换快捷键冲突,需要修改IDEA中的快捷键。 File->Settings->keymap->Main menu->code->Completion->Basic
1)先移除掉之前的快捷键

2)添加Alt+/快捷键:

2) 字体大小缩放快捷键
调整字体我们如下配置:

但是每次这样调整的话,比较麻烦,我们可以配置鼠标滚轮来缩放字体大小:


1.6.2 IDEA常用快捷键
| 快捷键 | 功能 |
|---|---|
| Alt+Enter | 导入包,自动修正代码 |
| Ctrl+Y | 删除一行 |
| Ctrl+D | 快速复制一行 |
| Ctrl+Alt+L | 格式化代码 |
| Ctrl+/ | 单行注释 |
| Ctrl++Shift+/ | 多行注释 |
| Alt+Shift+上下箭头 | 移动当前代码行 |
| Ctrl+Shift+N | 快速查询当前项目下的所有文件 |
| Ctrl+N | 快速查询当前项目的所有类 |
二、数据类型转换
Java程序中要求参与计算的数据,必须要保证数据类型一致,如果数据类型不一致将发生类型的转换。
2.1 自动转换
一个 int类型变量和一个 byte 类型变量进行加法运算, 结果会是什么数据类型?
int i = 1;
byte b = 2;
运算结果,变量的类型将是 int 类型,这就是出现了数据类型的自动类型转换现象。
- 自动转换:将取值范围小的类型 自动提升为取值范围大的类型 。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
public static void main(String[] args) {
int i=1;
byte b =2;
// byte x=b+i; // 报错
// int类型和byte类型运行,结果是int类型
int j=b+i;
System.out.println(j);
}
}
- 自动转换2:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo {
@Test
public void test1() throws Exception {
float a = 20.5F;
double b = 30.0D;
// float c = a + b; // 报错,最终的数据类型为是double
double c = a + b;
System.out.println(c);
}
}
- 自动转换3:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo {
@Test
public void test1() throws Exception {
int a = 10;
long b = 20L;
// int c = a+b; // 报错,最终的数据类型为是long
long c = a + b;
System.out.println(c);
}
}
2.1.1 转换图解
byte 类型内存占有1个字节,在和 int类型运算时会提升为int 类型自动补充3个字节,因此计算后的结果还是 int 类型。

同样道理,当一个 int 类型变量和一个 double 变量运算时, int 类型将会自动提升为 double 类型进行运算。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo02 {
public static void main(String[] args) {
int i=1;
double d=2.5;
// int类型和double类型运算,结果是double类型
// int类型会提升为double类型
// int x= i+d; // 报错
double x=d+i;
System.out.println(x);
}
}
2.1.2 转换规则
1)小的转为大的
范围小的类型向范围大的类型提升,byte、short、char 运算时直接提升为 int ;
byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double
小的范围与大的范围相加的结果就是大的范围的数据类型
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo03 {
public static void main(String[] args) {
byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2; // 当变量的数据类型小于int做运算时,会转成int再运算 byte b3 = (byte)b1 + b2;
}
}
Tips:当变量的数据类型小于int做运算时,会转成int再运算
- 观察下列代码:
short s = 1;
s = s + 1; // 是否报错?
System.out.println(s);
答案
2)整数转为小数
我们前面知道,当数据类型范围小的与数据类型范围大的发生运算时,其结果的数据类型为范围大的;但是,当整数类型与小数类型发生运算时,其结果一定为小数类型!
【代码示例】
public class Demo {
public static void main(String[] args) {
long a = 10L;
float b = 10.5F;
// long c = a + b; // 报错,结果为float类型的
float c = a + b;
System.out.println(c);
}
}
3)变量的声明
在使用long、float、double赋值时,分别要在值的后面加上l、f、d等来说明其数据类型(大小写都可以),其中long类型可以不加'l'后缀,double也可以不加'd'后缀;float则是强制要加。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo {
public static void main(String[] args) {
long a = 10L;
float b = 10.5F;
double c = 20.0D;
// 小写也可以
long a1 = 10l;
float b1 = 10.5f;
double c1 = 20.0d;
// 小写也可以
long a3 = 10; // long类型的后缀可以省略不加
// float b3 = 10.5; // float类型的后缀一定要加
double c3 = 20.0; // double类型的后缀可以省略不加
}
}
2.2 强制转换
在Java中,我们也可以将数据取值范围大的转换为数据取值范围小到的,这种转换并不是自动的过程,而是需要我们手动的转换,我们称这种转换为强制转换。
例如下面代码:
long a = 10L;
int b = a; // 报错
long类型内存8个字节, int类型内存4个字节。 long取值范围大于int ;想要赋值成功,只有通过强制类型转换,将 long 类型强制转换成int类型才能赋值。
- 强制转换:将 取值范围大的类型 强制转换成 取值范围小的类型;比较而言,自动转换是Java自动执行的,而强制转换需要我们自己手动执行。
强制转换格式:
数据类型 变量名 = (数据类型)被转数据值;
将 1.5 赋值到 int 类型,代码修改为:
long a = 10L;
int b = (int)a;
同样道理,当一个 short 类型与 int 类型相加,我们知道会类型提升,但是还想给结果赋值给 short 类型变量,就需要强制转换。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo04 {
public static void main(String[] args) {
// short类型变量,内存中存储两个字节
short s = 1;
int i = 1;
/*
出现编译错误
s和i做运算的时候,i是int类型,s会被提升为int类型
s+i后的结果是int类型,将结果在赋值会short类型时发生错误
*/
// s = s + i; // 编译失败
s = (short) (s + i); // 强制转换,编译成功
System.out.println(s);
}
}
2.2.1 转换图解
short 类型内存占有2个字节,在和 int类型运算时会提升为 int 类型 ,自动补充2个字节,计算后的结果还是 int 类型,但最终被强转为了short类型,占用2个字节空间。

2.2.2 浮点数与整数的底层存储
下面是8个基本数据类型的取值范围大小:
| 数据类型 | 关键字 | 内存占用 | 取值范围 |
|---|---|---|---|
| 字节型 | byte | 1个字节 | -128~127 |
| 短整型 | short | 2个字节 | -32768~32767 |
| 整型 | int(默认) | 4个字节 | -2147483648~2147483647 |
| 长整型 | long | 8个字节 | -2的63次方~2的63次方-1 |
| 单精度浮点数 | float | 4个字节 | 1.4013E-45~3.4028E+38 |
| 双精度浮点数 | double(默认) | 8个字节 | 4.9E-324~1.7977E+308 |
| 字符型 | char | 2个字节 | 0-65535 |
| 布尔类型 | boolean | 1个字节 | true,false |
我们可以发现,int和float都是占用4个字节大小,但是float的取值范围却比int要大的多。同样的情况在long与double这两种类型上也存在;
这是为什么呢?
double与long表示范围的差距是由于存储结构的不同导致的,换句话说我们保存1000这个数,我们long要存储+1000,其二进制为001111101000,而double存储的是+1E3。拆开来看,存储一个数double可以分成三部分:尾数位(1),基数位(10),指数位(3)。也就是用科学计数法来存储,这简单的1000就能看出差距,long存储1000需要符号位(+)和数字位(1000),需要5位。而double存储,却只需要3位。同样一个数,double能够用更少的内存存储,所以多余的内存就能存储更多的数,因此double > long
通过如下代码可以查看到每个类型的最大值:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
public static void main(String[] args) {
// 2147483647
System.out.println(Integer.MAX_VALUE);
// 3.4028235E38
System.out.println(Float.MAX_VALUE);
// 9223372036854775807
System.out.println(Long.MAX_VALUE);
// 1.7976931348623157E308
System.out.println(Double.MAX_VALUE);
}
}
2.2.3 整数之间的强制转换
强制转换指的是:取值范围大的,转换为取值范围小的。强制转换的时候尤其要注意转换之后的类型是否能存储之前的数据。
- 示例1:数值没有超出转换之后类型的取值范围的情况
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo05_强制类型转换_整数转换_01 {
public static void main(String[] args) {
int a = 100;
byte b = (byte) a;
// byte也能存储100,因此转换的时候不会出现什么问题
System.out.println(b); // 100
}
}
- 示例2:数值超出了转换之后类型的取值范围的情况
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo06_强制类型转换_整数转换_02 {
public static void main(String[] args) {
// 八个字节: 00000000 00000000 0000000 10000100 01000000 11000000 11000000 10000000 ---> 十进制: 568022057088
long a = 568022057088L;
// 四个字节: 01000000 11000000 11000000 10000000 ---> 十进制: 1086374016
int b = (int) a;
System.out.println(b); // 1086374016
// 两个字节: 11000000 10000000 ---> 十进制: -16256
short c = (short) b;
System.out.println(c); // -16256
// 一个字节: 10000000 ---> 十进制: -128
byte d = (byte) c;
System.out.println(d); // -128
}
}
2.2.4 浮点数的强制转换
1) 浮点数转浮点数
- 示例1:数值没有超出转换之后类型的取值范围的情况
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo07_强制类型转换_浮点数转浮点数_01 {
public static void main(String[] args) {
double a = 180.8D;
float b = (float) a;
System.out.println(b); // 180.8
}
}
- 示例2:数值超出了转换之后类型的取值范围的情况
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo07_强制类型转换_浮点数转浮点数_02 {
public static void main(String[] args) {
double a = 3.8E38D;
float b = (float) a;
// float的最大取值范围为: 1.4013E-45~3.4028E+38,无法存储3.8E38,赋值失败
System.out.println(b); // Infinity
}
}
超出最大容量:

2) 浮点数转整数
浮点数强制转换为整数类型时也会出现一定的问题;
- 示例1:浮点数强制转换为整数,数值没有超出转换之后类型的取值范围的情况
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo09_强制类型转换_浮点数转整数_01 {
public static void main(String[] args) {
double a = 18.8D;
// 取值范围: -2的63次方~2的63次方-1
long b = (long) a;
// 取值范围: -2147483648~2147483647
int c = (int) a;
// 取值范围: -32768~32767
short d = (short) a;
// 取值范围: -128~127
byte e = (byte) a;
System.out.println(a); // 18.8
System.out.println(b); // 18
System.out.println(c); // 18
System.out.println(d); // 18
System.out.println(e); // 18
}
}
Tips:浮点数转成整数后将会丢失精度,即小数点后面的通通丢失(注意,并不是四舍五入)
- 示例2:浮点数强制转换为整数(long和int类型),数值超出了转换之后类型的取值范围的情况
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo10_强制类型转换_浮点数转整数_02 {
public static void main(String[] args) {
double a = 5.2E63;
// 取值范围: -2的63次方~2的63次方-1
long b = (long) a;
// 取值范围: -2147483648~2147483647
int c = (int) a;
System.out.println(a); // 5.2E63
System.out.println(b); // 9223372036854775807(long的最大值)
System.out.println(c); // 2147483647(int的最大值)
}
}
Tips:当强制超出该类型的范围时:如果是转换为long或int类型,默认为该类型的最大取值范围值
执行结果:

- 示例3:浮点数强制转换为整数(short和byte类型),数值超出了转换之后类型的取值范围的情况
在Java中,将double或float转换为short/byte时,数值将首先转换为int,然后转换为short/byte,如果该数组超出了int的取值范围,那么转换为short或者byte时结果为-1,如果没有超出int范围,那么如果转换为short将会截取2个字节,转换为byte将会截取1个字节。
示例代码:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo11_强制类型转换_浮点数转整数_03 {
public static void main(String[] args) {
/*
int的取值范围(4个字节): -2147483648~2147483647
short取值范围(2个字节): 取值范围: -32768~32767
byte取值范围(1个字节): -128~127
*/
// 超出了int范围,直接为-1
System.out.println((short) 2147483648.8D); // -1
// 在int范围内,截取两个字节
// 01111111 11111111 11111111 11111100 ---> 2147483644
// 11111111 11111100 ---> -4
System.out.println((short) 2147483644.4D); // -4
// 在int范围内,截取两个字节
// 00000000 00001100 01101110 10110110 ---> 814774
// 01101110 10110110 ---> 28342
System.out.println((short) 814774.8D); // 28342
// 超出了int范围,直接为-1
System.out.println((byte) 2147483648.8D); // -1
// 在int范围内,截取1个字节
// 01111111 11111111 11111111 11111100 ---> 2147483644
// 11111100 ---> -4
System.out.println((byte) 2147483644.4D); // -4
// 在int范围内,截取1个字节
// 00000000 00001100 01101110 10110110 ---> 814774
// 10110110 ---> -74
System.out.println((byte) 814774.8D); // -74
}
}
三、运算符
3.1 算术运算符
| 算术运算符 | |
|---|---|
+ |
加法运算,字符串连接运算 |
- |
减法运算 |
* |
乘法运算 |
/ |
除法运算 |
% |
取模运算,两个数字相除取余数 |
++、-- |
自增自减运算 |
3.1.1 基本运算
- 算数运算符练习:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo05 {
public static void main(String[] args) {
// 定义变量
int a = 5;
int b = 3;
System.out.println(a + b); //8
System.out.println(a - b); //2
System.out.println(a * b); //15
System.out.println(a / b); //1
System.out.println(a % b); //2
System.out.println("------------"); //整数相除,结果是整数,要得到小数,必须有小数参与运算(提升为double类型)
System.out.println(5.0 / 3); //1.6666666666666667
System.out.println(5 / 3.0); //1.6666666666666667
}
}
%取余注意事项:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo06 {
public static void main(String[] args) {
System.out.println(5 % 3);
System.out.println(-5 % 3);
System.out.println(5 % -3);
System.out.println(-5 % -3);
}
}
Tips:取余结果符号与左边符号相同
3.1.2 ++和--
++ 运算,变量自己增长1。反之, -- 运算,变量自己减少1,用法与 ++ 一致。
- 独立运算:
- 变量在独立运算时, 前++ 和 后++ 没有区别 。
- 变量 前++ :例如 ++i 。
- 变量 后++ :例如 i++ 。
- 混合运算:
- 和其他变量放在一起, 前++ 和 后++ 就产生了不同。
- 变量 前++:变量a自己加1,将加1后的结果赋值给b,也就是说a先计算。a和b的结果都是2。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo07 {
public static void main(String[] args) {
int a = 1;
int b = ++a; //先++,后赋值
System.out.println(a); //2
System.out.println(b); //2
}
}
- 变量 后++:变量a先把自己的值1,赋值给变量b,此时变量b的值就是1,变量a自己再加1。a的结果是2,b的结果是1。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo08 {
public static void main(String[] args) {
int a = 1;
int b = a++; //先赋值,后++
System.out.println(a); //2
System.out.println(b); //1
}
}
自增自减小练习
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo09 {
public static void main(String[] args) {
int a = 10;
int b = 10;
int c = 10;
a = b++;
c = --a;
b = ++a;
a = c--;
System.out.println(a); //?
System.out.println(b); //?
System.out.println(c); //?
}
}
答案
3.1.3 +=运算
public class Demo {
public static void main(String[] args) {
short s = 1;
s += 1;
System.out.println(s);
}
}
s += 1 逻辑上看作是 s = s + 1;计算结果被提升为int类型再向short类型赋值时发生错误,因为不能将取值范围大的类型赋值到取值范围小的类型,但是, s=s+1进行两次运算 , += 是一个运算符,只运算一次,并带有强制转换的特点,也就是说 s += 1 就是 s = (short)(s + 1) ,因此程序没有问题编译通过,运行结果是2;
但如果是s=s+1;那么就会出现编译报错,需要强制转换;
3.1.4 字符串注意事项
符号在遇到字符串的时候,表示连接、拼接的含义。"a"+"b"的结果是“ab”,连接含义
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo10 {
public static void main(String[] args) {
// +遇到字符串表示连接
System.out.println("df" + "bz"); //"dfbz"
System.out.println("dfbz" + 10); //"dfbz10"
//1. "dfbz"+5="dfbz5"; 2. "dfbz5"+5="dfbz"
System.out.println("dfbz" + 5 + 5);
System.out.println("dfbz" + (5 + 5)); //1. 5+5=10; 2. 10+"dfbz"="10dfbz"
System.out.println(5 + 5 + "dfbz"); //1. 5+5=10; 2. 10+"dfbz"="10dfbz"
System.out.println("1+1="+1+1);
}
}
思考?
System.out.println("1+1="+1+1);
3.1.5 常量和变量的运算
思考?下面的程序有问题吗?
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo {
public static void main(String[] args) {
byte b1 = 1;
byte b2 = 2;
byte b3 = 1 + 2;
byte b4 = b1 + b2;
}
}
分析: b3 = 1 + 2 , 1 和 2 是常量,为固定不变的数据,在编译的时候(编译器javac),已经确定了 1+2 的结果并没有超过byte类型的取值范围,可以赋值给变量 b3 ,因此b3=1 + 2是正确的。反之, b4 = b2 + b3 , b2 和 b3 是变量,变量的值是可能变化的,在编译的时候,编译器javac不确定b2+b3的结果是什么,因此会将结果以int类型进行处理,所以int类型不能赋值给byte类型,因此编译失败。
3.2 赋值运算符
赋值运算符,就是将符号右边的值,赋给左边的变量。
| 赋值运算符 | |
|---|---|
= |
赋值 |
+= |
加后赋值 |
-= |
减后赋值 |
*= |
减后赋值 |
/= |
除后赋值 |
%= |
取模后赋值 |
- 赋值运算符测试:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo11 {
public static void main(String[] args) {
// 定义变量
int i = 3; // 将3赋值给变量i
i = i + 2; // 将变量i和2相加,再赋值给变量i
System.out.println(i);
// +=: 赋值运算符, 将=左边的变量和=右边的值进行操作,再赋值给变量
int j = 10;
j += 5; // j = j + 5
System.out.println(j);
int m = 10;
m -= 5; // m = m ‐ 5;
System.out.println(m);
System.out.println("‐‐‐‐‐‐‐‐‐‐");
byte b = 1;
// b = b + 2; // 错误: 不兼容的类型: 从int转换到byte可能会有损失
// b += 2; // 可以
b = (byte) (b + 2);
System.out.println(b);
}
}
3.3 比较运算符
比较运算符又叫关系运算符,是两个数据之间进行比较的运算,运算结果都是布尔值 true 或者 false 。
| 比较运算符: | |
|---|---|
== |
比较符号两边数据是否相等,相等结果是true。 |
< |
比较符号左边的数据是否小于右边的数据,如果小于结果是true。 |
> |
比较符号左边的数据是否大于右边的数据,如果大于结果是true。 |
<= |
比较符号左边的数据是否小于或者等于右边的数据,如果小于或等于结果是true。 |
>= |
比较符号左边的数据是否大于或者等于右边的数据,如果小于或等于结果是true。 |
!= |
不等于符号 ,如果符号两边的数据不相等,结果是true。 |
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo12 {
public static void main(String[] args) {
System.out.println(3 == 3); // true
System.out.println(3 == 4); // false
System.out.println(3 != 4); // true
System.out.println(3 > 4); // false
System.out.println(3 < 4); // true
System.out.println(5 <= 4); // false
System.out.println(4 >= 4); // true
// 注意
int i = 3;
int j = 4;
System.out.println(i = j); // 将j赋值给i,输出i
System.out.println(i == j); // true
}
}
3.4 逻辑运算符
3.4.1 运算规则
- 逻辑运算符,是用来对两个布尔类型进行运算的,运算结果都是布尔值
true或者false
| 运算符 | 运算规则 | 示例 | 结果 |
| --- | --- | --- | --- |
|&| 与(有假为假)并且 | false&true | false |
||| 或(有真为真)或者 | false|true | true |
|^| 异或(相同为false,不同为true) | false^true | true |
|!| 非(取反,true为false,false为true) | !true | false |
|&&| 短路与(和&
一样,前面条件为false不执行后面的,效率高) | false&&true | false |
|||| 短路或(和|
一样,前面条件为true不执行后面的,效率高) | false||true | true |
3.4.2 代码示例
&:与;|:或;!:非;^:异或 ;
【代码示例】
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo13 {
public static void main(String[] args) {
// & 与: 有false则false,
System.out.println(false & false); // false
System.out.println(false & true); // false
System.out.println(true & false); // false
System.out.println(true & true); // true
System.out.println("‐‐‐‐‐‐‐‐‐‐‐");
// | 或: 有true则ture,
System.out.println(false | false); // false
System.out.println(false | true); // true
System.out.println(true | false); // true
System.out.println(true | true);// true
System.out.println("‐‐‐‐‐‐‐‐‐‐‐");
// ! 非: 取反
System.out.println(!true); // false
System.out.println(!false); // true
System.out.println("‐‐‐‐‐‐‐‐‐‐‐");
// ^ 异或: 相同为false,不同为true
System.out.println(false ^ false); // false
System.out.println(false ^ true); // true
System.out.println(true ^ false); // true
System.out.println(true ^ true);// false
}
}
3.4.3 特殊情况
短路运算和非短路运算的结果都是一样的,唯一的区别时短路运算在前面条件符合时是不会执行后面条件的,效率较高;非短路运算则不管前面运算结果如何而一定会执行后面的运算,在特定场景下会使用到;
1)短路与运算
- 短路与:
int a = 10;
int b = 10;
System.out.println(a != b && a++ > 10); // false
System.out.println(a); // 10
- 非短路与:
int a = 10;
int b = 10;
System.out.println(a != b & a++ > 10); // false
System.out.println(a); // 11
2)短路或运算
- 短路或:
int a = 10;
int b = 10;
System.out.println(a == b || a++ > 10); // true
System.out.println(a); // 10
- 非短路或:
int a = 10;
int b = 10;
System.out.println(a == b | a++ > 10); // true
System.out.println(a); // 11
3.5 三元运算符
- 三元运算符格式:
数据类型 变量名 = 布尔类型表达式 ? 结果1 : 结果2;

三元运算符计算方式:
- 布尔类型表达式结果是true,三元运算符整体结果为结果1,赋值给变量。
- 布尔类型表达式结果是false,三元运算符整体结果为结果2,赋值给变量。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo15 {
public static void main(String[] args) {
int a = 30;
int b = 30;
int c = a > b ? 100 : 20;
System.out.println(c);
}
}
三元运算符练习
- 判断两个数是否相同
- 获取两个数的较大值
3.6 位移运算
位移运算是对于"位"直接的运算,是将任何进制的数字先转化为2进制,之后再进行移位运算;位移运算分为有符号位移和无符号位移,其中有符号位移包含左位移和右位移,无符号位移只有右位移;
3.6.1 有符号位移
1) 左移位运算
- 正数的左移位:如10 << 2,右边自动补0,左边移出位舍弃,即
00001010 --> 00101000,结果是40。实际的意思是,每向左移动一位,就相当于乘以2
10: 00000000 00000000 00000000 00001010
10 << 2: 00000000 00000000 00000000 00101000 : 40
相当于: 10 * 2^2 = 40
- 负数的左移位:负数的左移与正数的左移一致,在右边自动补0。如-2<<2:
11111110 --->11111100,结果为-4。
对于负数的计算记得要转成补码来运算
-2: 11111111 11111111 11111111 11111110
-2 << 2: 11111111 11111111 11111111 11111000 : -8
相当于: -2 * 2^2 = -8
Tips:左位移N,就是乘以2^N
左位移运算代码:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo14_有符号位移_左位移运算 {
public static void main(String[] args) {
// 左位移N,就是乘以2^N
// 10 * 2^1
System.out.println(10 << 1); // 10 * 2 = 20
// 10 * 2^2
System.out.println(10 << 2); // 10 * 4 = 40
// 10 * 2^3
System.out.println(10 << 3); // 10 * 8 = 80
System.out.println("------------------");
// -10 * 2^1
System.out.println(-10 << 1); // -10 * 2 = -20
// -10 * 2^2
System.out.println(-10 << 2); // -10 * 4 = -40
// -10 * 2^3
System.out.println(-10 << 3); // -10 * 8 = -80
}
}
2) 右移位运算
- 正数的右移:如10 >> 2,左边自动补0,右边移出位舍弃,即
00001010 --> 00000010,结果是2,实际的意思是,每向右移动一位,就相当于除以2,小数舍弃,即10/2/2=2.5,舍弃小数,结果就是2。
10: 00000000 00000000 00000000 00001010
10 >> 2: 00000000 00000000 00000000 00000010 : 2
相当于: 10 / 2^2 = 2.5 = 2
4: 00000000 00000000 00000000 00000100
4 >> 2: 00000000 00000000 00000000 00000001 : 1
相当于: 4 / 2^2 = 1
- 负数的右移:如-2 >> 2,由于二进制的首位为符号位,负数在右移过程中,为了保持负数的特性,所以左边会自动补1而不是0,即
11111110 --> 11111111,结果为-1。
-2: 11111111 11111111 11111111 11111110
-2 >> 2: 11111111 11111111 11111111 11111111 : -1
相当于: -2 / 2^2 = -1(特殊情况)
-8: 11111111 11111111 11111111 11111000
-8 >> 2: 11111111 11111111 11111111 11111110 : -2
相当于: -8 / 2^2 = -2
Tips:有符号右位移N,就是除以2^N
有符号右位移代码:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo15_有符号位移_右位移运算 {
public static void main(String[] args) {
// 有符号右位移N,就是除以2^N
// 10 / 2^2
System.out.println(10 >> 2); // 2
// 4 / 2^2
System.out.println(4 >> 2); // 1
System.out.println("--------------------");
// -2 / 2^1
System.out.println(-2 >> 2); // -1
// -8 / 2^2
System.out.println(-8 >> 2); // -2
}
}
3.6.2 无符号位移
无符号右位移:所谓的无符号右移,就是无论是正数还是负数,高位通通补0。****另外无符号位移没有左位移运算。
如:-2 >>> 2,对于负数的有符号右移在左边自动补1,但是对于无符号右移,左边是自动补0。
- 1)对于正数而言,>>和>>>没区别。
2: 00000000 00000000 00000000 00000010
2 >>> 1: 00000000 00000000 00000000 00000001 : 1
相当于: 2 / 2^1 = 1
8: 00000000 00000000 00000000 00001000
8 >>> 2: 00000000 00000000 00000000 00000010 : 2
相当于: 8 / 2^2 = 2
- 2)但是对于负数而言:由于无符号右移位不管是正数还是负数,高位通通补0,这样下来就会出现这样的问题:
- -2 >>> 1:结果是2147483647(Integer.MAX_VALUE)
-2: 11111111 11111111 11111111 11111110
-2 >>> 1: 01111111 11111111 11111111 11111111(变为正数了) : 2147483647(int的最大值)
- -1 >>> 1:结果是2147483647(Integer.MAX_VALUE)
-1: 11111111 11111111 11111111 11111111
-1 >>> 1: 01111111 11111111 11111111 11111111(变为正数了) : 2147483647(int的最大值)
- -2 >>> 2:等于 Integer.MAX_VALUE / 2
-2: 11111111 11111111 11111111 11111110
-2 >>> 2: 00111111 11111111 11111111 11111110(变为正数了) : 1073741822
无符号右位移:
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo16_无符号位移运算 {
public static void main(String[] args) {
// 由于无符号右移都是在左边补0,因此对于正数而言和有符号位移是一样的,都是: 无符号右位移N,就是除以2^N
// 2 / 2^1
System.out.println(2 >>> 1); // 2 / 2 = 1
// 8 / 2^2
System.out.println(8 >>> 2); // 8 / 4 = 2
System.out.println("--------------------");
// 对于负数而言,在左边补0将会把负数变为了正数,因此无符号右移会出现非常大的int数
// 11111111 11111111 11111111 11111110 ---> 01111111 11111111 11111111 11111111(变为正数了)
System.out.println(-2 >>> 1); // 2147483647
// 11111111 11111111 11111111 11111111 ---> 01111111 11111111 11111111 11111111(变为正数了)
System.out.println(-1 >>> 1); // 1073741823
// 11111111 11111111 11111111 11111110 ---> 00111111 11111111 11111111 11111110(变为正数了)
System.out.println(-2 >>> 2); // 1073741823
}
}
Tips:左移位运算只有无有符号位移,没有无符号位移运算;
四、方法
4.1 方法概述
我们在学习运算符的时候,都为每个运算符单独的创建一个新的类和main方法,我们会发现这样编写代码非常的繁琐,而且重复的代码过多。能否避免这些重复的代码呢,就需要使用方法来实现。
简单来说Java方法是语句的集合,它们在一起执行一个功能。
- 方法:就是将一个功能抽取出来,把代码单独定义在一个大括号内,形成一个单独的功能。当我们需要这个功能的时候,就可以去调用。这样即实现了代码的复用性,也解决了代码冗余的现象。
4.2 方法的简单使用
4.2.1 方法的定义
- 定义格式:
修饰符 返回值类型 方法名(参数列表){
逻辑代码...
return 返回值;
}
- 定义格式解释:
- 修饰符: 目前固定写法
public、static。 - 返回值类型: 方法运行结果的数据类型,如果该方法没有返回值,那么请声明为
void - 方法名:满足标识符的规范,用来调用方法。
- 参数列表:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 修饰符: 目前固定写法
- 举例:
public static void methodName() {
System.out.println("这是一个方法");
}
4.2.2 方法的调用
方法在定义完毕后,方法不会自己运行,必须被调用才能执行,我们可以在主方法main中来调用我们自己定义好的方法。在主方法中,直接写要调用的方法名字就可以调用了。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo16 {
public static void main(String[] args) {
// 调用方法
methodName();
}
public static void methodName() {
System.out.println("这是一个方法");
}
}
4.2.3 调用练习
需求:定义一个方法利用三元运算符求3个数的最大值。
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo17 {
public static void main(String[] args) {
operato();
}
// 这个方法可以帮助我们求三个数的最大值
public static void operation() {
int a = 100;
int b = 50;
int c = 80;
int temp = a > b ? a : b;
int result = temp > c ? temp : c;
System.out.println("这三个数的最大值为: " + result);
}
}
4.2.4 注意事项
方法定义注意事项:
- 方法必须定义在一个类中方法外
- 方法不能定义在另一个方法的里面
public class Demo {
public static void main(String[] args) {
}
//正确位置,类中方法外
public static void method(){
}
}
错误示例:
public class Demo {
public static void main(String[] args) {
//错误写法
public static void method(){
}
}
}
4.3 方法使用进阶
4.3.1 方法的参数列表和返回值
需求:定义方法实现两个整数的求和计算。
- 明确返回值类型:方法计算的是整数的求和,结果也必然是个整数,返回值类型定义为int类型。
- 明确参数列表:计算哪两个整数的和,并不清楚,但可以确定是整数,参数列表可以定义两个int类型的
变量,由调用者调用方法时传递
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo17 {
public static void main(String[] args) {
int max = operation3(20, 18, 40);
System.out.println("最大值为: "+max);
}
// 计算任意三个数的最大值,并且将结果返回给调用者
public static int operation3(int a, int b, int c) {
int temp = a > b ? a : b;
int result = temp > c ? temp : c;
return result;
}
// 计算任意三个数的最大值
public static void operation2(int a, int b, int c) {
int temp = a > b ? a : b;
int result = temp > c ? temp : c;
System.out.println("a的值为: " + a);
System.out.println("b的值为: " + b);
System.out.println("c的值为: " + c);
System.out.println("最大值为: " + result);
}
}
- 方法信息详解:

- 方法调用详解:

4.3.2 调用方法的三种形式
public static void main(String[] args) {
print();
}
public static void print() {
System.out.println("方法被调用");
}
赋值调用:调用方法,在方法前面定义变量,接收方法返回值
public static void main(String[] args) {
int sum = getSum(5,6);
System.out.println(sum);
}
public static int getSum(int a,int b) {
return a + b;
}
输出语句调用:在输出语句中调用方法, System.out.println(方法名()) 。
public static void main(String[] args) {
System.out.println(getSum(5,6));
}
public static int getSum(int a,int b) {
return a + b;
}
不能用输出语句调用void 类型的方法。因为方法执行后没有结果,也就打印不出任何内容。
4.3.3 方法的重载
- 方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关(即使修饰符和返回值列表不一样也不属于重载)
- 参数列表不同:个数不同,数据类型不同,顺序不同。
有时候我们在一个类中定义多个方法,这些方法的功能差不多是一样的,我们就不希望取其他方法名,只要保证这几个方法的参数列表不同即可,这就是方法的重载;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo06_方法的重载 {
public static void main(String[] args) {
int maxInt = max(40, 80);
System.out.println("最大值为: " + maxInt);
double maxDouble = max(80.8D, 90.2D);
System.out.println("最大值为: " + maxDouble);
}
// 这个方法可以比较两个int数
public static int max(int a, int b) {
int result = a > b ? a : b;
return result;
}
// 这个方法可以比较两个double数
public static double max(double a, double b) {
double result = a > b ? a : b;
return result;
}
}
我们发现求2个int数的最大值和2个double数的最大值功能是一样的,其意思也差不多;如果定义不同的方法名使用起来不方便,我们给方法命名最好能够见名知意;这个时候我们就希望定义成一样的名称,就是方法的重载;

4.3.4 方法重载练习
练习一
比较两个数据是否相等。参数类型分别为两个 byte 类型,两个 short 类型,两个 int 类型,两个 long 类型,并在 main 方法中进行测试。
public class Method_Demo6 {
public static void main(String[] args) {
//定义不同数据类型的变量
byte a = 10;
byte b = 20;
short c = 10;
short d = 20;
int e = 10;
int f = 10;
long g = 10;
long h = 20;
// 调用
System.out.println(compare(a, b));
System.out.println(compare(c, d));
System.out.println(compare(e, f));
System.out.println(compare(g, h));
}
// 两个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;
}
}
练习二
判断哪些方法是重载关系。
public static void open(){}
public static void open(int a){}
static void open(int a,int b){}
public static void open(double a,int b){}
public static void open(int a,double b){}
public void open(int i,double d){}
public static void OPEN(){}
public static void open(int i,int j){}

浙公网安备 33010602011771号