数据类型转换
数据类型不一致,发生类型转换
boolean类型不能发生数据类型转换,char类型与数值运算时字符为Unicode编码
自动转换(隐式)
- 编译器自动处理完成
- 从小到大:
byte
–>short
–>char
–>int
–>long
–>float
–>double
public class Test {
public static void main(String[] args) {
long a = 10;//整数10默认是int类型,发生自动转换
System.out.println(a);
float b = 10L;
System.out.println(b);
double c = 1.1F;//1.1F发生精度丢失
System.out.println(c);
//byte + byte = int + int = int自动转换
byte d = 123;
byte e = 111;
int f = d + e;
System.out.println(f);
}
}
强制转换(显式)
- 从大到小数据类型转换需要显式加上
(待转换的类型)
- 一般不推荐使用,会发生精度损失、数据溢出。
public class Test {
public static void main(String[] args) {
//123L是long类型,强转为byte类型
byte a = (byte)123L;
System.out.println(a);
byte b = (byte)128;//发生溢出,int类型的128超出byte最大值127
System.out.println(b);//-128
int c = (int)2.1;
System.out.println(c);//2,发生精度损失
}
}
强制转换(隐式)
在数值型赋值时,只要对应的数据没有超过对应数据类型的范围,系统默认进行强制类型转换,如任何整数都是默认
int
类型,赋值给byte
、short
,任何小数默认是double
类型,赋值给float
时进行隐式数据类型强转
public class Test {
public static void main(String[] args) {
//int类型的127转换成byte类型
byte a = 127;
System.out.println(a);
}
}
其中若是常量数值运算赋值给byte
、short
时,会触发编译器的常量优化,即在编译的时候就会进行常量的运算。
public class Test {
public static void main(String[] args) {
//javac执行的时候会变成byte a = 3;
byte a = 1 + 2;
System.out.println(a);
}
}
float
与double
精度丢失
从前面自动类型转换的代码可以看出1.1F
发生了精度丢失问题,使用float和double注意
float和double类型主要是为了科学计算和工程计算而设计的。他们执行二进制浮点运算,这是为了在广泛的数字范围上提供较为精确的快速近似计算而精心设计的。然而,它们并没有提供完全精确的结果,所以我们不应该用于精确计算的场合。float和double类型尤其不适合用于货币运算,因为要让一个float或double精确的表示0.1或者10的任何其他负数次方值是不可能的(其实道理很简单,十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10)。
方法一
通过四舍五入等常规方法规避精度丢失问题,适合精度要求不高的计算。
方法二
在商业用算中使用
BigDecimal
类,而且需要在构造参数使用String类型。
-
BigDecimal(double value)
将double型数据转换成BigDecimal
型数据- 将
double
型数据转换成BigDecimal
数据,然后就可以正常进行精确计算了。等计算完毕后,我们可以对结果做一些处理,比如对除不尽的结果可以进行四舍五入。最后,再把结果由BigDecimal
型数据转换回double
型数据。
- 将
-
BigDecimal(String value)
将String型数据转换成BigDecimal
型数据附网上前辈所写工具类
import java.math.BigDecimal;
/**
* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精
* 确的浮点数运算,包括加减乘除和四舍五入。
*/
public class Arith{
//默认除法运算精度
private static final int DEF_DIV_SCALE = 10;
//这个类不能实例化
private Arith(){
}
/**
* 提供精确的加法运算。
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1,double v2,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
运算符
操作符
算术运算符
+ | 加法 – 相加运算符两侧的值 |
---|---|
– | 减法 – 左操作数减去右操作数 |
* | 乘法 – 相乘操作符两侧的值 |
/ | 除法 – 左操作数除以右操作数取整 |
% | 取余 – 左操作数除以右操作数的余数 |
++ | 自增: 操作数的值增加1 |
— | 自减: 操作数的值减少1 |
-
前增增(减减)(++a,–a): 先进行自增或者自减运算,再进行表达式运算。
-
后增增(减减)(a++,a–): 先进行表达式运算,再进行自增或者自减运算。
-
变量在独立运算时两者没有区别
同时
+
还可被用于char
加法提升为int
,或拼接字符串"Hello"+"World"=="HelloWorld"
。但是String
+int
=String
,如"10"+24=="1024"
。
关系运算符
== | 检查如果两个操作数的值是否相等,如果相等则条件为真。 |
---|---|
!= | 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 |
位运算符
& | 如果相对应位都是1,则结果为1,否则为0 |
---|---|
| | 如果相对应位都是 0,则结果为 0,否则为 1 |
^ | 如果相对应位值相同,则结果为0,否则为1 |
〜 | 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 |
<< | 按位左移运算符。左操作数按位左移右操作数指定的位数。 |
>> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 |
>>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 |
将数值转变为二进制进行位运算
逻辑运算符
&& | 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 |
---|---|
| | | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 |
! | 称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 |
赋值运算符
= | 简单的赋值运算符,将右操作数的值赋给左侧操作数 |
---|---|
+ = | 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 |
– = | 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 |
* = | 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 |
/ = | 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 |
%= | 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 |
<< = | 左移位赋值运算符 |
>> = | 右移位赋值运算符 |
&= | 按位与赋值运算符 |
^ = | 按位异或赋值操作符 |
| = | 按位或赋值操作符 |
三元运算符
public class Test {
public static void main(String[] args) {
int e = 1 > 2 ? 1 : 2;
//1>2为真值为1,为假为2
System.out.println(e);//2
}
}
通过表达式1 关系运算符 表达式2? 值1:值2
来进行运算。
instanceof
运算符
比较一个对象是否属于一个类型,格式为
待比较对象 instanceof 类型名称
。
public class Test {
public static void main(String[] args) {
String a = "";
boolean e = a instanceof String;
System.out.println(e);//true
}
}
留言