Java语法基础——变量
变量的语法规定:
- 变量必须有明确类型
- 变量必须声明,并且初始化后才能使用
- 变量有作用域,超过作用域释放
- 变量作用域:声明变量开始到块结束(语句块:{})
变量的类型
|——基本类型
|——整型(最常用int,但要注意使用范围;short很少用,byte用于表示文件等底层数据)
|——byte(8位:-128~127)
|——short(16位:-32768~32767)
|——int(32位:-2^31~2^31-1,约2G)
|——long(64位:-2^63~2^63-1)
|——浮点型
|——float(32位),double(64位)
|——字符型
|——char(16位:刚好存一个汉字)
|——布尔型
|——boolean(8位,一个字节)
|——引用类型
注意:eclipse中默认使用int表示整数,double表示小数,其他类型需要在末尾加字母
int:
- 任何整数的“字面量”都是int类型(字面量就是直接写出来的常数,如:5)
- “整数字面量”在不超过范围情况下可以给“小类型变量”赋值
- 整数超范围运算会溢出
1 public class Test { 2 public static void main(String[] args) { 3 int i = -5; 4 byte b ; 5 //b = 128;//编译错误,超过byte范围 6 //b = i;//编译错误,编译器不确定int变量i的取值,不能赋值给byte变量b 7 b = (byte)i; 8 System.out.println("0xffffff80"+0xffffff80);//-128,电脑只认补码 9 System.out.println("80是"+0x80);//128 10 //b = 0x80;//编译错误,超过范围 11 b = 0xffffff80; 12 //int x= 080;//编译错误,8进制没有8 13 int max = 0x7fffffff; 14 int a = max +1; 15 System.out.println(a);//超范围溢出,变成最小值 16 //x是 7fffffff(高位是0)加1变成80000000(高位变成1),即是int型最小值 17 System.out.println("0x80000000是:"+0x80000000); 18 }
long:
- 使用L后缀的字面量(直接量)是long类型
- 计算时间规定:long类型从GMT 1970年元旦开始累计的毫秒数作为时间,这个规定将时间转换为整数long
- 使用System.currentTimeMillis()获得系统时间
- 时间是一个long类型整数
1 public class Test { 2 public static void main(String[] args) { 3 //long max = 0x7fffffffffffffff;//编译错误,超过int范围 4 long max = 0x7fffffffffffffffL; 5 System.out.println(max); 6 long now = System.currentTimeMillis(); 7 System.out.println(now); 8 long year = now/1000/60/60/24/365+1970; 9 System.out.println("今年是公元"+year+"年"); 10 } 11 }
float,double
1、由于float精度比较差,很少使用,大多使用double
精度:尾数长度决定
范围:指数大小决定(例如2的13次方,2^13,2为底数,13为指数)
float的精度没有int高,但是float的大小范围比int大
2、浮点数字面量默认是double类型(D为后缀是double,f后缀是float)
1 public class Test { 2 public static void main(String[] args) { 3 float fa = 5;//5没有后缀f,是int型 4 float fb = 5; 5 float fc = fa - fb; 6 System.out.println("fc="+fc);//10.0 7 int a = 0x7fffffff; 8 int b = 0x7ffffff0; 9 fa = a; 10 fb = b; 11 System.out.println("fa-fb="+(fa-fb));//0.0 12 //float精度没有int高,当把int型a赋给float时会损失精度 13 System.out.println("fa+fb="+(fa+fb));//4.2949673E9,float范围比int大 14 System.out.println("a+b="+(a+b));//-17,超过int范围发生溢出 15 16 double da = a; 17 double db = b; 18 System.out.println("da-db="+(da-db)); 19 double dx = 3.1435256364363643634636346346363;//打印出来是3.1435256364363644 20 float fx = 3.1435256364363643634636346346363f;//精度损失,打印出来是3.1435256 21 //float fx = 3.1435256364363643634636346346363;//编译错误,double字面量不能直接赋给float 22 System.out.println("dx="+dx); 23 System.out.println("fx="+fx); 24 //注意区别1 1L 1.0 1D 1F——1.0和1D都是double 25 //浮点数计算不精确,避免使用浮点数进行精确计算,可用BigDecimal 26 27 double x = 2.6; 28 double y = x - 2; 29 System.out.println("y="+y);//0.6000000000000001 30 } 31 }
char:
1、字符是一个16位无符号“整数”!
字符的数值是unicode编码值
整数范围:0~65535
2、unicode 8万多字(unicode英文编码与ASCII编码一致)
规定:'中' 编码数字 20013
3、Java char类型支持了i18n(国际化),就是支持全球文字
4、在中文本地系统中,字库(字模)只能显示两万多汉字
5、字符 字面量 就是一个char整数字面量 '中'
6、字符可以参与数学运算
‘A’的编码 65
‘0’的编码 48
7、特殊字符,可以使用转义字符书写
‘\n’new line换行
‘\r’return回车
‘\u4e2d’unicode 16进制编码
8、控制字符也是字符,如:回车,换行,退格等,但是控制字符输出效果不明显
1 public class Test { 2 public static void main(String[] args) { 3 char c = 20013;//字符是一个数 4 System.out.println(c);//中 5 c = 45666; 6 System.out.println(c);//不可显示 7 8 c = 'A'+2; 9 System.out.println(c); 10 System.out.println('A');//65,'A'是10进制编码 11 System.out.println('\n');//换行,而本身System.out.println就是换行打印,所以空了两行 12 System.out.println((int)'龙'); 13 System.out.println('\u4e2d');//中 14 System.out.println((char)20013);//中 15 } 16 }
注意:
- java中字面量(直接量)之间的运算,在编译期间,优化为运算结果了
- java中int类型的字面量,在不超过小类型范围情况下,可以给小类型变量赋值
- 由于java编译器,不能确定变量表达式的结果,不允许直接将大类型变量给小类型赋值
1 public class Test { 2 public static void main(String[] args) { 3 int n = 2; 4 char c; 5 c = 'A'+2;//int 67 6 //c = 'A'+n;//编译错误,不能将int赋给char 7 c =(char)('A'+2); 8 //c = 'A'+65530;//编译错误,超过char范围 9 10 byte b; 11 b = 4+6; 12 //b = 4+n;//有不确定变量,编译错误 13 //b = 4+126;//超出范围,编译错误 14 b = 4+0xffffffff; 15 } 16 }
符号运算封闭性原则
- 同种类型参与运算,得到同种类型结果
- 小于32位数(byte,short,char)按照32位计算
- 注意,整数的除法是整除
1 public class Test { 2 public static void main(String[] args) { 3 int a,c; 4 long l; 5 a = 0x7fffffff; 6 l = a+1;//a和1都是int型,同类型相加还是int型,然后再符号位扩展变成long型 7 System.out.println("l="+l);//溢出,为最小值 8 l = (long)a + 1;//先转换再相加 9 System.out.println("l="+l);//正常 10 11 byte b1 =5; 12 byte b2 =6; 13 //byte b3 = b1+b2;//编译错误,编译器不能确定变量取值范围 14 byte b3=(byte)(b1+b2); 15 16 System.out.println(5/2);//得2 17 //下面4种都得2.5 18 System.out.println(5.0/2); 19 System.out.println(5D/2); 20 System.out.println((double)5/2); 21 System.out.println(5/2.0); 22 23 System.out.println(80/100);//整除,结果是0 24 System.out.println(80.0/100);//浮点除,结果是0.8 25 } 26 }
类型转换
- 自动类型转换,也称为 隐式转换
- 强制类型转换
1 public class Test { 2 public static void main(String[] args) { 3 int i = -1;//i 是32位数 4 long l = i;//l 是64位数,发生符号位扩展 5 System.out.println("l="+l); 6 System.out.println(Integer.toBinaryString(i)); 7 System.out.println(Long.toBinaryString(l)); 8 //Long.toBinaryString方法的参数是long类型 9 //在i向long类型参数传递时候发生了自动类型转换! 10 System.out.println(Long.toBinaryString(i)); 11 //System.out.println(Integer.toBinaryString(l));//报错 12 l = 0xff00000005l; 13 System.out.println("l="+l); 14 System.out.println("Long.toBinaryString(l)="+Long.toBinaryString(l)); 15 System.out.println((int)l);//5,超过整数范围,发生高位溢出现象 16 //强制类型转换也会发生精度损失 17 double px = 3.523531263464343333342634634*10000; 18 double p = 9.8; 19 float f = (float)px; 20 l = (long)px; 21 System.out.println("px ="+px);//35235.31263464344 22 System.out.println("f ="+f);//35235.312 23 System.out.println("l = "+l);//35235 24 l = (long)(px+0.5);//利用强制转换实现4舍5入 25 System.out.println(l);//35235 26 System.out.println((long)p);//9 27 } 28 }
下面内容摘自粉笔网http://www.fenby.com/learn/courseExercises/27#
1. 局部变量只会存活在声明该变量的方法中
public void read() { int s = 42; //'s'只能用在此方法中,当方法结束时s会消失 }
变量s只能用在read()方法中。换句话说,此变量的范围只局限在所属的方法范围内。其余的程序代码完全见不到s。
2. 实例变量的寿命与对象相同。如果对象还活着,则实例变量也会是活的。
public class Life { int size; public void setSize(int s) { size = s; //'s'会在方法结束时消失,但size在类中到处都可用 } }
此时s变量(这次是方法的参数)的范围同样也只限制在所属的setSize()这个方法中。
静态的方法不能调用非静态的变量
静态的方法是在无关特定类的实例情况下执行的,也不会有该类的实例出现。因为静态的方法是通过类的名称来调用,所以静态的方法无法引用到该类的任何实例变量。在此情况下,静态的方法也不会知道可以使用哪个实例变量值。
如果你尝试在静态的方法内使用实例变量,编译器会认为:“我不知道你说的是哪个实例的变量!”
如果你要编译下面这段程序代码:
public class Duck { private int size; public static void main(String[] args) { System.out.println("Size of duck is " + size); } public void setSize(int s) { size = s; } public int getSize() { return size; } }
你会得到编译器提示的错误。因为它不知道你说的size是哪个实例的变量!
静态的方法也不能调用非静态的方法
非静态的方法做什么工作?它们通常是以实例变量的状态来影响该方法的行为。getName()方法会返回name变量的值。谁的名字?当然是被调用对象的。
但是这一段无法通过编译:
public class Duck { private int size; public static void main(String[] args) { System.out.println ("Size is " + getSize()); } public void setSize(int s) { size = s; } public int getSize() { return size; } }
编译器会提示错误,因为它还是不知道是谁的size?