基本数据类型在计算的时候都会向数值范围大的方向转换
【注意:数值范围较大和数据类型的字节数更多并不一定对应,比如float只有四个字节,long有八个字节,但是float表示的范围更大,这是因为它们的底层原理不同】
举例如下:
例一,所有的byte类型,short类型,char值,int类型在相互运算的时候都会变成int类型,数值常量默认为int
//数值常量默认为int
//所有的byte类型,short类型,char值,int类型在相互运算的时候都会变成int类型
public class Demo{
public static void main(String[] args){
byte b = 1;
byte b1 = b + 1;
//在等式的右边,b为byte类型,1 默认为int型,i + 1就会转化成int型,而int型是4个字节,
//等式左边的b1是byte类型,一个字节,所以会报错(不兼容的类型: 从int转换到byte可能会有损失)
}
}
public class Demo{
public static void main(String[] args){
byte b = 1;
int b1 = b + 1; //将b1的类型改为int型,就没问题了
}
}
例二,所有的byte类型,short类型,char值,int类型在相互运算的时候都会变成int类型:
///所有的byte类型,short类型,char值,int类型在相互运算的时候都会变成int类型
public class Demo{
public static void main(String[] args){
byte b = 1;
byte b1 = 3;
byte b3 = b + b1; //哪怕是两个byte之间进行运算也会转化成int,所以会报错
//解决办法就是:把b3的类型改成int
}
}
例三:
public class Demo{
public static void main(String[] args){
char c = 'a';
int i = c + 1;
System.out.println(i);//c的ASCII码是97,再加1,所以结果是98
}
}
例四,int,float,double自身来进行计算的时候没有类型的提升,如果超出范围就会出现精度的损失:
public class Demo{
public static void main(String[] args){
int x = 2147483647;//int的最大值
int y= 66;
System.out.println(x+y);//结果超出int的范围,会显示一个错误数据
}
}
给个题目来做一做:
public class Demo{
public static void main(String[] args){
int x = 4;
System.out.println("x is " + ((x > 4) ? 99.9 : 9)); //输出会是什么呢?
}
}
为什么输出是 9.0 而不是 9 ;这就涉及到上面所讲的基本数据类型的自动转化了,99.9 : 9
这里的运算中,9 的类型提升了,从int变成了float
那么?怎么实现大容量数据类型向小容量数据类型去转换(比如int 向 type转换)而不报错呢?
基本数据类型强制转换的语法:(目标类型)值
举例:
public class Demo{
public static void main(String[] args){
byte b = 1;
byte b1 = 2;
//两个byte类型的数据进行四则运算时会自动转化为int
byte b3 = b + b1;
}
}
public class Demo{
public static void main(String[] args){
byte b = 1;
byte b1 = 2;
byte b3 =(byte)( b + b1); //就这么使用强制转换的语法就行了
}
}
注意:强制转换的存在意义是有前提的,大容量数据转换为小容量数据时,不会失去精度,才有转换的意义!
比如:
public class Demo{
public static void main(String[] args){
byte b = 1; //byte类型的最大值是127
int b1 = 127;
byte b3 =(byte)( b + b1); //很显然b+b1后的数超出了byte的可表示范围,再强制转换,得不到有意义的数
System.out.println(b3);
}
}
(补充一点:包装类现在没有那么常用了,因为jdk1.5版本之后,它产生了一个新的特性:自动拆装包【可以自动的把包拆成基本类型,也可以自动的把基本类型包装成包装类】)
java是一个完全的面向对象的编程语言,
而java中的8个基本数据类型却没有类的概念,
在我们眼中,包装类是基本类型和引用类型之间交换的桥梁
java.lang
包,所以它们不需要导包,可以直接用Number
Serializable和Comparable
下面就以Integer
来说明一下包装类吧:
八个包装类中有六个(Byte,Short,Integer,Long,Float,Double)是与数字相关,都默认继承父类Number
Number
中有一种方法叫xxxValue()
,例如:
这些(一个种类的)方法:将一个包装类型转化为对应的基本类型(拆包),这个知道一下就好,基本上没有什么用处
jdk1.5版本之前,包装类与基本数据类型的转化:
Integer i = new Integer(10); 包装
int value = i.intValue(); 拆包
jdk1.5版本之后:
Integer i = 10; 自动包装
int value = new Integer(10); 自动拆包
将String转换成int有两种方法:
int value = Integer.parseInt("666"); 将字符串直接转换成int
int value = new Integer("666"); 先把String构成一个Integer对象,再自动拆成int
1.==
与equals()
区别
2.==
可以比较基本数据类型(变量中的值),也可以比较引用数据类型(变量中存储的地址引用)
3.equals()
是Object
类中继承过来的方法,每一个引用类型都可以调用
4.默认继承的equals()
比较与==
一致,如果想要改变比较规则,我们可以重写equals()
5.但是Integer重写了equals()
,所以Integer比较的是数值
public class Demo {
public static void main(String[] args){
Integer i1 = 10;
Integer i2 = 10;
Integer i3 = new Integer(10);
Integer i4 = new Integer(10);
System.out.println(i1 == i2);
System.out.println(i1 == i3);
System.out.println(i3 == i4);
System.out.println(i1.equals(i2));
System.out.println(i1.equals(i3));
System.out.println(i3.equals(i4));
}
}
首先:==
比较的是什么?equals()
比的是什么?还要了解i1,i2,i3,i4
它们四个在内存中的存储方式
Integer i1 = 10;
Integer i2 = 10;
---
10自动包装成Integer对象
这个对象存放在Integer对应的静态元素区里
i1,i2都指向这个对象
Integer i3 = new Integer(10);
---
new就是堆内存产生新的空间,这个对象里面存了一个10
i3指向这个新产生的空间
Integer i4 = new Integer(10);
---
new,又产生了一个新的对象,这个对象里面也存了一个10
i4指向这个新的空间(不同于i3指向的空间)
==
比较的是变量空间里面存放的内容(都是地址)
System.out.println(i1 == i2); //true
System.out.println(i1 == i3);//false
System.out.println(i3 == i4);//false
equals()代码:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
---
equals()在包装类中被重写了,比较的不再是地址,而是值
所以:
System.out.println(i1.equals(i2));//true
System.out.println(i1.equals(i3));//true
System.out.println(i3.equals(i4));//true
上面的题目代码全部不变,只把全部10改为1000,再输出,结果会有变化
public class Demo {
public static void main(String[] args){
Integer i1 = 1000;
Integer i2 = 1000;
Integer i3 = new Integer(1000);
Integer i4 = new Integer(1000);
System.out.println(i1 == i2); 很显然,这个输出变成了false,其余的没变
System.out.println(i1 == i3);
System.out.println(i3 == i4);
System.out.println(i1.equals(i2));
System.out.println(i1.equals(i3));
System.out.println(i3.equals(i4));
}
}
Integer i1 = 1000;
Integer i2 = 1000;
System.out.println(i1 == i2); 为什么这个输出变成了false呢?
还要研究Integer
类加载的过程
Integer类有一个内部类的代码:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
从这个代码可以看出:
Integer类加载的时候,自己有一个静态空间,空间内立即加载Integer类型的数组,数组内存储256个Integer对象,范围从 -127 ~ 128 ,如果我们用的对象范围在这之内(比如10),直接去静态区中找对应的对像;如果超出范围(比如1000),它会帮我们new出一个新对象