1.Java的数据类型分为三大类
布尔型,字符型和数值型
其中数值型又分为整型和浮点型
2.Java的变量类型
布尔型 boolean
字符型 char
整型 byte,short,int,long
浮点型 float,double
3.数据类型转换
Java中数据类型转换分为三种,简单数据类型转换,字符串与其他类型转换,其他实用数据类型转换
(1)简单数据类型转换
在Java中,整型,实型,字符型被视为简单数据类型。
这些类型级别从低到高:(byte,short,char)-> int -> long -> float -> double
从低级变量到高级变量那是自动类型转换,从高级变量到低级变量那是强制类型转换,包装类过渡类型转换
(2)低级变量可以直接转换为高级变量
如:byte b;
int i=b;
float f=b;
如果低级类型为char型,向高级类型(整型)转换时,会转换成对应的ASCII码值
如:char c='c';
int i=c;
输出i的结果是:99
对于byte,short,char三种类型而言,它们是相同级别的,不能相互转换,可以使用强制类型转换
如:short i=99;
char c=(char)i;
输出c的结果是:c
(3)强制类型转换
int i=99;
byte b=(byte)i;
(4)包装类过渡类型转换
Java的包装类就是可以直接将简单类型的变量表示为一个类,Java共有6个包装类,分别是Boolean,Character,Integer,Long,Float,Double
包装类到底有什么作用?
在进行简单数据类型转换时,可以利用包装类进行中间过渡。一般情况下,首先声明一个变量,然后生成一个对应的包装类,就可以利用包装类的各种方法进行类型转换。
如:当希望把float型转换为double型
float f1=100.00f;
Float F1=new Float(f1);
Double d1=F1.doubleValue();
(5)字符串与其他数据类型的转换
几乎所有的java.lang.Object类派生的所有类都提供了toString()方法,就是可以将该类转换成字符串。
如:int f1=3.14f;
Float F1=new Float(f1);
String sf1=F1.toString();
栗子:给出以下代码,请给出结果.
class Two{ Byte x; } class PassO{ public static void main(String[] args){ PassO p=new PassO(); p.start(); } void start(){ Two t=new Two(); System.out.print(t.x+””); Two t2=fix(t); System.out.print(t.x+” ” +t2.x); } Two fix(Two tt){ tt.x=42; return tt; } }
结果是:null,42,42
注意:x是包装类Byte,引用类型!不是基本类型byte。实例该类对象时,如果成员变量没有显示初始化那么Java默认初始化为null.
该题中引用类型t作为形参进行传递,形参的改变会改变实参的值,所以再次打印t.x时已经变为42了。
4.+能使类型提升
如:指出以下程序的错误之处:
short s=1;
s=s+1;
原因是,s+1为int,不能赋值给short。
栗子1:
boolean b=true?flase:true == true?false:true;
结果是:false
原因:(1)三目运算符是右结合性的,(2)==的优先级比 ? : 都高,所有要先算,
true?flase:((true == true)?false:true)
之后就是true?flase: (true ?false:true ) -->flase?false:false --> false
栗子2:
int a=5;
System.out.println("value is"+((a<5)?10.9:9));
结果是:9.0
原因:Java会根据运算符的精度类型进行自动类型转换。由于前面一个是10.9,那么后面的9就会自动变成9.0
栗子3:(重要)
布尔逻辑与(&)和逻辑与(&&),布尔逻辑或(|)和逻辑或(||)的区别
特点:凡是&&前面是false,那么&&后面的表达式就不用再做了。||前面的是true,||后面的就不用再做了。
但是无论运算符&、| 前面的是true,还是false,运算符后面的表达式都的继续进行运算。
如:int m=n=5;
if((m!=5)&&(n++=5)){}
System.out.println(n);//结果是5,因为&&前面的是false,&&后面的就不用做了
int m=n=5;
if((m!=5)&(n++=5)){}
System.out.println(n);//结果是6
int m=n=5;
if((m==5)||(n++=5)){}
System.out.println(n);//结果是5,因为||前面是true,后面的就不用做了
int m=n=5;
if((m==5)|(n++=5)){}
System.out.println(n);//结果是6
5.传值与传引用
不管Java参数的类型是什么,一律传递参数的副本。如果是传值,那么传递的是值的副本;如果Java是传引用,那么传递的是引用的副本。
(1)对于基本类型变量而言,传值就是把自己复制一份传递,即使自己的副本变了,自己也不变。
(2)对于对象类型而言,它传递的引用副本指向自己的地址,而不是自己实际值的副本。
为什么要这么做呢?
因为对象类型是放在堆里的,一方面,速度相对于基本类型比较慢,另一方面,对象类型本身比较大,如果采用重新复制对象值的办法,浪费内存且速度慢。
(3)String类型也是对象型变量,所以它必然传引用副本。
Java中的引用到底是什么?
Person person=new Person("张三");
这个person就是一个引用,是引用变量,保存了它所指向的对象的在堆中的地址。它是存在栈中的,指向新创建的Person对象。
栗子1:
public class Test{ public static void test (StringBuffer str){ str.append(",world!"); } public static void main(String[] args){ StringBuffer string =new StringBuffer("Hello"); test(string); System.out.println(string); } }
运行结果是:Hello,World!
这里的string是一个引用,Java对于引用形式传递对象类型的变量时,实际上是将引用作为一个副本传进方法函数的。那么这个函数里面的引用副本所指向的是什么?是对象的地址。
通过引用副本(复制的钥匙)找到地址(仓库)并修改地址中的值,也就修改了对象。(但是这样的引用副本有时效性,函数结束,钥匙销毁。)可以理解为,张三拿一把复制的钥匙,进了仓库,在仓库改变了很多东西,那李四拿着另外一把钥匙打开这个仓库,这个仓库还是那个仓库,里面的东西肯定改变了。
栗子2:
public class Test{ public static void test (String str){ str="world"; } public static void main(String[] args){ String string ="Hello"; test(string); System.out.println(string); } }
运行结果是:Hello
str="world";隐含着让Java生成一个新的String对象。当执行str="world";时,其过程为:首先系统会自动生成一个新String对象,并把这个新对象的值设为"world",然后把这个引用赋给str(可以理解为str这把钥匙原来指向"Hello"这个仓库,但是现在要求str这把钥匙重新指向"world"这个仓库。),所以既然对象是新的,那就与原来的"Hello"没有任何关系。当函数结束,str作用消失,原来得内存地址上的内容并未改变。仍然是"Hello"。
栗子3:下列 java 程序输出结果为______。
int i=0; Integer j = new Integer(0); System.out.println(i==j); System.out.println(j.equals(i));
true,true
解释:
==如果是primitive主类型,那么比较值;如果是对象,那么比较引用地址
i==j ,这个是基本类型与 Integer 的比较, j 会自动拆箱成 int 类型,然后比较的是值。因此返回真。
j.equals(i) ,调用 equals 方法后,这个 i 会自动装箱成 Integer 类型,然后再比较值,所以也返回真。