带你读《Java程序设计与计算思维》之二:认识数据处理与表达式

简介: 程序设计的过程就是一种计算思维的表现,《Java程序设计与计算思维》结合Java程序设计语言的教学特点,遵循计算思维的方式,图解重要概念,通过大量的范例程序讲解和上机编程实践来指导读者活用Java程序语法,兼顾培养计算思维和学习面向对象程序设计的双目标。

点击查看第一章
点击查看第三章

第2章 认识数据处理与表达式

计算机主要的特点之一就是具有强大的计算能力,能把从外界得到的数据输入计算机,并通过程序来进行运算,最后输出所要的结果。下面我们从数据处理的角度来认识Java。Java中任何数据处理的结果都是由表达式来完成的。通过不同的操作数与运算符的组合就可以得到程序设计者所要的结果。在本章中,我们将认识变量与常数的使用以及Java语言中常见的基本数据类型,其中的数据类型代表变量使用内存空间的大小,而变量用于存放程序执行时的数据(如图2-1所示)。同时,我们还会示范如何进行各种数据类型之间的转换。

image.png

本章的学习目标

  • 变量与常数的使用
  • 基本数据类型
  • 自动数据类型转换
  • 基本输入与输出
  • 强制类型转换

2.1 数据类型介绍

当程序执行时,外界的数据进入计算机后,当然要有一个“栖身”之处,这时系统就会分配一个内存空间给这份数据。而在程序代码中,我们所定义的变量(Variable)与常数(Constant)的主要用途就是存储数据,并用于程序中的各种计算与处理。Java语言是一种强类型(Strongly Type)语言,意思是指:“变量在使用之前,必须声明其数据类型,我们可以任意存取这个变量的值,但是变量所声明的数据类型在程序中不可以随意变更。”
Java的数据类型可以分成“基本(Primitive)数据类型”与“引用(Reference)数据类型”。基本数据类型在声明时会先分配内存空间,目前Java共有byte、short、int、long、float、double、char和boolean八种基本数据类型。而引用数据类型则不会在声明时就分配内存空间,必须另外指定内存空间,也就是说,引用数据类型的变量值其实记录的是一个内存地址,这种类型的数据类型有数组、字符串。图2-2说明了基本数据类型中8种数据类型的分类关系。

image.png

2.1.1 整数类型

整数类型用来存储不含小数点的数据,与数学上的意义相同,如-1、-2、-100、0、1、2、100等。整数类型分为byte(字节)、short(短整数)、int(整数)和long(长整数)4种,按数据类型的存储单位及数值表示的范围整理如表2-1所示。

image.png
image.png

【范例程序:CH02_01】

01    // CH02_01.java,字节数据类型声明的实例
02    public class CH02_01 {
03        public static void main (String args[ ]) {
04            byte a=123;  // 声明字节数据类型并赋初值
05            byte b=1234;
06        }
07    }

【程序的编译结果】
程序的编译结果可参考图2-3。

image.png

程序CH02_01经编译后,编译器提示程序中有一处错误,并说明是数据类型声明的错误,byte(字节)可表示的数值范围是-127~128,因而第05行导致编译失败,因为1234已经超出byte类型数值的范围,而第04行编译成功,因为123符合所规定的范围。我们可以把第05行程序修改为“short b=1234”,即采用short(短整数)数据类型,这样1234就包括在数据类型指定的范围内了。

2.1.2 浮点数类型

浮点数(Floating Point)就是带有小数点的数字,也就是我们在数学上所指的实数。由于程序设计语言普遍应用于许多科学的精密运算,因此整数所能表示的数值范围显然不足,这时浮点数就派上用场了。
浮点数的表示方法有两种,一种是小数点表示法;另一种是科学记数法表示法。例如,3.14和-100.521是小数点表示法,而6e-2和3.2E-18是科学记数法表示法。在科学记数法表示法中,其中的e或E代表以10为底数,例如6e-2,其中6被称为有效数值,-2被称为指数。表2-2所示为小数点表示法与科学记数法表示法的对照表。

image.png

尤其是当需要进行小数基本四则运算时,或者数学运算上的开平方根(image.png)与求三角函数的正弦、余弦等运算时,运算结果需要精确到小数点后几位,这时就会使用到浮点数类型。Java浮点数类型包含float(浮点数)和double(双精度浮点数),如表2-3所示。

image.png

【范例程序:CH02_02】

01    // CH02_02.java,浮点数与双精度浮点数的声明
02    public class CH02_02 {
03        public static void main(String args[ ] ){
04            float a=12.5f;
05            double b=123456.654d;
06            System.out.println("a="+a);
07            System.out.println("b="+b);
08        }
09    }

【程序的执行结果】
程序的执行结果可参考图2-4。

image.png

【程序的解析】
程序代码的第04行声明了一个名称为a的浮点数,它被赋予的初值为12.5f,该数值的后面多加了一个字母“f”作为float(浮点数)的标记,程序代码的第05行声明了一个名称为b的浮点数,它被赋予的初值是123456.654d,这个数值的后面多加了一个字母“d”作为double(双精度浮点数)的标记。数值后面的大写字母“F”和大写字母“D”与它们的小写字母表示的意思相同。通常在编写程序时,在浮点数后面有没有这样的标记并无太大的关系。

2.1.3 布尔类型

布尔(Boolean)类型的变量用于关系运算的判断或逻辑运算的结果,例如判断“5>3”是否成立,判断结果的布尔值只有true(真)和false(假)两种。
【范例程序:CH02_03】

01    // CH02_03.java,布尔值的声明与打印输出
02    public class CH02_03 {
03        public static void main(String args[]) {
04            boolean logic=true;  // 设置布尔变量的值为false
05            System.out.println("声明的布尔值="+logic);
06        }
07    }

【程序的执行结果】
程序的执行结果可参考图2-5。

image.png

2.1.4 字符类型

在Java中,字符数据类型为char,它是一种使用16位(16-bit)二进制数所表示的Unicode字符。表2-4列出了char数据类型的存储单位及数据值表示的范围。

image.png

在Java程序中,可以使用单引号将字符引起来,以此表示字符数据类型的值。大家要特别注意的是,字符数值是用单引号标注单个字符而不是使用双引号,这和字符串(例如"学无止境")以双引号标注是不一样的,例如字符变量的赋值方式:

char ch1='X';

另外,也可以用'u十六进制数字'的方式来表示字符的值,u表示Unicode码格式。不同的字符有不同的数据表示值,如字符@的数据表示值为'u0040',字符A的数据表示值为'u0041'。
【范例程序:CH02_04】

01    // CH02_04.java,字符数据类型声明的实例
02    public class CH02_04 {
03        public static void main(String args[ ]) {
04            char ch1='X';
05            char ch2='\u0058';  //Unicode编码的写法
06            System.out.println("ch1="+ch1);
07            System.out.println("ch2="+ch2);
08        }
09    }

【程序的执行结果】
程序的执行结果可参考图2-6。

image.png

【程序的解析】
第04、05行:两种不同方式的字符数据类型写法,可以直接写字符'X',如果知道该字符的Unicode编码,也可以用字符对应的Unicode编码的十六进制数值来作为字符值。
另外,字符类型的数据中除了一般的字符外,还有一些特殊的字符无法使用键盘来输入或直接显示在屏幕上。这时必须在字符前加上反斜杠“”来通知编译器将后面的字符当成一个特殊字符,就是所谓的转义序列字符(Escape Sequence Character),用于某些特殊的控制功能。例如,'n'是表示换行功能的转义序列字符。有关各种转义序列字符与Unicode码之间的关系,请参考表2-5的说明。

image.png

2.2 变量与常数

前文已经介绍过,外界的数据进入计算机需要有一个“栖身”之所,系统会分配内存空间用于存储这些数据。在程序代码中所定义的变量(Variable)与常数(Constant)就让编译器在程序投入系统运行时给这些变量与常数分配内存空间,以便参与程序中的各种运算与处理。变量是一种可变动的数值,它的数值会根据程序内部的处理与运算进行变更。简单来说,变量与常数都是程序设计人员用来存取内存中数据内容的一个标识码,两者最大的差异在于变量的内容会随着程序执行而改变,但常数则会固定不变。

2.2.1 变量与常数的声明

变量是具备名称的一块内存空间,用来存储可变动的数据内容。当程序需要存取某个内存的内容时,就可以通过变量名称将数据从内存中取出或写入这个内存空间。在使用变量前,必须对变量进行声明,Java语言的变量声明语句可分为“数据类型”与“变量名称”两部分。声明语句的语法如下:

数据类型变量名称;      // 符号“;”表示语句的结束

假如我们声明两个整数变量num1和num2,其中int为Java语言中用于声明整数类型的关键字(keyword):

int num1=30;
int num2=77;

这时Java会分别自动分配4字节的内存空间给变量num1和num2,它们的存储值分别为30和77。当程序运行过程中需要存取这块内存空间的内容时,就可以直接使用变量名称num1与num2来进行存取,如图2-7所示。

image.png

以上为单个变量声明的程序语句,当同时要声明多个相同数据类型的变量时,可使用逗号“,”来分隔变量名称,例如:

long apple, banana ; // 同时声明多个long类型的变量,以逗号作为分隔符

完成变量的声明后,有些变量可根据需要赋初值,就是在变量声明的语句中加入初值的设置,语法如下:

数据类型变量名称=初值;

例如:

int apple =5;    // 声明单个int类型的变量,并把它的初值设置为5
boolean a=true,b=false;  // 同时声明多个boolean类型的变量,并赋初值

在赋初值时,注意数据类型的字符和浮点数的赋值。给char数据类型赋初值有三种方法:字符、Unicode码以及ASCII码,其中初值为字符、Unicode码格式时,必须在字符的左右两边各加上单引号“'”。如下所示:

char  apple ='@';            //用字符表示方式来赋初值“@”
char  apple ='\u0040';    //用“@”字符对应的Unicode码格式来赋初值,即“\u0040”
char  apple =64;    //用“@”字符对应的ASCII码“64”来赋初值,ASCII码用十进制数表示

2.2.2 变量与常数的命名规则

在Java语言中,标识符(Identifier)用来命名变量、常数、类、接口、方法,标识符是用户自行命名的文字串,由英文大小写字母、数字或下画线“_”等符号组合而成,变量命名有一定的要求与规则:

  • 必须为合法的标识符,变量名的第一个字符必须是字母、$或“_”中的一种。变量名的第一个字符之后可以是字母、$、数字或“_”等,而且变量名最长可以有255个字符。另外,在Java中,变量名中字母大小写的不同会被视为不同的变量。例如,M16与m16其实表示两个不同的变量。
  • 变量名不可以是关键字(Keyword)、保留字(Reserved Word)、运算符以及其他一些特殊字符,如int、class、+、-、*、/、@、#等。在Java语言中,关键字由具有明确意义的英文单词组成,这些单词被赋予了构建程序的功能,如声明变量数据类型、程序的流程控制、表示布尔值等。Java语言中共有52个关键字,在使用时必须注意每一个关键字中的英文字母全为小写。表2-6所示是按功能分类的Java关键字。

    image.png

  • 在同一个作用域(scope)内,变量名必须是独一无二的;处于不同作用域时,变量名可以相同。注意:变量的作用域就是指变量的有效范围。

虽然变量的命名从语法上讲只需要遵守上面的三个主要规则即可,但是在实际应用中,建议大家参考各个研发公司所制定的有关Java程序编写的规范,因为如果大家都能遵守这些惯用的命名法,所编写而成的程序就可以维持一致性,无论是在程序的阅读或维护上都较容易。下面列出编写程序时建议的几个重要规范。

  • 不取无任何含义的变量名称:在为变量命名时,还必须考虑一个重要原则,就是尽量使用有明确含义的名称,避免无任何含义的变量名称,如abc。尽量使用有代表意义的名称,有明确含义的名称可以突显变量在程序中的用途,让程序代码易于理解、查错、调试以及日后的维护。例如可以把存储“姓名”的变量命名为name,把存储“成绩”的变量命名为score等。
  • 注意变量名中字母的大小写:在Java程序中有一个不成文的规则,通常变量名是以小写英文字母作为开头的,再接上一个大写字母开头且有含义的单词,例如存储“用户密码”的变量命名为userPassword。

表2-7列举了不同的命名结果,并说明了这些命名是否合乎Java语言的命名规则。

image.png
image.png

在变量声明方面,Java与其他的程序设计语言最大的不同在于它舍弃了定义“常数”的声明,因此并不存在所谓的常数类型。不过,程序开发人员仍然可以使用Java关键字final来定义常数。final关键字的作用是强调在此关键字后面的各种对象不能再被覆盖、覆写或重新定义。使用final关键字声明常数的方式如下:

final 数值类型常数名称 = 初始值;

例如:

final float PI = 3.1415926;

因为常数是一种固定、不会变动的数值,例如圆周率(PI)、光速(C)等,所以它的使用范围通常包括整个程序。因此常数经常被声明为类的成员,也就是所谓的成员数据,为了与普通变量有所区分,常数的命名大多是使用大写英文字母。
下面的范例程序实现了相对论公式的计算。我们定义了一个常数C(光速)以及两个变量m(质量)与e(能量),通过这个范例程序我们来了解变量与常数的声明方式。
【范例程序:CH02_05】

01    // CH02_05.java,变量与常数的声明
02    public class CH02_05 {  //声明常数C(光速)
03        final static double C = 2997924581.2;
04        public static void main(String args[]) {
05            //声明变量e与m
06            int m;
07            double e;
08            //给变量赋值
09            m = 10;
10            e = m * C * C;
11            //输出到屏幕上
12            System.out.println("当质量为:" + m);
13            System.out.println("所释放出的能量为:" + e);
14        }
15    }

【程序的执行结果】
程序的执行结果可参考图2-8。

image.png

2.3 基本输入与输出功能

输入(Input)与输出(Output)是一个程序基本的功能。在Java中有各种负责数据输入输出的相关数据流(Data Stream)类,但是基础的I/O操作莫过于使用System类中的out对象与in对象,它们各自都拥有一些与标准输入(in对象)和输出(out对象)相关的方法(Method)。

2.3.1 在屏幕上输出数据

Java的标准输出语句的声明方式如下:

System.out.print(数据);       //不会换行
System.out.println(数据);      //会换行
  • System.out:代表系统的标准输出。
  • println与print:它们的功能是将括号内的字符串打印输出。差别在于print在输出内容后不会换行,而println则会在输出内容后自动换行。
  • 数据的格式可以是任何类型,包括变量、常数、字符、字符串或对象等。

再看看下面的程序语句的输出情况:

System.out.println("字符串A" + "字符串B");    //使用运算符“+”来执行字符串的串接运算
System.out.println (布尔值变量?变量A:变量B);    //使用三元条件运算符来进行条件判断

【范例程序:CH02_06】

01    //程序:CH02_06.java,基本输出
02    public class CH02_06 {
03        public static void main(String args[]) { //声明变量
04            String myStringA = "第一个字符串";
05            String myStringB = "第二个字符串";
06            String myStringC = "会串接在一起";
07            int myIntA = 3;
08            boolean myBoolean = true;
09            //在屏幕上输出
10            System.out.print("[JAVA基本输出练习]\n");
11            System.out.println("“真”的英文是" + myBoolean);
12            System.out.println(myStringA + myStringB);
13            System.out.println(myStringC);
14            System.out.println("1 + 2 = " + myIntA);
15            System.out.println("5 - 3 = " + (5 - myIntA));
16        }
17    }

【程序的执行结果】
程序的执行结果可参考图2-9。

image.png

【程序的解析】
第10行:使用n转义控制字符强制print()方法执行换行操作。
第10~15行:示范各种基本输出使用模式。
2.3.2 从键盘输入数据
在Java中,标准输入可以使用System.in,并配合read()方法,使用方式如下:
System.in.read();

  • System.in:代表系统的标准输入。
  • read():这个方法的功能是先从输入流(例如键盘输入的字符串)中读取下一个字节,再返回这个字符的ASCII码(0~255之间的整数)。

例如下面的程序语句:

System.out.println("请从键盘输入一个字符");
char data = (char) System.in.read();

在这段程序中,因为read()会返回整数类型,要对返回的数值进行类型转换的操作(将int类型转换为char类型),所以必须在read方法前面加上“(char)”。另外,read()方法一次只能读取一个字符,由于在此程序中仅有一行调用read()方法的语句,因此在键盘上无论输入多少个字符,它都只会读取第一个字符的ASCII值。
【范例程序:CH02_07】

01    //程序:CH02_07.java,基本输入
02    import java.io.*;
03    public class CH02_07 {
04        private static char myData;
05        public static void main(String args[]) throws IOException {
06            System.out.print("[基本输入练习]\n");
07            System.out.print("请输入字符:");
08            //输入字符
09            myData = (char)System.in.read();
10            System.out.println("输入的字符为:" + myData);
11        }
12    }

【程序的执行结果】
程序的执行结果可参考图2-10。

image.png

【程序的解析】
第04行:声明一个字符变量myData,用以存储用户键盘所输入的字符数据。
但问题是输入的数据类型不可能只限于单个字符,基于这个理由,我们不妨使用java.util.Scanner类,在这个类中可以通过Scanner对象来从外界获取输入的数据。有关Scanner对象的创建方式,必须使用new运算符,其声明的语法如下:

java.util.Scanner input_obj=new java.util.Scanner(System.in);

当以上述语句创建好Scanner对象后,就可以调用该对象所提供的方法来获取用户从键盘输入的数据。例如要输入一整行字符串,Scanner对象提供了nextLine()方法;要获取输入的整数,Scanner对象提供了nextInt()方法;要获取输入的浮点数,Scanner对象提供了nextDouble()方法。下面为获取各种数据类型输入的语句:

java.util.Scanner input_obj=new java.util.Scanner(System.in);
System.out.print("请从键盘输入字符串类型: ");
String StrVal =input_obj.nextLine();
System.out.println("您所输入的字符串值为 "+StrVal);
        
System.out.print("请从键盘输入整数类型: ");
int IntVal =input_obj.nextInt();
System.out.println("您所输入的整数值为 "+IntVal);
        
System.out.print("请从键盘输入浮点数类型: ");
double DoubleVal =input_obj.nextDouble();
System.out.println("您所输入的浮点数为 "+DoubleVal);

2.4 数据类型的转换

Java语言的数据类型定义很严谨,不允许数据类型之间随意转换(Conversion),也就是说原本把变量声明为int数据类型,如果给它赋予char类型的数据,在编译时就会发生错误。数据转换的方式有两种:一种是“由小变大”;另一种是“由大变小”。

2.4.1 由小变大模式

如果“目的变量”和“源变量或数据”之间的类型不相同,在转换时符合两个条件,转换后的源变量或数据类型就不会影响数值的精度。“由小变大”的转换机制会“自动转换”,而不会损失数据的精确度。下面列出转换的机制:

double(双精度浮点数)> float(浮点数)> long(长整数)> int(整数)> char(字符)> short(短整数)> byte(字节)
  • 转换类型之间必须兼容。例如short(短整数)可以和int(整数)互相转换,但不可以和byte(字节)互相转换。
  • “目的变量”的数据类型必须大于“源变量或数据”的数据类型,也就是以数值范围较大的为主。例如short(短整数)可以和int(整数)互相转换;int(整数)可以和long(长整数)互相转换。

2.4.2 由大变小模式

“由大变小”的转换机制需“指定转换”,当“目的变量”的数据类型小于“源变量或数据”的数据类型时,使用的转换语法如下:

(指定类型) 数据 | 变量;    // 注意括号不可省略

所谓“指定类型”是指目的类型。“数据 | 变量”指的是源变量或数据。数值大范围的数据类型转换成数值小范围的数据类型时,部分数据可能会被截去,即损失了精度。例如,声明两个整数变量分别为X和Y,并各赋予了初值,X=19、Y=4。如果进行除法运算“X/Y”,那么运算的结果(Z)为4,但是如果希望计算结果的精确度能够到小数点后面,结果的类型就不能使用“整数int”,正确的做法应该是采用“强制类型转换”的方式来重新定义参与计算的变量值或数值:

Z=(float)X / (float)Y; // 先将X和Y原来声明的整数类型强制转变成浮点数类型

【范例程序:CH02_08】

01    //程序:CH02_08.java,数据类型的转换
02    public class CH02_08 {
03        public static void main(String[ ] args) {
04            int i=10;
05            byte b=(byte) i;
06            byte b1=65;
07            char c=(char)b1;
08            System.out.println("i="+i);
09            System.out.println("b="+b);
10            System.out.println("b1="+b1);
11            System.out.println("c="+c);
12        }
13    }

【程序的执行结果】
程序的执行结果可参考图2-11。

image.png

2.5 表达式与运算符

精确快速的计算能力是计算机最重要的能力之一,而这种能力是通过程序设计语言中各种五花八门的表达式来实现的。表达式(Expression)就像平常所用的数学公式一样,是由运算符(Operator)与操作数(Operand)所组成的。以下是一个简单的表达式:

d=a*b-123.4;

这个表达式中的d、a、b、123.4等常数或变量被称为操作数,而=、*、-等运算符号被称为运算符。Java语言的运算符除了基本的加、减、乘、除四则运算符之外,还有很多运算符,例如赋值运算符(=)。表2-8列出了Java中基本的四则运算符以及其他用途的运算符。

image.png
image.png

表达式由操作数和运算符组成。操作数代表运算数据,运算符代表运算关系,例如算术运算符、关系运算符、逻辑运算符、移位运算符以及赋值运算符等。任何运算都与操作数和运算符有关,如图2-12所示。

image.png

2.5.1 算术运算符

算术运算符(Arithmetic Operator)的用途类似一般数学运算中的加(+)、减(-)、乘(×)和除(÷)四则运算,是经常使用的数学运算符。这些算术运算符在Java语言中的用法及功能与它们在传统的数学中的用法及功能相同。不过,我们要注意的是加法运算符,在Java中,它除了可以执行数值加的运算,还具有“字符串串接”的功能。
(1)加、减、乘、除及求余数
加、减、乘、除及求余数运算符的用法可以参考表2-9。

image.png

其中,四则运算符和数学上的功能一模一样,在此不多做介绍。而求余数运算符“%”用于计算两数相除后的余数,这个运算要求参与运算的两个操作数都必须是整数类型。
(2)递增(Increment)与递减(Decrement)运算
递增“++”和递减运算符“--”是对变量加1和减1的简写方式,这种运算只适用于整数类型的变量,属于一元运算符(或称为单目运算符),它们可增加程序代码的简洁性。要注意的是,递增或递减运算符在变量前后的位置不同,虽然都是对操作数执行加1或减1的运算,但是在表达式中的运算顺序还是有差别的,递增与递减运算符可以分为前缀(Prefix)和后缀(Postfix)两种。使用方式和运算结果可参考表2-10。

image.png

(3)数值的正负数表示
正数默认不需要带加号,但负数则要使用负号(即减法运算符)来表示。当负数进行减法运算时,为了避免运算符的混淆,最好以空格符或小括号“( )”隔开,例如:

int x=5;        // 声明变量x为int整数类型,并把它的初值设为5
x=x- -2;        // 用空格符隔开,避免和递减运算符相混淆
x=x-(-2);        // 用小括号隔开

【范例程序:CH02_09】

01    /*文件名:CH02_09.java    
02    *说明:水果礼盒
03    */
04    public class CH02_09 {
05        public static void main(String args[]) {
06            int apple=15,banana=20;//声明变量
07            System.out.print("(1).小明买了苹果15个,香蕉20根,水果总共买了");
08            System.out.println((apple+banana)+"个");
09            System.out.print("(2).苹果每个3元,香蕉每根1元,总共花费了");
10            System.out.println((apple*3+banana*1)+"元");
11            System.out.print("(3).将苹果4个和香蕉3根装成一盒,共可装");
12            System.out.println((apple/4)+"盒");
13            System.out.println("(4).装盒后苹果剩下"+(apple%4)+"个,"+"香蕉剩下"+(20-apple/4*3)+"根");
14        }
15    }

【程序的执行结果】
程序的执行结果可参考图2-13。

image.png

【程序的解析】
第06行:声明变量apple(苹果)和banana(香蕉),并分别设置初值为15和20。根据数量的数据类型,因而声明这两个变量为int类型。
第07~13行:示范简单的算术运算。
2.5.2 关系运算符
关系运算符(Relational Operator)用于比较两个操作数之间的关系,是大于(>)、小于(<)还是等于(= =),诸如此类的关系都可以用关系运算符来运算。运算的结果为布尔值,如果关系成立,就返回真(true);如果关系不成立,就返回假(false)。在Java中,关系比较运算符共有6种,如表2-11所示。

image.png
image.png

需要注意的是,一般数学上使用“≠”表示不等于,但是“≠”符号在编辑软件中无法直接从键盘输入,因此Java语言使用“!=”来代替“≠”表示不等于。另外,等于关系的表示方式在数学上一般使用一个等于符号(=)来表示,不过在Java语言中是以两个等于符号(==)来表示的,因此读者在编写Java程序中要表达“不等于”和“等于”时要多加注意。
【范例程序:CH02_10】

01    /*文件名:CH02_10.java    
02    *说明:关系运算
03    */
04    public class CH02_10 {
05        public static void main(String args[]) {
06            System.out.print("15大于5 为"+(15>5)+"\n");
07            System.out.print("15小于5 为"+(15<5)+"\n");
08            System.out.print("15大于等于15 为"+(15>=15)+"\n");
09            System.out.print("15小于等于5 为"+(15<=5)+"\n");
10            System.out.print("15不等于5 为"+(15!=5)+"\n");
11            System.out.print("15等于5 为"+(15==5)+"\n");
12        }
13    }

【程序的执行结果】
程序的执行结果可参考图2-14。

image.png

【程序的解析】
第06~11行:用关系运算符判断两个操作数之间的关系,判断的结果为布尔(Boolean)数据类型。
程序代码中使用“"n"”表示“换行”的意思。

2.5.3 逻辑运算符

逻辑运算符(Logical Operator)用于基本的逻辑运算,判断的结果也是布尔数据类型,如果结果为真,其值为true(可用数字1表示);如果结果为假,其值为false(可用数字0表示)。&&和||运算符的运算顺序是从左到右,而!运算符的运算顺序是从右到左。
逻辑运算符在运用上可分为“布尔数据类型的逻辑运算”和“位的逻辑运算”。逻辑运算符用于判断两个关系运算符之间的关系,例如用于计算“a>0 && b>0”这类逻辑运算的结果。
(1)布尔数据类型的逻辑运算
Java中的逻辑运算符共有4种,如表2-12所示。

image.png

“!”代表“非”,是求反的意思。“&&”(AND)和“||”(OR)逻辑运算的真值表可参考表2-13和表2-14。

image.png

(2)位的逻辑运算
操作数在计算机内存中存储的值实际上是以二进制方式存储的。我们可以使用位运算符(Bitwise Operator)来对两个整数操作数进行位与位之间的逻辑运算。我们将整数转换成二进制数值时必须注意不同整数类型占用的存储空间,byte类型的数值5占用一个字节,因而转换为二进制值为“00000101”,即8个二进制位(bit)。若是short类型,则占用两个字节,对应16个二进制位;int类型占用4个字节,对应32个二进制位;long类型占用8个字节,占用64个二进制位。
Java语言提供了4种位逻辑运算符,分别是&(AND,即“与”)、|(OR,即“或”)、^(XOR,即“异或”)与~(NOT,即“非”),如表2-15所示。

image.png

【范例程序:CH02_11】

01    /*文件名:CH02_11.java    
02    *说明:逻辑运算
03    */
04    public class CH02_11 {
05        public static void main(String args[]) {
06            int a=15,b=3;
07            System.out.println("(a>10)&&(b>5)的返回值为 "+(a>10&&b>5));
08            System.out.println("(a>10)||(b>5)的返回值为 "+(a>10||b>5));
09            System.out.println("(a>10)&(b>5)的返回值为 "+(a>10&b>5));
10            System.out.println("(a>10)|(b>5)的返回值为 "+(a>10|b>5));
11            System.out.println("(a>10)^(b>5)的返回值为 "+(a>10^b>5));
12            System.out.println(" 15 & 3 的返回值为 "+(a&b));
13            System.out.println(" 15 | 3 的返回值为 "+(a|b));
14            System.out.println(" 15 ^ 3 的返回值为 "+(a^b));
15            System.out.println(" ~3 的返回值为"+(~b));
16        }
17    }

【程序的执行结果】
程序的执行结果可参考图2-15。

image.png

【程序的解析】
第07~11行:布尔类型的逻辑运算。
第12~15行:位的逻辑运算。

2.5.4 移位运算符

移位运算符(Shift Operator)应用于整数类型,将整数转换成二进制后,对二进制的各个位做向左或向右的移动。在Java语言中有两种移位运算符,可参考表2-16的说明。

image.png

【范例程序:CH02_12】

01    /*文件名:CH02_12.java    
02    *说明:移位运算
03    */
04    public class CH02_12 {
05        public static void main(String args[]) {
06            System.out.println("5 << 2 的返回值为 "+(5<<2));
07            System.out.println("-5 << 2 的返回值为 "+(-5<<2));
08            System.out.println("5 >> 2的返回值为 "+(5>>2));
09            System.out.println("-5 >> 2的返回值为 "+(-5>>2));
10        }
11    }

【程序的执行结果】
程序的执行结果可参考图2-16。

image.png

【程序的解析】
第06~09行:整数的移位运算。

2.5.5 赋值运算符

赋值运算符(Assignment Operator)由至少两个操作数组成,主要作用是将等号“=”右方的值或者表达式的计算结果赋予等号左方的变量。由于是将“=”号右边的值赋值给“=”号左边,因此“=”号的左边必须是变量,而右边则可以是变量、常数或表达式等。
初学者很容易将赋值运算符“=”的作用和数学上的“等于”功能混淆,在程序设计语言中,“=”主要是赋值的概念。以下是赋值运算符的使用方式:

变量名称 = 要赋予的值或表达式;

例如:

a= a + 5;         /* 将a值加5后赋值给变量a */
c ='A';           /* 将字符'A'赋值给变量c */

a=a+5在数学上根本不成立,不过在Java的世界中,我们可以这样解读:当声明变量之后,在内存中已经给这个变量分配了内存空间,在后续使用中就要使用赋值运算符来给该变量赋值。Java语言的赋值运算符除了一次给一个变量赋值外,还能够把同一个数值同时赋值给多个变量,例如:

int x,y,z;
x=y=z=200;     /* 把一个值同时赋给不同变量 */

在Java中还有一种复合赋值运算符,是由赋值运算符与其他运算符组合而成的。先决条件是赋值号“=”右边的源操作数必须有一个和左边接收赋值数值的操作数相同,如果一个表达式含有多个复合赋值运算符,运算过程必须从右边开始,逐步进行到左边。
例如以“A += B;”语句来说,它就是语句“A=A+B;”的精简写法,也就是先执行A+B的计算,接着将计算结果赋值给变量A。这类运算符的说明及使用语法如表2-17所示。

image.png

下面的范例程序用于说明复合赋值运算符的使用方式。要特别注意的是,在运算过程中,运算的顺序是从赋值号的右边开始的,而后逐步进行到左边。例如,复合赋值运算符在多重表达式中的使用:

a+=a+=b+=b%=4;

这个表达式的实际运算顺序和运算过程如下:

b =b%4
b=b+b;
a=a+b;
a=a+a;

【范例程序:CH02_13】

01    /*文件名:CH02_13.java    
02    *说明:赋值运算
03    */
04    public class CH02_13 {
05        public static void main(String args[]) {
06            int A=5;
07            System.out.println("A=5 ");
08            A+=3+2;
09            System.out.println("A+= 3+2 的值为 "+(A));
10            A=5;
11            A-=5-4;
12            System.out.println("A-= 5-4 的值为 "+(A));
13            A=5;
14            A*=2*3;
15            System.out.println("A*= 2*3 的值为 "+(A));
16            A=5;
17            A/=10/5+3;
18            System.out.println("A/= 10/5+3 的值为 "+(A));
19            A=5;
20            A%=15%4;
21            System.out.println("A%= 15%4的值为 "+(A));
22            A=5;
23            A &=5-3;
24            System.out.println("A&= 5-3 的值为 "+(A));
25            A=5;
26            A|=2;
27            System.out.println("A|= 2 的值为 "+(A));
28            A=5;
29            A^=2+1;
30            System.out.println("A^= 2+1 的值为 "+(A));
31        }
32    }

【程序的执行结果】
程序的执行结果可参考图2-17。

image.png

【程序的解析】
第06~30行:变量A的赋值运算。

2.5.6 运算符的优先级

一个表达式中往往包含多个运算符,这些运算符执行的先后顺序如何呢?这时就需要按照运算符的优先级来建立运算规则。当表达式中使用多个运算符时,例如z=x+3y,就必须按照运算符的优先级来进行运算。按照数学基本运算中“先乘除后加减”的规则,这个表达式会先执行3y的运算,把运算的结果与x相加,再将相加的结果赋值给z,最后得到这个表达式的最终运算结果。在Java中,在处理含有多个运算符的表达式时,同样必须遵守一些规则与步骤,说明如下:
(1)当遇到一个表达式时,先区分运算符与操作数。
(2)按照运算符的优先级进行整理。
(3)将各个运算符根据其结合顺序进行运算。
在进行包含多种运算符的运算时,必须先了解各种运算符的“优先级”和“结合律”。假如表达式中有多个运算符,那么各个运算符要按照既定的顺序完成运算,这里所说的顺序就是运算符“优先运算的顺序”。表达式中常见的括号(如“( )”)具有最高的优先级,即括号内的运算优先级高于括号外的运算优先级。表2-18列出了Java中各种运算符的优先级。

image.png

表2-18中所列的优先级,1代表最高优先级,15代表最低优先级。“结合律”指在表达式中遇到同等级优先级时的运算规定,如“3+2-1”,加号“+”和减号“-”同属于优先级4,根据结合律,顺序是从左到右,先从最左边执行“3+2”的运算后,再往右执行减“-1”的运算。程序设计人员应该熟悉各个运算符的优先级和结合律,这样在编写程序时才不至于出现这类错误或不合理的问题。

2.6 高级应用练习实例

本章主要讨论了Java语言的基本数据处理,包括变量与常数、各种数据类型、类型转换和运算符等。另外,如果可以灵活使用各种数据类型,再搭配简易的输出指令和运算符,就可以编写出许多实用的程序。

2.6.1 多重逻辑运算符的应用

我们知道逻辑运算符运用于条件判断表达式来控制程序执行的流程,而一个条件判断表达式中可以使用多个逻辑运算符。不过,当连续使用逻辑运算符时,它的计算顺序为从左到右进行。以下程序中声明了a、b和c三个整数变量,并赋予了初值,请判断以下两个表达式结果的真假值(布尔类型的结果,true或者false):

a<b && b<c || c<a
!(a<b) && b<c || c<a

【综合练习】多重逻辑运算符的应用与范例

01    // 多重逻辑运算符的应用与范例
02    public class WORK02_01 {
03        public static void main (String args[] ) {
04            int a=7,b=8,c=9; /*声明a、b和c三个整数变量,并赋初值*/
05            System.out.println("a<b && b<c || c<a = "+(a<b && b<c || c<a));
06            /* 先计算“a<b && b<c”,再将结果与“c<a”进行OR的运算 */
07            System.out.println("!(a<b) && b<c || c<a = "+(!(a<b) && b<c || c<a));
08        }
09    }

【程序的执行结果】
程序的执行结果可参考图2-18。

image.png

2.6.2 位逻辑运算符的运算练习
请大家运用位逻辑运算符对两个整数12与7进行位与位之间的AND、OR、XOR位逻辑运算,并显示出运算结果。
【综合练习】位逻辑运算符的应用与范例

01    // 位逻辑运算符的应用与范例
02    public class WORK02_02 {
03    public static void main (String args[]) {
04    int bit_test=12;/* 声明整数变量并赋初值 (00001100) */
05        int bit_test1=7;/* 声明整数变量并赋初值 (00000111)*/
06        System.out.println("bit_test="+bit_test+"  bit_test1= "+bit_test1);
07    System.out.println("-----------------------------------------");
08    /* 执行 AND、OR、XOR 位逻辑运算 */
09    System.out.println("执行 AND 运算的结果:"+(bit_test & bit_test1));
10    System.out.println("执行 OR  运算的结果:"+(bit_test | bit_test1));
11    System.out.println("执行 XOR 运算的结果:"+(bit_test ^ bit_test1));
12      }
13    }

【程序的执行结果】
程序的执行结果可参考图2-19。

image.png

2.6.3 自动类型转换与强制类型转换的比较

我们知道强制类型转换可以用来弥补自动类型转换无法处理的情况。例如下面的情况:

int i=100, j=3;
float Result;
Result= i /j;

这时自动类型转换会将i/j的结果(整数值33)转换成float类型,再赋值给Result变量,得到33.000000,而i/j小数点后面的部分完全被舍弃了,因此无法得到精确的结果值。如果我们要获取小数部分的数值,请试着在上述程序代码中增加强制类型转换的功能。
除了由编译器自行转换的自动类型转换之外,Java语言还允许用户强制转换数据类型。例如,如果想让两个整数相除得到更精确的结果,那么可以用强制类型转换,即将两个整数转换成浮点数类型。要在表达式中强制转换数据类型,采用如下语法:

(强制转换类型名称)  表达式或变量;

例如以下程序片段:

int a,b,avg;
avg=(float)(a+b)/2;/* 将a+b的结果值强制转换为浮点数类型 */

注意,上述程序语句中包含转换类型名称的小括号是绝对不可以省略的,否则计算结果得到的浮点数在被自动类型转换为整数时,小数部分会被直接舍弃。另外,在赋值运算符“=”左边的变量不能进行强制数据类型转换,例如:

(float)avg=(a+b)/2;  /* 不合法的程序语句 */

【综合练习】强制类型转换练习

01    // 自动类型转换与强制类型转换的比较
02    public class WORK02_03 {
03      public static void main (String args[]) {
04    int i=100, j=3; /* 声明整数变量 i 与 j,并赋初值 */
05        float Result;   /* 声明浮点数变量 Result */
06        System.out.println("自动类型转换的执行结果为:");
07        Result=i/j;       /* 自动类型转换 */
08        System.out.println("Result=i/j="+i+"/"+j+"="+Result);
09        System.out.println("--------------------------------------");
10        System.out.println("强制类型转换的执行结果为:");
11        Result=(float) i / j;  /* 强制类型转换 */
12      System.out.println("Result=(float)i/(float)j="+i+"/"+j+"="+Result);
13        System.out.println("--------------------------------------");
14      }
15    }

【程序的执行结果】
程序的执行结果可参考图2-20。

image.png

课后习题

一、填空题
1.    是指“变量在使用之前,必须声明其数据类型,我们可以任意存取这个变量的值,但是变量所声明的数据类型不可以随意变更”。
2.Java的数据类型可以分成        
3.    在程序设计语言中代表数据存储的内存空间。
4.布尔数据类型数据结果的表示只有        两种。
5.基本数据类型按照使用性质的不同,可分成                4种。
6.如果字母B的Unicode值为42,它的Java字符数据表示值为    
7.Java定义的整数类型包含                
8.声明语句的语法可分成        两部分。
9.在字符前加上反斜杠“”来通知编译器将后面的字符当成一个特殊字符,就是所谓的    
10.表达式是由        组成的。
11.    是用来表示Unicode码格式的,不同的字符有不同的数据表示值。
12.当用负数进行减法运算时,为了避免分辨运算符造成的混淆,最好以        隔开。
二、问答与实践题
1.说明 Java中变量的命名规则有哪些注意事项。
2.表2-19中不正确的变量命名违背了哪些原则?

image.png

3.递增(++)和递减(--)运算方式可分成哪两种?
4.判断下列命名中哪些是合法的命名、哪些是不合法的命名?
  A.is_Tim
  B.is_TimChen_Boy_NICE_man
  C.Java SE 11
  D.Java_11
  E.#Tom
  F.aAbBcC
  G.1.5_J2SE
5.下列程序代码是否有错,如果有错,请说明原因。

01    public class EX02_05 {
02        public static void main(String args[ ]) {
03            int number1=15:number2=8; //声明两个变量,并赋初值
04            System.out.print("两个数相加的结果为:");
05            System.out.println(number1+number2);
06        }
07    }

6.下列程序代码是否有错,如果有错,请说明原因。

01    public class EX02_06 {
02        public static void main(String args[ ]) {
03            int a,b;
04            float c=(a+b);
05            System.out.println("计算结果= "+c);    
06        }
07    }

7.请编写Java程序来实现“sum=12; t=2;sum+=t”这段程序代码,这段程序执行后,观察sum的值是多少,t的值又是多少。
8.请编程实现“int a=11,b=21,c=12,d=31;boolean ans=(c>a)&&(b9.请解释什么是操作数和运算符,并列举各种运算符。
10.试举出至少10个关键字。
11.举例说明数据类型的自动类型转换。
12.请比较下列运算符的优先级。
  ① 括号:( ) 、 [ ]
  ② 条件选择运算符:?:
  ③ 赋值运算:=
13.请设计一个Java程序,可用来计算圆的面积及其周长。
14.请设计一个Java程序,可用来计算梯形的面积。
15.改写第14题,不过此次梯形的上底、下底和高可由用户自行输入,并计算梯形面积。

相关文章
|
1月前
|
Java
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
25 0
|
1月前
|
存储 Java
Java 编程实例:相加数字、计算单词数、字符串反转、元素求和、矩形面积及奇偶判断
Java中相加两个数字可通过简单赋值实现,如`int sum = x + y;`。若要用户输入数字相加,可使用`Scanner`类读取。计算单词数,可使用`split()`方法或`StringTokenizer`类。反转字符串,可用`for`循环或`StringBuilder`的`reverse()`方法。计算数组元素总和,可遍历数组累加。矩形面积通过长度乘以宽度得出。判断奇偶性,利用模2运算或位运算检查最低位。更多内容,可关注微信公众号`Let us Coding`。
49 0
|
18天前
|
XML 数据可视化 前端开发
java正则表达式
java正则表达式
|
2天前
|
Java 程序员 编译器
JavaSE&Java8 Lambda 表达式
JavaSE&Java8 Lambda 表达式
|
6天前
|
并行计算 Java 编译器
Java Lambda表达式简介
Java Lambda表达式简介
12 0
|
7天前
|
Java 开发者
探索 Java 的函数式接口和 Lambda 表达式
【4月更文挑战第19天】Java 中的函数式接口和 Lambda 表达式提供了简洁、灵活的编程方式。函数式接口有且仅有一个抽象方法,用于与 Lambda(一种匿名函数语法)配合,简化代码并增强可读性。Lambda 表达式的优点在于其简洁性和灵活性,常用于事件处理、过滤和排序等场景。使用时注意兼容性和变量作用域,它们能提高代码效率和可维护性。
|
10天前
|
分布式计算 Java API
Java 8新特性之Lambda表达式与Stream API
【4月更文挑战第16天】本文将介绍Java 8中的两个重要新特性:Lambda表达式和Stream API。Lambda表达式是Java 8中引入的一种新的编程语法,它允许我们将函数作为参数传递给其他方法,从而使代码更加简洁、易读。Stream API是Java 8中引入的一种新的数据处理方式,它允许我们以声明式的方式处理数据,从而使代码更加简洁、高效。本文将通过实例代码详细讲解这两个新特性的使用方法和优势。
|
14天前
|
Java
Java 14 强势登场:Switch 表达式的进化之路
Java 14 强势登场:Switch 表达式的进化之路
18 0
|
16天前
|
Java 开发者
Java中的Lambda表达式:简洁、灵活的编程利器
在现代软件开发中,编写简洁、高效的代码是至关重要的。Java中的Lambda表达式为开发者提供了一种简洁、灵活的编程方式,使得代码更具可读性和可维护性。本文将探讨Lambda表达式的基本概念、语法结构以及在实际项目中的应用,以帮助读者更好地理解和运用这一强大的编程工具。
6 0
|
18天前
|
存储 Java API
java8新特性 lambda表达式、Stream、Optional
java8新特性 lambda表达式、Stream、Optional