数据类型
一、基本数据类型
Java 的基本数据类型有八种,分别是byte、short、int、long、float、double、boolean和char. 它们的包装类分别是Byte、Short、Integer、Long、Float、Double、Boolean 和Character.
区别见下面的表格:
类型 | 占用字节 | 占用位数 | 最大值 | 最小值 | 默认值 | 封装类 |
---|---|---|---|---|---|---|
byte | 1 | 8 | 0 | Byte | ||
short | 2 | 16 | 0 | Short | ||
int | 4 | 32 | 0 | Integer | ||
long | 8 | 64 | 0 | Long | ||
float | 4 | 32 | -3.4E-38 | 3.4E+38 | 0.0f | Float |
double | 8 | 64 | -1.7E-308 | 1.7E+308 | 0.0d | Double |
boolean | 1 | 1 | 0 | 1 | false | Boolean |
char | 2 | 16 | \u0000 | \uffff | '\u0000' | Character |
存储位置: 做为基础变量,存储在栈中;
传递方式: 做为参数是数值传递.
二、类型转换
1.自动类型转换
自动类型转换是指:范围小的数据类型可以自动转换成范围大的数据类型.
具体转换如下图所示:
自动类型转换图,实线表示不会造成数据丢失,虚线表示会有数据丢失
(1).自动转换可能会有数据溢出问题,比如
int a = 100000000;
int b = 2000;
long c = a * b;
上面代码两个int相乘,结果也是int,由于超出int范围,导致结果为负数, 正确做法是将a或者b优先转换成long型.
(2).向下转换时可以直接将 int 常量字面量赋值给 byte、short、char 等数据类型,而不需要强制转换,只要该常量值不超过该类型的范围都能自动转换。
(3).byte,short,char三种类型, 它们平级,因此不能相互自动转换,必须使用强制类型转换;
(4).表达式的数据类型自动提升, 关于类型的自动提升,注意下面的规则。
①所有的byte,short,char型的值将被提升为int型;
②如果有一个操作数是long型,计算结果是long型;
③如果有一个操作数是float型,计算结果是float型;
④如果有一个操作数是double型,计算结果是double型;
(5).特殊情况下
采用+=、*=等缩略形式的运算符,系统会自动强制将运算结果转换为目标变量的类
当运算符为自动递增运算符(++)或自动递减运算符(--)时,如果操作数为byte,short, char 类型不会发生改变
2.强制类型转换
强制类型转换也就是,强制显示的把一个数据类型转换为另外一种数据类型.
3.类型提升
所谓类型提升就是指在多种不同数据类型的表达式中,类型会自动向范围表示大的值的数据类型提升。
三、引用类型
所有的非基本数据类型都是引用数据类型
具体有:
类、接口、数组、枚举、注解、字符串
存储位置: 对象存在栈中, 内容存在堆中,对象存的是指向内容的地址;
传递方式: 做为参数是使用引用传递,但这个引用是用的拷贝形式.
四、扩展
float 和 double 转 int 时
1.如何向上取整
使用Math的方法ceil()方法
2.如何向下取整
使用Math的方法floor()方法
3.如何四舍五入
DecimalFormat的实例方法format()方法
BigDecimal的setScale()方法
ROUND_UP
舍弃非零部分,并将舍弃的非零部分左相邻的数加一
ROUND_DOWN
截断显示,不管后面的数是否是超过5还是没有超过5
ROUND_CEILING
向点左边的数据进行动态取舍,如果左边的数是正数,则和ROUND_UP,如果是负数则和ROUND_DOWN一致
ROUND_FLOOR
和ROUND_GEILING正好相反
ROUND_HALF_UP
这种方式正我们说的四舍五入, 就是大于等于0.5的部分,则和ROUND_UP一致,否则和ROUND_DOWN一致.
ROUND_HALF_DOWN,就是大于0.5的部分,则和ROUND_UP一致,否则和ROUND_DOWN一致.这种方式就是五舍六入,
ROUND_HALF_EVEN
银行家舍入法, 就是舍弃左边的数为奇数,则采用ROUND_HALF_UP方式,为偶数则采用ROUND_HALF_DOWN
ROUND_UNNECESSARY
断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException
String.format()方法
NumberFormat的format()方法
五、相关面试题
1.面试题:
byte b1=3,b2=4,b;
b=b1+b2;
b=3+4;
哪句是编译失败的呢?为什么呢?
答: b = b1 + b2 会编译失败.
因为范围小于int的byte、short和char 在进行运算时,都会自动提升自己的类型为int,所以这里等号右边最终结果是int类型,赋值给比自己范围小的byte类型,需要进行强转,高位会丢失.
考察知识点: byte、short和char在运算中,类型会自动提升为int类型.
2.java基本类型封装类和原始类型的区别及好处?
区别:
答: 区别有:
(1).存储位置不同,基本类型存储在栈中,封装类是存在两个地方,对象是存在栈中,存放的是指向内容的地址, 而值是存放在堆中;
(2).作为参数,传递方式不同, 基本类型是值传递, 封装类是引用传递;
(3).原始类型没有自己的属性和方法,而封装类有自己的属性和方法;
(4).基本类型和封装类的默认值不同,封装类是默认是null,基本类型的默认值分别是byte、short、int、long、char都是0; float是0.0f; double是0.0d, boolean是false;
好处:
基础数据类型的封装类好处就是使用面向对象的思想去操作数据.
3.&和&&的区别?
答:
相同点:
(1)、& 和 && 都可以用作逻辑运算;
(2)、都是两个条件为true才会是true;
不同点:
(1)、当&两个条件类型不是boolean类型的时候,是作为位运算符,而 &&就是纯粹的逻辑运算;
(2)、&&有短路, 当第一个条件为false的时候, 后面一个条件不会再执行,而&则没有短路逻辑.
4.switch语句可以跟哪些类型?
答:
(1)、byte、short、char和int;
(2)、在java 1.5后支持枚举类型,因为枚举类有一个ordinal方法,该方法实际上是一个int类型的数值;
(3)、在java 1.7后支持String类型,需要注意String对象不能为null.
5.String 是最基本的数据类型吗?
答: String不是最基本的数据类型,而是属于引用类型, 基本数据类型有八种,分别是byte、short、int、long、float、double、char和boolean.
6.short s1 = 1; s1 = s1 + 1;
有错吗?short s1 = 1; s1 += 1;
有错吗?
答:
(1)、s1 = s1 + 1是有错的, 因为右边的s1 + 1最中运算结果是int,大范围赋值给小范围,不会自动类型转换, 只能进行又高位丢失的强制类型转换,所以是错误的,正确的写法,应该是s1=(short)(s1 +1);
(2)、s1+=1,这个是没有错误的, 因为+=算法符在执行中有隐式的强转步骤;
7.float f=3.4;是否正确?
答: 不正确, 因为3.4默认是double类型, 大范围转小范围,需要进行强制类型转换,而不能自动类型转换. 正确的写法是: float f=3.4f 或者 float f=(float)3.4
8.Java有没有goto?
答: java中没有goto,只有没有实际用处的goto关键字
9.在Java中,如何跳出当前的多重嵌套循环?
答: 在需要跳出的循环外添加标签,比如 lable: for() ,然后在内循环使用break lable;
10.64位的JVM当中,int的长度是多少?
答: 32位
11.可以将int强转为byte类型么?会产生什么问题?
答: 可以,如果int类型的值超出了byte的范围,那么int的高位会丢失.
12.int a = 1; int b = 2;
怎么让a,b值交换?
答:
a = a ^ b;
b = a ^ b;
a = a ^ b
13.Java中,char型变量中能不能存储一个中文汉字,为什么?
答: 可以存放一个中文汉子, 因为char存储是unicode编码对应的值, 而unicode编码里面含有中文,但不包含中文生僻字,如果要存储的是生僻字,那么就不能存储了.
byte a = 127;
a+=5;
System.out.println(a);
请问输出结果是什么?
答: 输出的结果是 -124. 因为127已经是byte的最大值,再加就会超出范围,首先直接将127 + 5 = 132 将132 二进制就是10000100, 求的反码就是10000011,再求的原码就是111111100,将原码转10进制就是-124.
15.不同类型的变量在相互赋值时,什么情况下需要进行强制类型转换?
答:
(1).当类型是基本数据类型的时候,大范围到小范围就需要进行强制类型转换;
(2).当类型是引用类型时,等号右边是父类类,左边是子类类型,那么就需要进行强制类型转换.
public static void say() {
System.out.println(3 - 2.6 == 0.4);
}
判断输出结果?
答: 输出结果是false, 因为整型和浮点型进行运算,精度会有损失,造成3 - 2.6 结果并不等于0.4.
Integer i1 =200;
Integer i2 =200;
System.out.println("i1==i2: "+(i1==i2));
Integer i3 =100;
Integer i4 =100;
System.out.println("i3==i4: "+(i3==i4));
上面代码打印结果是什么?
答:
(1).第一个打印是false,因为200已经超出了Integer内部的默认缓存大小范围-128~127,超过的范围就需要使用new 关键重新创建对象,重新创建对象那么对象的指向的地址就会不一样.
(2).第二个打印是true,因为Integer内部的默认你缓存大小范围是-128~127,100属于缓存中,存储在栈中,比较的时值,所以是一样的.