Java 程序基本结构
首先我们来看一个完整的 Java 例子:
public class Demo {
public static void main(String[] args) {
System.out.println("我想学习Java!");
}
}
我们来对这个 Java 程序进行解析:
- public 是访问修饰符,表示该类是公开的。如果不写 public,也能正确编译,但是这个类将无法从命令行执行,将在后面的实训中详细介绍;
- class 是关键字,表示这是一个类;
- Demo 是这个 Java 程序的名称(类名),Java 中对定义类名有一定的要求。要求如下:
- 类名必须以英文字母开头,后接字母,数字和下划线的组合;
- Java 程序中良好的命名习惯通常是以大写字母开头来命名类名,如果类名由多个单词组成,每个单词的第一个字母都应该大写。例如:Student、OutputTriangle 等。
注意:1.你创建的 Java 文件的名称必须和类名一致。例如这个例子的代码文件名称为 Demo.java;2.我们在日后的编码中要注意遵守命名习惯。 在类内部,可以定义若干方法(method),如下所示:
public static void main(String[] args) {
System.out.println("我想学习Java!");
}
上面的代码示例定义了一个方法,该方法命名 main,Java 的执行语句必须放在方法内部,这些语句将会被依次顺序执行;这个方法 main 的返回值类型是 void,表示没有任何返回值。
关键字 static 也是一个修饰符,它表示静态方法,后面我们会讲解方法的类型,目前,我们只需要知道,public static void main(String[] args){}
是 Java 的入口程序,在我们目前的基础阶段,所有的代码都需要写在这里。
当然,方法名也有命名规则,和类一样,但是首字母是小写。
在方法内部,语句才是真正的执行代码。Java 的每一行语句必须以分号结束。
public static void main(String[] args) {
System.out.println("我想学习Java!");
}
至此,我们对 Java 基本程序结构就有了初步的了解。而在上面,我们会发现一个名词:“关键字”,大家对此会有些疑惑:在 Java 中的关键字是什么,又有哪些是关键字呢?
关键字
关于关键字你只需要记住一点:Java 关键字就是 Java 语言中已经被赋予特定意义的一些单词。
怎么理解呢?你可以设想一下你家新装修买了一扇门,你能叫这扇门为"天安门"吗?显然不能,在这里"天安门"就是关键字,就是一个被赋予了特殊意义的词。
图 1 列出了 Java 常用的一些关键字。
图1
大家可能会问:这么多我记不住怎么办?
没关系,现在你只需要混个脸熟就可以了,在后面的学习中不需要刻意的去记就能自然而然的记住了。
注意事项:Java 关键字是区分大小写的哦!所以 void 是关键字,但 Void 就不是了, public 是关键字 Public 就不是了~~
在 Java 的编写过程中我们还需要对一些程序进行注释,除了方便自己阅读外,更可以让别人更好地理解自己的程序,所以我们需要进行一些注释,注释内容可以是编程思路,也可以是程序的功能,总而言之就是方便自己和他人更好的阅读。
注释
在 Java 程序中,注释是一种给人阅读的文本,不是程序的一部分,所以编译器会自动忽略注释,Java 语言支持三种注释方式,它们分别是:
//
单行注释;/* */
多行注释;/** */
说明注释。
他们在 Java 程序中怎么使用呢?
例子:
/**我是说明注释
* 这是我的第一个 Java 程序
* @author admin
* @version 1.2
*/
public class Demo { // Demo 是类名
public static void main(String[] args) { // 程序主方法,方法名为 main
// 我是单行注释
System.out.println("Hello world!");
/* 多行注释开始
注释内容
注释结束 */
}// main 方法结束
} // 类定义结束
通过上面的学习,我们对 Java 的结构以及语法规则已经有了一定了解,接下来我们将正式开始 Java 代码的编写。
输出方法
我们如何向显示器输出我们想要的内容呢?
System.out.print("");
:将我们想要输出的内容放入双引号之间,该语句便可以将其输出到显示器。
语法如下:
/**
*输出内容
*@author admin
*类名:Demo
*/
public class Demo {
//在主方法 main 中编写执行语句
public static void main(String[] args) {
//main 方法内部
System.out.print("我想学习Java!");// 输出:我想学习Java!
}// main 方法结束
}// 类定义结束
执行结果:我想学习Java!
。
当我们想要输出多段话时:
/**
*输出内容
*
*/
public class Demo {
public static void main(String[] args) {
System.out.print("我想学习Java!");
System.out.print("我一定会好好学习的。");
System.out.print("毛主席说:“好好学习,天天向上。”");
}
}
执行结果:我想学习Java!我一定会好好学习的。毛主席说:“好好学习,天天向上。”
。
我们会发现该方法并不能帮我们换行输出,那又该怎么办呢?
System.out.println("");
:该语句与System.out.print("");
用法一致,都可以将内容输出,不同的是该语句输出后会进行换行。
public class Demo {
public static void main(String[] args) {
System.out.println("我想学习Java!");// 换行输出
System.out.println("我一定会好好学习的。");// 换行输出
System.out.println("毛主席说:“好好学习,天天向上。”");// 换行输出
}
}
执行结果如下
我想学习Java!
我一定会好好学习的。
毛主席说:“好好学习,天天向上。”
我们从执行结果中看到最后会有一个空行,正是因为该方法会在输出后进行换行。
在上面的输出中,我们会发现该程序从上到下逐行地执行。Java 中语句执行顺序是由控制结构来决定的。
控制结构
在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的,不同的控制结构具有不同的语句执行顺序。所以,我们必须清楚不同控制结构的语句执行顺序。
Java 的控制结构有三种,分别是顺序结构、分支结构和循环结构。
顺序结构
顺序结构是程序中最简单最基本的流程控制,程序代码按照书写顺序从上到下逐行地执行。程序中大多数的代码都是这样执行的。总的来说:写在前面的先执行,写在后面的后执行。
例子:我们打印一个高为 3 底为 5 的直角三角形。
代码如下:
public class Demo {
public static void main(String[] args) {
System.out.println(" *");// 这一行换行输出由4个空格和1个*组成的字符串常量
System.out.println(" ***");// 这一行换行输出由2个空格和3个*组成的字符串常量
System.out.print("*****");// 这一行输出由5个*组成的字符串常量,不换行。
}
}
执行结果如下:
*
***
*****
我们上面的例子便是一个顺序结构的程序代码。
我们将在后面的实训中为大家详细介绍分支结构和循环结构,这里就不做介绍了。
字符串常量
Java 中使用双引号表示字符串常量,例如:"我想学习Java!"。它是一个不变的值,即这个符号所表示的值是无法被改变的。这里的常量实际上是字面常量。
字符串常量中出现的字符,例如'我'、'a'、'!',在计算机中以特定的编码形式表示。Java 使用 Unicode 字符集,我们常用的字符编码形式主要有适用于西文符号的 ASCII 码和适用于中文符号的汉字机内码(来自于国标码 GB2312)。
Unicode 字符集
全世界有上百种语言,各国有各国的标准,会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
因此,Unicode 应运而生。Unicode 把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
Unicode 是用 0 至 65535 之间的数字来表示所有字符。其中 0 至 127 这 128 个数字表示的字符仍然跟 ASCII 完全一样。大部分汉字的 Unicode 编码在 4E00-9FA5 范围内。具体的符号对应表,可以查询 unicode.org ,或者专门的汉字对应表。
需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制代码,并没有规定这个二进制代码应该如何存储。
标识符
在上一个实训中,我们对变量和类名的命名规则已经有了一定的了解,而它们都属于标识符,下面我们来看一下标识符的命名规则吧。
命名规则:
- 标识符必须以字母、下划线 _ 、或美元符 $ 开头(这里的字母并不单单指英文字母,中文也可以,但是我们并不推荐);
- 标识符其它部分可以是字母、下划线 _ 、美元符 $ 和数字的任意组合;
- Java 标识符大小写敏感,且长度无限制;
- 不可以是 Java 的关键字。
另外:表示类名和接口名的标识符用大写字母开始,如:Person,Student 等;表示方法和变量的标识符用小写字母开始,后面的描述性词以大写开始,如:playGames(),studyEnglish() 等等。
接下来我们讲解什么是变量,什么是常量,以及它们在 Java 程序中的使用。
变量和常量
变量和常量,有一个共同的属性:量。量是一种传递数据的介质,量的实质是“值”。而有些量在程序的运行过程中会发生改变,有些量在程序运行过程中值不能发生改变,这些数据在程序中分别被叫做变量和常量。例如,我们在数学中学过的圆的周长:C=2πr,其中C和r就是其中的变量,而 2 和 π就是其中的常量。
在实际的程序中,可以根据数据在程序运行中是否发生改变,来选择应该是使用变量表示还是常量表示。
现在,大家对变量和常量的概念应该已经有了基本的了解,那变量和常量在 Java 中又是怎么定义的呢?
声明变量
为了方便的引用变量的值,在程序中需要为变量设定一个名称,这就是变量名。Java 语言要求变量在使用以前必须首先声明,在程序中声明变量的语法格式如下:
[修饰符] 数据类型 变量名;
修饰符是可选的,我们在后面的实训中会进行详细的介绍。数据类型和变量名之间使用空格进行间隔(空格的个数不限,但是至少需要一个),声明语句使用“;”作为结束。也可以在声明变量的同时,设定该变量的值,语法格式如下:
数据类型 变量名 = 值;
在程序中,变量的值代表程序的状态,在程序中可以通过变量名来引用变量中存储的值,也可以为变量重新赋值,语法格式如下:
数据类型 变量名1 = 值1;
变量名1 = 值2;
当需要声明多个同类型的变量时,我们还可以使用如下格式:
数据类型 变量名1 = 值1,变量名2 = 值2,……变量名n = 值n;
在变量的声明语法中,我们会看到“数据类型”这个名词,它是什么呢,在 Java 又扮演了怎么样的角色呢?
数据类型
Java 语言支持的数据类型分为两种:基本数据类型(Primitive Type)和引用数据类型(Reference Type)。
Java 语言提供的基本数据类型共有八种,包括六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型,详细见下表。
数据类型 | 描述 | 占用字节 | 取值范围 | 默认值 |
byte | Java中最小的数据类型, | 1个字节 | -128127(-2^72^7-1) | 0 |
int | 整型,用于存储整数 | 4个字节 | -2147483648~2147483647 | 0 |
short | 短整型 | 2个字节 | -32768~32717 | 0 |
long | 长整型 | 8个字节 | -2^63~2^63-1 | 0L |
float | 浮点型,用于存储带小数点的数字 | 4个字节 | / | 0.0f |
double | 双精度浮点型,用于存储带有小数点的数字 | 8个字节 | / | 0.0d |
char | 字符型,用于存储单个字符 | 2个字节 | 0~65535 | 空 |
boolean | 布尔类型,用于判断真或假 | 1个字节 | 仅有两个值,即true、false | false |
注:一个字节等于 8 位(bit)
int
int 数据类型是 32 位、有符号的以二进制补码表示的整数;一般地整型变量默认为 int 类型,具体实例如下:
// 声明一个变量名为 a,数据类型为 int 的变量,并赋予该变量的值为 30000
int a = 30000;
// 声明一个变量名为 b,数据类型为 int 的变量,并赋予该变量的值为 -1200
int b = -1200;
// 输出 a,b 两个变量
System.out.println(a);
System.out.print(b);
执行结果如下:
30000
-1200
byte
byte 数据类型是 8 位、有符号的,以二进制补码表示的整数;该类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一,具体实例如下:
// 声明一个变量名为 a,数据类型为 byte 的变量,并赋予该变量的值为 100
byte a = 100;
// 声明一个变量名为 b,数据类型为 byte 的变量,并赋予该变量的值为 -50
byte b = -50;
// 输出 a,b 两个变量
System.out.println(a);
System.out.print(b);
执行结果如下:
100
-50
short
short 数据类型是 16 位、有符号的以二进制补码表示的整数;short 数据类型也可以像 byte 那样节省空间。一个 short 变量是 int 型变量所占空间的二分之一,具体实例如下:
// 声明一个变量名为 a,数据类型为 short 的变量,并赋予该变量的值为 1800
short a = 1800;
// 声明一个变量名为 b,数据类型为 short 的变量,并赋予该变量的值为 -600
short b = -600;
// 输出 a,b 两个变量
System.out.println(a);
System.out.print(b);
执行结果如下:
1800
-600
long
long 数据类型是 64 位、有符号的以二进制补码表示的整数;这种类型主要使用在需要比较大整数的系统上,具体实例如下:
// 声明一个变量名为 a,数据类型为 long 的变量,并赋予该变量的值为 1800000
long a = 1800000L;
// 声明一个变量名为 b,数据类型为 long 的变量,并赋予该变量的值为 -6000000
long b = -6000000L; //'L'和'l'均可,但小写容易与数字1混淆,建议大写;也可省略
// 输出 a,b 两个变量
System.out.println(a);
System.out.print(b);
执行结果如下:
1800000
-6000000
这四个数据类型就是 Java 数据类型中的整型,接下来讲解浮点型的数据类型。
float
float 数据类型是单精度、32 位的浮点数;float 在储存大型浮点数组的时候可节省内存空间,具体实例如下:
// 声明一个变量名为 a,数据类型为 float 的变量,并赋予该变量的值为 2.35
float a = 2.35f; // 定义float类型变量的时候赋值,该值后面必须加上f
// 声明一个变量名为 b,数据类型为 float 的变量,并赋予该变量的值为 -5.894
float b = -5.894f;
// 输出 a,b 两个变量
System.out.println(a);
System.out.print(b);
执行结果如下:
2.35
-5.894
double
double 数据类型是双精度、64 位的浮点数;浮点数的默认类型为 double 类型,具体实例如下:
// 声明一个变量名为 a,数据类型为 double 的变量,并赋予该变量的值为 1800.50d 这个d可写可不写。
double a = 1800.50d;
// 声明一个变量名为 b,数据类型为 double 的变量,并赋予该变量的值为 -600.47
double b = -600.47;
// 输出 a,b 两个变量
System.out.println(a);
System.out.print(b);
执行结果如下:
1800.5
-600.47
注意:这些类型的值在定义的时候不能超过它的范围,如果超过将会报错。
以上就是我们的浮点型和整型的数据类型了,Java 的基本数据类型还有字符型和布尔型,我们在后面的实训中会详细讲解。
我们已经了解了 Java 中的一些数据类型,现在我们继续回到变量这里。
在 Java 中,对于变量我们又有哪些要注意的呢?
- 在 main 方法中不能定义两个同名变量;
- Java 中的每个变量必须先声明,后使用;
- 在一行上可以定义多个变量,但建议只定义一个变量;
- 变量一次只能赋一个值,但可以修改多次。
对于变量,我们这节就讲到这里,接下来我们来看常量。
声明常量
在程序运行过程中一直不会改变的量,称为常量。其在整个程序中只能被赋值一次。
常量在程序中主要有 2 种表现形式:
- 字面常量:代表常数,便于程序的修改(例如:圆周率的值 3.1415926);
- 符号常量:增强程序的可读性(例如:常量 UP、DOWN、LEFT 和 RIGHT 分别代表上下左右,其数值分别是 1、2、3 和 4)。
常量一般分为以下几种:字符串常量、整型常量、浮点常量、字符常量、布尔常量和空常量。字符串常量我们在上一个实训中已经有了了解,本实训主要讲解整型常量和浮点型常量。
- 整数常量,直接写上数字,没有小数点,比如:10,20,30,50 等。
- 浮点常量,直接写上的数字,有小数点。其实可以把浮点常量比作小数,比如 4.5,5.6,7.8 等。
例子:
public class Demo {
public static void main(String[] args) {
System.out.println(12);// 12为整型常量
System.out.print(3.57);// 3.57为浮点型常量
}
}
执行结果:
12
3.57
在我们的生活中,我们会经常碰到两个数的加,减,乘,除,那么我们在 Java 当中又如何进行计算呢?
算术运算符
算术运算符主要用于进行基本的算术运算,如加法、减法、乘法、除法、赋值等。 Java 中常用的算术运算符:
算术运算符 | 名称 | 举例 |
+ | 加法 | 5+2=17 |
- | 减法 | 5-2=3 |
* | 乘法 | 5*2=10 |
/ | 除法 | 8/5=1,8.0/5=1.6 |
我们将通过下面的这些例子为大家详细讲解。
public class Demo {
public static void main(String[] args) {
// 定义一个int型的变量a,将其赋值为100
int a = 100;
// 定义一个int型的变量b,将其赋值为84
int b = 84;
// 定义一个 double 型的变量c,将其赋值为25.4
double c = 25.4;
//将变量a与变量b相加,然后输出
System.out.println(a+b);
// 将变量a与变量c相减,然后输出
System.out.println(a-c);
// 将变量a与变量b相乘,然后输出
System.out.println(a*b);
// 将变量a与变量b相除,然后输出
System.out.println(a/b);
// 将变量a与变量c相除,然后输出
System.out.println(a/c);
// 输出a*c-a/b+c的值
System.out.print(a*c-a/b+c);
}
}
执行结果如下:
184
74.6
8400
1
3.937007874015748
2564.4
我们发现 a/b 的为 1 ,是因为 / 并不是我们理解上的除法,当两个数都是整型的时候,它实际上是求整,也就是说它算出来的是商,因为两个整型相除,返回结果依然还是整型,它并不会保留小数部分,所以得到的是商。而一个整型和一个浮点型相除时得到的就是一个正常的除法运算值。
通过上面的练习,我们会发现 Java 中的运算顺序跟我们数学中的也是一样的,先算乘除再算加减。那如果我们想要先算加减,再算乘除怎么办呢?我们可以使用圆括号。
// 定义一个int型的变量a,将其赋值为100
int a = 100;
// 定义一个int型的变量b,将其赋值为84
int b = 84;
// 定义一个 double 型的变量c,将其赋值为25.4
double c = 25.0;
System.out.print((a+b)/c);
执行结果:
7.36
所以,最终的优先级是有圆括号的先算圆括号里面的,再算乘除,最后算加减。
注意:这些值在进行运算时不要超过它的范围,如果超出会产生数据溢出。
而赋值运算符又是怎样的呢?
基本的赋值运算符是“=”。他的优先级别低于其他的运算符,所以对该运算符往往最后读取。例如我们定义变量的时候给其赋值。
int a = 10;
复合的赋值运算符,又称为带有运算的赋值运算符,也叫赋值缩写。
运算符 | 名称 | 举例 | 等价于 |
+= | 加赋值 | n+=25 | n=n+25 |
- | 减赋值 | n-=25 | n=n-25 |
* | 乘赋值 | n*=25 | n=n*25 |
/ | 除赋值 | n/=25 | n=n/25 |
例子:
int a = 3;// 把右边的常量值赋值给左边的变量
a += 4;// 把左右两边相加的结果,赋值给左边,相当于 a = a + 4;
System.out.print(a);
执行结果:
7
它首先会进行加法运算 a+4,再将运算结果赋值给变量 a。
整型数据与整型数据进行运算时,谁的数据类型的范围大,数据类型就会变为谁的。浮点数据也是如此。当浮点数据类型与整形进行运算后,其数据类型都会变为该浮点数据类型。关于数据类型的转换,我们将会在后面的实训中详细介绍。
上面我们讲到了变量之间的运算,那如果我想要将两个字符串常量进行拼接又该怎么办呢?
例子:
public class Demo {
public static void main(String[] args) {
// 使用 + 可以将两个字符串常量进行拼接
System.out.println("我喜欢你"+"祖国!");
System.out.print("早上好"+",小明");
}
}
执行结果如下:
我喜欢你祖国!
早上好,小明
% 运算符及其优先级
在前面的实训中,我们学习了 Java 中的加减乘除运算符的使用,那在 Java 中又是如何获取除法运算的余数呢?
例子:
1.18/5 的余数是多少?
public class Demo {
public static void main(String[] args) {
// Java 中的 % 可以用来求两数之间的余数,将这个余数赋值给变量a
int a = 18 % 5;
System.out.print(a);
}
}
执行结果:3
。
2.已知春夏秋冬分别用 1、2、3、4 表示,现在是春季,那么请问 24 个季节后是什么季节呢?
public class Demo {
public static void main(String[] args) {
// 声明 int 型变量 pre,用于表示季节种类
int pre = 4;
// 声明 int 型变量 sum,用于表示多少季节后加上当前季节的值
int sum = 24 + 1;
// 求季节总数除以季节种类的余数
int season = sum % pre;
System.out.print(season);
}
}
执行结果:1
我们发现最后结果为 1,1 是春季的值,所以 24 个季度后就是春季。
那 % 在Java 运算符的优先级又是怎样的呢?
我们来做一个实验:分别求取 48%7/2 和 48/3%7 的值为多少?
public class Demo {
public static void main(String[] args) {
int a = 48%7/2;
int b = 48/3%7;
System.out.println(a);
System.out.print(b);// 最后一行结果输出时不换行
}
}
执行结果:3
2
我们看到输出的结果分别为 3 和 2,由此得出 % 和乘除的优先级是一样高的,谁在前面便先执行谁,其次为加减。
格式化输出
如果我们想要输出x的值为:100,d的值为:23.496
这种格式,除了之前学过的两种输出方式外,Java 中还有一种输出命令,而且比以上两种更为复杂、强大,那就是System.out.printf
。它可以控制 tab 制表符、数字保留多少小数等,可以让输出更加规范和更加美观。
格式控制字符 | 结果 |
%d | 整数 |
%8d | 整数,左对齐,输出宽度为 8 |
%-6d | 整数,右对齐,输出宽度为 8 |
%f | 浮点数 |
%.2f | 浮点数,四舍五入后保留两位小数 |
%8.2f | 浮点数,四舍五入后保留两位小数,左对齐,输出宽度为8 |
示例:
int x = 100;
double d = 23.496;
//一般输出方式:
System.out.println("x的值为:"+x+",d的值为:"+d);
//格式化输出方式:
System.out.printf("x的值为:%d,d的值为:%f",x,d);
执行结果:
x的值为:100,d的值为:23.496
x的值为:100,d的值为:23.496000
它的基本格式:格式控制符以一个 % 开始,一个字母结束,字母规定了方法按照何种方式打印这个值,例如 d 表示十进制整数(int),f 表示浮点数(double)。%d 和 %f 代替后面的参数,格式字符串中的格式控制字符的个数必须与后面提供的参数个数相匹配。
在 % 和转换代码之间可以插入一个整数来表示转换后的值的宽度,即输出字符串的长度。默认情况下,转换后会在字符串的左边添加空格以达到需要的长度,如果我们想在右边加入空格则应该使用负宽度(转换得到的字符串的宽度比设定的要长,宽度会被忽略)。
int x = 100;
double d = 23.496;
System.out.printf("x的值为:%6d,d的值为:%-12f。",x,d);
执行结果:
x的值为: 100,d的值为:23.496000 。
在宽度之后我们还可以插入一个小数点以及一个数值,来指定转换后的 double 值保留的小数位数(精度、四舍五入)。
double d = 23.496;
System.out.printf("d的值为:%.2f。",x,d);
执行结果:
d的值为:23.50。
如果想要换行输出怎么办呢?我们可以采用转义字符。
所有的 ASCII 码都可以用“\”加数字(一般是 8 进制数字)来表示。而 Java 中定义了一些字母前加“\”来表示常见的那些不能显示的 ASCII 字符,如 \0,\t,\n 等,就称为转义字符,因为后面的字符,都不是它本来的 ASCII 字符意思了。如下是一些常见的转义符。
转义字符 | 意义 | ASCII码值(十进制) |
\b | 退格(BS) ,将当前位置移到前一列 | 008 |
\n | 换行(LF) ,将当前位置移到下一行开头 | 010 |
\r | 回车(CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表(HT) (跳到下一个TAB位置) | 009 |
\\ | 代表一个反斜线字符''' | 092 |
\' | 代表一个单引号(撇号)字符 | 039 |
\" | 代表一个双引号字符 | 034 |
\? | 代表一个问号 | 063 |
\0 | 空字符(NUL) | 000 |
在输出语句中采用换行的转义符:
double d = 23.496;
System.out.print(d+"\n");
System.out.printf("d的值为:%.2f。\n",x,d);
执行结果:
23.496
d的值为:23.50。
Scanner 类 reader 对象
我们在使用 Java 写代码时,如果想要实现输入操作怎么办呢,这时候我们需要用到的是 Scanner 类来实现获取用户从键盘上的输入操作。
Scanner 类是一个基于正则表达式的文本扫描器,它可以从文件、输入流、字符串中解析出基本类型值和字符串值;Scanner 类可以任意地对字符串和基本类型(如 int 和 double )的数据进行分析。
当我们引入 Scanner 这个类的时候,我们需要导入java.util.Scanner
这个类。
使用 import 导入类
如果我们要使用其他包的类,需要使用 import 导入,从而可以在本类中直接通过类名来调用,否则就需要书写类的完整包名和类名。import 导入包后,便于编写代码,提高可维护性。
注意:Java 会默认导入 java.lang 包下所有的类,因此这些类我们可以直接使用,例如 System、Math 都是 java.lang 包下的类。
例子:
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
}
}
导入了这个类以后,我们就可以使用 Scanner 这个类了。现在我们来使用该类创建一个 Scanner 的实例对象。
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
// 创建一个Scanner的实例对象,这个对象可以为用户提供输入,将这个实例对象命名为reader,后面我们可以直接用reader调用Scanner类的相关方法
Scanner reader = new Scanner(System.in);
}
}
Scanner 类提供了两种方法来获取输入,这两种方法分别是:
- nextXXX():获取用户输入的内容,其中 XXX 可以用来表示 int,long,double 等代表基本数据类型,需要注意的是,如果我们是获取输入的字符串,那么我们可以直接使用 next()。
例子:
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
// 创建一个Scanner的实例对象,这个对象可以为用户提供输入,将这个实例对象命名为reader,后面我们可以直接用reader调用Scanner类的相关方法
Scanner reader = new Scanner(System.in);
// 从键盘处接收用户输入的浮点型数据
double a = reader.nextDouble();
System.out.print("输入的数据为:" + a);
}
}
假设用户键盘输入的数据为:10.0
。
注意:输入完数据后需要回车,而且你定义的数据类型不能小于键盘输入的数据类型,例如这里你键盘输入的是 10.0,那你这里就不能用整型接收,只能用浮点型接收。
执行结果:
输入的数据为:10.0
如果想要从键盘获取多个值又该怎么办呢?
例子:
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
// 创建一个Scanner的实例对象,这个对象可以为用户提供输入,将这个实例对象命名为reader,后面我们可以直接用reader调用Scanner类的相关方法
Scanner reader = new Scanner(System.in);
// 从键盘处接收用户第一次输入的浮点型数据
double a = reader.nextDouble();
// 从键盘处接收用户第二次输入的整型数据
int b = reader.nextInt();
System.out.println("第一次输入的数据为:" + a);
System.out.print("第二次输入的数据为:" + b);
}
}
用户第一次键盘输入的数据为:20.0
。回车 用户第二次键盘输入的数据为:55
。回车
执行结果:
第一次输入的数据为:20.0
第二次输入的数据为:55
- hasnextXXX():表示是否还有下一个输入项,其中 XXX 与上个方法一致,我们会在后面详细介绍。
Java 的 Math 类中提供了的方法可以很方便的实现本关任务。
下面我们来介绍几个 Math 类中常用的方法。 #####Math 类
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如平方、对数、平方根和三角函数等。下表为 Math 类的一些常用方法。
方法 | 描述 |
abs(x) | 返回参数x的绝对值,不改变x的数据类型 |
sqrt(x) | 计算x的平方根,返回值为 double |
cbrt(x) | 计算x的立方根,返回值为 double |
floor(x) | 返回小于x的最大整数,返回类型为 double |
ceil(x) | 返回大于等于x的的最小整数,返回类型为 double |
round(x) | 将x四舍五入取整,返回值为 long |
pow(x,y) | 计算x的y次方,返回类型为 double |
max(x,y) | 计算x和y的最大值,返回类型为 double |
min(x,y) | 计算x和y的最小值,返回类型为 double |
sin(x) | 求x的正弦值 |
cos(x) | 求x的余弦值 |
tan(x) | 求x的正切值 |
asin(x) | 求x的反正弦值 |
acos(x) | 求x的反余弦值 |
atan(x) | 求x的发正切值 |
toDegrees(x) | 将x转化为角度 |
toRadians(x) | 将x转换为弧度 |
PI | π |
接下来为大家详细介绍该类的一些常用方法。
立方根
在之前的实训中我们知道了求平方根的方法,现在我们来讲解求立方根的方法。
例子:求 ∛27 的值。
Math.cbrt(x)
可以求取立方根的结果,x 既可以是整型也可以是浮点型。
int a = 27;
double cbrt = Math.cbrt(a);
System.out.print(cbrt);
执行结果:
3.0
绝对值
例子:求 ∣−3.5∣ 的值。
Math.abs(x)
可以求取 x 的绝对值,x 既可以是整型也可以是浮点型。
double a = -3.5;
double abs = Math.abs(a);
System.out.print(abs);
执行结果:
3.5
取整
Math.ceil(x)
、Math.floor(x)
和Math.round(x)
都可以求取 x 的整数,x 既可以是整型也可以是浮点型,不过它们取整的方式不同。
Math.ceil(x)
返回大于等于给定参数的的最小整数。
double a = 3.8;
double b = 3.1;
double ceil1 = Math.ceil(a);
double ceil2 = Math.ceil(b);
System.out.println(ceil1);
System.out.print(ceil2);
执行结果:
4.0
4.0
Math.floor(x)
返回小于目标函数的最大整数。
double a = 3.8;
double b = 3.1;
double floor1 = Math.floor(a);
double floor2 = Math.floor(b);
System.out.println(floor1);
System.out.print(floor2);
执行结果:
3.0
3.0
Math.round(x)
四舍五入取整。
double a = 3.8;
double b = 3.1;
long round1 = Math.round(a);
long round2 = Math.round(b);
System.out.println(round1);
System.out.print(round2);
执行结果:
4
3
比较大小
Math.max(x,y)
、Math.min(x,y)
都可以比较 x 和 y 的大小,x、y 既可以是整型也可以是浮点型,不过它们一个返回最大值,一个返回最小值。
double a = 3.8;
double b = 3.1;
double max = Math.max(a,b);
double min = Math.min(a,b);
System.out.println(max);
System.out.print(min);
执行结果:
3.8
3.1
三角函数
例子:
double a = 30;// 定义一个变量a,用来表示角度为30°
// Math.toRadians可以将角度转化为弧度。也就是将30度转化为π/6。
double b = Math.toRadians(a);// 定义一个变量b,用来表示弧度。
// Math.sin 可以算出该弧度对应的正弦值。
double sin = Math.sin(b)
System.out.print(sin);
执行结果:0.49999999999999994
然而结果并不是我们所熟知的 0.5,这是为什么呢?
// 输出 Math 类中π的值
System.out.print(Math.PI);
执行结果:3.141592653589793
可以看出 Math 类中 π 的值是精简后的,而前面的30°转化为6π的值也会有所不同,所以得出的结果有误差。
那根据正弦值又怎么得出它的角度呢?
// Math.asin可以将正弦值转化为反正弦值,这里的 sin 采用上面这个例子求出的sin值。
double asin = Math.asin(sin);
// Math.toDegrees可以将其转化为角度
double d=Math.toDegrees(asin);
System.out.println(d);
执行结果:29.999999999999996
基本数据类型转换
在 Java 开发之中,经常会涉及到不同类型数据之间进行相互转换。那 Java 之间又是如何转换数据类型的呢?
Java 中数据类型的转换有两种:
- 自动转换;
- 强制转换。
首先我们得需要知道 Java 基本数据类型之间的范围大小。
Java 中整型和浮点型按照范围从小到大:
byte -> short -> int -> long -> float -> double
字符型转换为整型: char -> int
自动转换
自动类型转换 (也叫隐式类型转换) ,其实就是小范围的数据类型向大范围的数据类型转换,你可以想象一下,把一杯水往一个容积大的空桶中倒进,水不会流出来。
注意:自动类型转换的前提条件,必须是把数据类型范围小的数值或变量赋给数据类型范围大的变量。
例子:
int d = 100;
// 当一个 int 类型和一个 long 型相加时,类型会自动转换为 long
long c = 12500000;
long l = c + d;
自动转换也要小心数据溢出问题,看下面的例子。
int d = 1;
int c = 2147483647;
// c+d 本质上依然是 int 型,这里将结果转化为 long
long l = c + d;
System.out.print(l);
执行结果:
-2147483648
结果却输出的是负数,这是因为两个 int 相加得到的结果是 int,相加的结果超出了 int 的代表范围。这种情况,一般把第一个数据转换成范围大的数据类型再和其他的数据进行运算。
int d = 1;
int c = 2147483647;
long e = c;
long l = e + d;
System.out.print(l);
执行结果:
2147483648
我们在之前的实训中了解到了当两个整型做 / 运算时,/ 实际上是求整,那如果我们想要求出准确的结果,我们该怎么做呢?
我们可以将整型转化为浮点型,例如:
int d = 5;
int c = 2;
double e = d; // 将变量d类型转换为double
System.out.print(e/c);
也可以简写为:
int d = 5;
int c = 2;
System.out.print((double)d/c);
执行结果为:
2.5
当范围小的数据与范围大的数据进行运算时,类型会自动转换为范围大的那个类型。所有的 byte 类型、short 类型、char 类型在运算时将被提升到 int 类型。
注意:char 类型比较特殊,char 自动转换成 int、long、float 和 double,但 byte 和 short 不能自动转换为 char,而且 char 也不能自动转换为 byte 或 short。
强制类型转换
强制类型转换 (也叫显式类型转换) ,其实就是大范围的数据类型向小范围的数据类型转换,它需要加强制转换符来实现强制转换。例子:
double a = 2.31;
int b = (int)a;
System.out.print(b);
执行结果:
2
在强制类型转换中,如果是将浮点类型的值转换为整数,直接去掉小数点后边的所有数字;而如果是整数类型强制转换为浮点类型时,将在小数点后面补零。
强制转换需要注意两点:
- 把一个浮点数强制转换为整数时,Java 会直接截断浮点数的小数部分,造成数据丢失;
- 把一个超出数据范围的数值赋给数据类型时,会出现数据溢出的情况,造成数据的缺失。例如:int 类型的 a 的值为 249,将其强转为 byte 类型时结果会变为 -7,数据溢出。