Java学习笔记 - 数据类型与运算符【下】

2.6 基本数据类型(primitive data type)

Java是一种强类型语言,每个变量都必须声明其数据类型。 Java的数据类型可分为两大类:基本数据类型(primitive data type)和引用数据类型(reference data type)。

Java中定义了3类8种基本数据类型

  • 数值型- byte、 short、int、 long、float、 double

  • 字符型- char

  • 布尔型-boolean

7.png

图2-2 数据类型的分类

【注意事项】

引用数据类型的大小统一为4个字节,记录的是其引用对象的地址!

本章只讲解基本数据类型。引用数据类型在后续数组和面向对象章节讲解。

2.6.1 整型变量/常量

整型用于表示没有小数部分的数值,它允许是负数。整型的范围与运行Java代码的机器无关,这正是Java程序具有很强移植能力的原因之一。与此相反,C和C++程序需要针对不同的处理器选择最有效的整型。

表2-4 整型数据类型
类型占用存储空间表数范围
byte1字节~-1(-128~127)
short2字节~-1(-32768~32767)
int4字节~-1 (-2147483648~2147483647) 约21亿
long8字节~-1

Java 语言整型常量的四种表示形式

  • 十进制整数,如:99, -500, 0

  • 八进制整数,要求以 0 开头,如:015

  • 十六进制数,要求 0x 或 0X 开头,如:0x15

  • 二进制数,要求0b或0B开头,如:0b01110011

Java语言的整型常数默认为int型,声明long型常量可以后加‘ l ’或‘ L ’ 。

【示例2-10】长整型常数的声明

long a = 55555555;  //编译成功,在int表示的范围内(21亿内)。
long b = 55555555555;//不加L编译错误,已经超过int表示的范围。

我们修改成long类型的常量即可:

long b = 55555555555L;

2.6.2 浮点型变量/常量

带小数的数据在Java中称为浮点型。浮点型可分为float类型和double类型。

表2-5 浮点型数据类型
类型占用存储空间表数范围
float4字节-3.403E38~3.403E38
double8字节-1.798E308~1.798E308

float类型又被称作单精度类型,尾数可以精确到7位有效数字,在很多情况下,float类型的精度很难满足需求。而double表示这种类型的数值精度约是float类型的两倍,又被称作双精度类型,绝大部分应用程序都采用double类型。浮点型常量默认类型也是double。

Java浮点类型常量有两种表示形式

  • 十进制数形式,例如:3.14 314.0 0.314

  • 科学记数法形式,如314e2 314E2 314E-2

【示例2-11】使用科学记数法给浮点型变量赋值

double f = 314e2;  //314*10^2-->31400.0
double f2 = 314e-2; //314*10^(-2)-->3.14

float类型的数值有一个后缀F或者f ,没有后缀F/f的浮点数值默认为double类型。也可以在浮点数值后添加后缀D或者d, 以明确其为double类型。

【示例2-12】float类型赋值时需要添加后缀F/f

float f = 3.14F;
double d1 = 3.14;
double d2 = 3.14D;

老鸟建议

  • 浮点类型float,double的数据不适合在不容许舍入误差的金融计算领域。如果需要进行不产生舍入误差的精确数字计算,需要使用BigDecimal类。

【示例2-13】浮点数的比较

float f = 0.1f;
double d = 1.0/10;
System.out.println(f==d);//结果为false

【示例2-14】浮点数的比较二

float d1 = 423432423f;
float d2 = d1+1;
if(d1==d2){
   System.out.println("d1==d2");//输出结果为d1==d2
}else{
    System.out.println("d1!=d2");
}

运行以上两个示例,发现示例2-13的结果是“false”,而示例2-14的输出结果是“d1==d2”。这是因为由于字长有限,浮点数能够精确表示的数是有限的,因而也是离散的。 浮点数一般都存在舍入误差,很多数字无法精确表示(例如0.1),其结果只能是接近, 但不等于。二进制浮点数不能精确的表示0.1、0.01、0.001这样10的负次幂。并不是所有的小数都能可以精确的用二进制浮点数表示。

java.math包下面的两个有用的类:BigInteger和BigDecimal,这两个类可以处理任意长度的数值。BigInteger实现了任意精度的整数运算。BigDecimal实现了任意精度的浮点运算。

菜鸟雷区

  • 不要使用浮点数进行比较!很多新人甚至很多理论不扎实的有工作经验的程序员也会犯这个错误!需要比较请使用BigDecimal类

【示例2-15】使用BigDecimal进行浮点数的比较

import java.math.BigDecimal;
public class Main {
	public static void main(String[] args) {
		BigDecimal bd = BigDecimal.valueOf(1.0);
		bd = bd.subtract(BigDecimal.valueOf(0.1));
		bd = bd.subtract(BigDecimal.valueOf(0.1));
		bd = bd.subtract(BigDecimal.valueOf(0.1));
		bd = bd.subtract(BigDecimal.valueOf(0.1));
		bd = bd.subtract(BigDecimal.valueOf(0.1));
		System.out.println(bd);//0.5
		System.out.println(1.0 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1);//0.5000000000000001
	}
}

浮点数使用总结

  • 默认是double类型

  • 浮点数存在舍入误差,数字不能精确表示。如果需要进行不产生舍入误差的精确数字计算,需要使用BigDecimal类。

  • 避免比较中使用浮点数,需要比较请使用BigDecimal类

2.6.3 字符型变量/常量

字符型在内存中占2个字节,在Java中使用单引号来表示字符常量。例如’A’是一个字符,它与”A”是不同的,”A”表示含有一个字符的字符串。

char 类型用来表示在Unicode编码表中的字符。Unicode编码被设计用来处理各种语言的文字,它占2个字节,可允许有65536个字符。

【示例2-16】字符型举例

char eChar = 'a'; 
char cChar ='中';

Unicode具有从0到65535之间的编码,他们通常用从’\u0000’到’\uFFFF’之间的十六进制值来表示(前缀为u表示Unicode)

【示例2-17】字符型的十六进制值表示方法

char c = '\u0061';

Java 语言中还允许使用转义字符 ‘\’ 来将其后的字符转变为其它的含义。常用的转义字符及其含义和Unicode值如表2-6所示。

【示例2-18】转义字符

char c2 = '\n';  //代表换行符
表2-6 转义字符
转义符含义Unicode值
\b退格(backspace)\u0008
\n换行\u000a
\r回车\u000d
\t制表符(tab)\u0009
\“双引号\u0022
\‘单引号\u0027
\\反斜杠\u005c

注意事项

  • 以后我们学的String类,其实是字符序列(char sequence)。

课堂代码

/**
 * 测试字符类型
 * @author 高淇
 *
 */
public class TestPrimitiveDataType3 {
    public static void main(String[] args) {
        char  a = 'T';
        char  b = '尚';
        char c = '\u0061';
        System.out.println(c);
        
        //转义字符
        System.out.println(""+'a'+'\n'+'b'); 
        System.out.println(""+'a'+'\t'+'b'); 
        System.out.println(""+'a'+'\''+'b');        //a'b 
        
        
        //String就是字符序列
        String  d = "abc";
        
    }
}

2.6.4 boolean类型变量/常量

boolean类型有两个常量值,true和false,在内存中占一位(不是一个字节),不可以使用 0 或非 0 的整数替代 true 和 false ,这点和C语言不同。 boolean 类型用来判断逻辑条件,一般用于程序流程控制 。

【示例2-19】boolean类型

    boolean flag ;
    flag = true;   //或者flag=false;
    if(flag) {
             // true分支
    } else {
             //  false分支
    }

老鸟建议

Less is More!!请不要这样写:if(flag== true),只有新手才那么写。关键也很容易写错成if(flag=true),这样就变成赋值flag 为true而不是判断!老鸟的写法是if(flag)或者if(!flag)

2.7 运算符(operator)

计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操作变量。

算术运算符二元运算符+,-,*,/,%
一元运算符++,--
赋值运算符=
扩展运算符+=,-=,*=,/=
关系运算符>,<,>=,<=,==,!= instanceof
逻辑运算符&&,||,!,^
位运算符&,|,^,~ , >>,<<,>>>
条件运算符? :
字符串连接符+

2.7.1 算术运算符

算术运算符中+,-,*,/,%属于二元运算符,二元运算符指的是需要两个操作数才能完成运算的运算符。其中的%是取模运算符,就是我们常说的求余数操作。

二元运算符的运算规则:

整数运算:

  1. 如果两个操作数有一个为Long, 则结果也为long。

  2. 没有long时,结果为int。即使操作数全为short,byte,结果也是int。

浮点运算:

  1. 如果两个操作数有一个为double,则结果为double。

  2. 只有两个操作数都是float,则结果才为float。

取模运算:

  • 其操作数可以为浮点数,一般使用整数,结果是“余数”,“余数”符号和左边操作数相同,如:7%3=1,-7%3=-1,7%-3=1。

算术运算符中++,–属于一元运算符,该类运算符只需要一个操作数。

【示例2-20】一元运算符++与–

int a = 3;
int b = a++;   //执行完后,b=3。先给b赋值,再自增。
System.out.println("a="+a+"\nb="+b);
a = 3;
b = ++a;   //执行完后,c=5。a先自增,再给c赋值
System.out.println("a="+a+"\nb="+b);

2.7.2 赋值及其扩展赋值运算符

表2-8 赋值及其扩展运算符
运算符用法举例等效的表达式
+=a += ba = a+b
-=a -= ba = a-b
*=a *= ba = a*b
/=a /= ba = a/b
%=a %= ba = a%b

【示例2-21】扩展运算符

int a=3;
int b=4;
a+=b;//相当于a=a+b;
System.out.println("a="+a+"\nb="+b);
a=3;
a*=b+3;//相当于a=a*(b+3)
System.out.println("a="+a+"\nb="+b);

2.7.3 关系运算符

关系运算符用来进行比较运算,如表2-9所示。关系运算的结果是布尔值:true/false;

表2-9 关系运算符
运算符运算符示例
==等于a==b
!=不等于a!=b
>大于a>b
<小于a<b
>=大于或等于a>=b
>=小于或等于a<=b

注意事项

  • =是赋值运算符,而真正的判断两个操作数是否相等的运算符是==。

  • ==、!= 是所有(基本和引用)数据类型都可以使用

  • <、 <= 、>=、> 仅针对数值类型(byte/short/int/long, float/double。以及char)

2.7.4 逻辑运算符

Java中的逻辑运算符如表2-10所示。逻辑运算的操作数和运算结果都是boolean值。

表2-10 逻辑运算符
运算符说明
逻辑与&(与)两个操作数为true,结果才是true,否则是false
逻辑或|(或)两个操作数有一个是true,结果就是true
短路与&&(与)只要有一个为false,则直接返回false
短路或||(或)只要有一个为true, 则直接返回true
逻辑非!(非)取反:!false为true,!true为false
逻辑异或^(异或)相同为false,不同为true

短路与和短路或采用短路的方式。从左到右计算,如果只通过运算符左边的操作数就能够确定该逻辑表达式的值,则不会继续计算运算符右边的操作数,提高效率。

【示例2-22】短路与和逻辑与

//1>2的结果为false,那么整个表达式的结果即为false,将不再计算2>(3/0)
boolean c = 1>2 && 2>(3/0);
System.out.println(c);
//1>2的结果为false,那么整个表达式的结果即为false,还要计算2>(3/0),0不能做除数,//会输出异常信息
boolean d = 1>2 & 2>(3/0);
System.out.println(d);

2.7.5 位运算符

位运算指的是进行二进制位的运算,常用的位运算符如表2-11所示。

表2-11 位运算符

位运算符说明
~取反
&按位与
|按位或
^按位异或
<<左移运算符,左移1位相当于乘2
>>右移运算符,右移1位相当于除2取商

【示例2-23】左移运算和右移运算

int a = 3*2*2;
int b = 3<<2; //相当于:3*2*2;
int c = 12/2/2;
int d = 12>>2; //相当于12/2/2;

雷区

  1. &和|既是逻辑运算符,也是位运算符。如果两侧操作数都是boolean类型,就作为逻辑运算符。如果两侧的操作数是整数类型,就是位运算符。

  2. 不要把“^”当做数学运算“乘方”,是“位的异或”操作。

2.7.6 字符串连接符

“+”运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串然后再进行连接。

【示例2-24】连接符“+”

int a=12;
System.out.println("a="+a);//输出结果: a=12

2.7.7 条件运算符

语法格式:

x ? y : z

其中 x 为 boolean 类型表达式,先计算 x 的值,若为true,则整个运算的结果为表达式 y 的值,否则整个运算结果为表达式 z 的值。

【示例2-25】三目条件运算符

int score = 80;
int x = -100;
String type =score<60?"不及格":"及格";
int flag = x > 0 ? 1 : (x == 0 ? 0 : -1);
System.out.println("type= " + type);
System.out.println("flag= "+ flag);

运行结果如图2-5所示。

1.png

图2-5 示例2-25运行效果图

2.7.8 运算符优先级的问题

表2-12 运算符的优先级

优先级运算符结合性
1()括号运算符由左至右
2!、+(正号)、-(负号)一元运算符 由左至右
2~位逻辑运算符由右至左
2++、–递增与递减运算符由右至左
3*、/、%算术运算符由左至右
4+、-算术运算符由左至右
5<<、>>位左移、右移运算符由左至右
6>、>=、<、<=关系运算符由左至右
7==、!=关系运算符由左至右
8&位运算符、逻辑运算符由左至右
9^位运算符、逻辑运算符由左至右
10|位运算符、逻辑运算符由左至右
11&&逻辑运算符由左至右
12||逻辑运算符由左至右
13? :条件运算符由右至左
14=、+=、-=、*=、/=、%=赋值运算符、扩展运算符由右至左

老鸟建议

大家不需要去刻意的记这些优先级,表达式里面优先使用小括号来组织!!

逻辑与、逻辑或、逻辑非的优先级一定要熟悉!(逻辑非>逻辑与>逻辑或)。如:

a||b&&c的运算结果是:a||(b&&c),而不是(a||b)&&c

2.8 类型转换

2.8.1 自动类型转换

自动类型转换指的是容量小的数据类型可以自动转换为容量大的数据类型。如图2-6所示,黑色的实线表示无数据丢失的自动类型转换,而虚线表示在转换时可能会有精度的损失。

1.png

图2-6 自动类型转换

可以将整型常量直接赋值给byte、 short、 char等类型变量,而不需要进行强制类型转换,只要不超出其表数范围即可。

【示例2-26】自动类型转换特例

short  b = 12;  //合法
short  b = 1234567;//非法,1234567超出了short的表数范围

2.8.2 强制类型转换

强制类型转换,又被称为造型,用于显式的转换一个数值的类型。在有可能丢失信息的情况下进行的转换是通过造型来完成的,但可能造成精度降低或溢出。

语法格式:

(type)var

运算符“()”中的type表示将值var想要转换成的目标数据类型。

【示例2-27】强制类型转换

double x  = 3.14; 
int nx = (int)x;   //值为3
char c = 'a';
int d = c+1;
System.out.println(nx);
System.out.println(d);
System.out.println((char)d);

运行结果如图2-7所示。

1.png

图2-7 示例2-27运行效果图

当将一种类型强制转换成另一种类型,而又超出了目标类型的表数范围,就会被截断成为一个完全不同的值。

【示例2-28】强制类型转换特例

int x = 300;
byte bx = (byte)x;    //值为44

新手雷区

不能在布尔类型和任何数值类型之间做强制类型转换

2.8.3 基本类型转化时常见错误和问题

操作比较大的数时,要留意是否溢出,尤其是整数操作时。

【示例2-29】常见问题一

int money = 1000000000; //10亿
int years = 20;
//返回的total是负数,超过了int的范围
int total = money*years;
System.out.println("total="+total);
//返回的total仍然是负数。默认是int,因此结果会转成int值,再转成long。但是已经发生//了数据丢失
long total1 = money*years; 
System.out.println("total1="+total1);
//返回的total2正确:先将一个因子变成long,整个表达式发生提升。全部用long来计算。
long total2 = money*((long)years); 
System.out.println("total2="+total2);

运行结果如图2-8所示。

1.png

图2-8 示例2-29运行效果图

L和l 的问题:

不要命名名字为l的变量,l容易和1混淆。long类型使用大写L不要用小写。

【示例2-30】常见问题二

int l = 2; //分不清是L还是1,
long a = 23451l;//建议使用大写L
System.out.println(l+1);

2.9 简单的键盘输入和输出

为了我们能写出更加复杂的程序,可以让我们的程序和用户可以通过键盘交互,我们先学习一下简单的键盘输入和输出。

【示例2-31】使用Scanner获取键盘输入

import  java.util.Scanner;
/**
 * 测试获得键盘输入
 * @author 高淇
 *
 */
public class TestScanner {
    public static void main(String[] args) {
        Scanner   scanner =  new Scanner(System.in);
        System.out.println("请输入名字:");
        String   name =  scanner.nextLine();
        System.out.println("请输入你的爱好:");
        String  favor = scanner.nextLine();
        System.out.println("请输入你的年龄:");
        int   age = scanner.nextInt();
         
        System.out.println("###############");
        System.out.println(name);
        System.out.println(favor);
        System.out.println("来到地球的天数:"+age*365);
        System.out.println("离开地球的天数:"+(72-age)*365);
         
    }
}

运行结果如图2-9所示。
在这里插入图片描述
2-9 示例2-31运行效果图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值