Java变量
变量概述
每个变量都有一个对应的数据类型以及变量名
变量名,类名,方法名等等标识符命名规则
-
组成:由26个字母大小写,0-9,- 或 $ 组成,不可以以数字为开头命名,中间不能留有空格
-
不可以使用关键字和保留字
-
区分大小写,长度无限制
变量的声明
// 数据类型 + 变量名,变量名...
int age;
String name;
String school,grade;
// 注意变量名不要是java保留字(关键字)
变量初始化
// 成员变量可以不用赋值 有默认初始化
// 局部变量必须初始化(两种方式)
int num;
num = 10;
int num2 = 10;、
// jdk10之后,可以不需要声明类型(从变量的初始值来判断类型)
var i = 10;
数据类型(重点)
java是一种强制类型语言,每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间(字节)
细节:字符串本质是类,属于引用数据类型
整数的类型
| 类型 | 占用存储空间 | 范围 |
|---|---|---|
| byte 字节 | 1字节 | -128 ~ 127 |
| short 短整型 | 2字节 | -2^15 ~ 2^15-1 |
| int 整型 | 4字节 | -2^31 ~ 2^31-1 |
| long 长整型 | 8字节 | -2^63 ~ 2^63-1 |
1字节(byte) = 8 位(bit)
bit 计算机中的最小的存储单位 byte 计算机中基本存储单位
整数型注意细节
-
数值常量值默认为int类型
-
长整型后面有一个后缀(L或l)
// 自动转型 Long num = 1000; int -> long // 赋值 Long num2 = 40000000L; // 反问:那为什么需要特定后缀L,不是自动转型不就可以了吗? // 如果你的数值在int范围内,那自然都没事;但是当你要赋值一个int范围外的数字又该怎么做呢? -
十六进制数值前缀:0X或者0x;八进制数值前缀:0 ;二进制数值前缀:0b 或者 0B (记住是数字0)
// 十六进制 OXCAFE // 八进制 010 // 二进制 0B1001 0B1_0000_0000 // jdk7以后 编译时会自动去除下划线 -
注意java没有任何无符号形式的关键字(unsigned)但是提供了方法处理
浮点类型
浮点数字 = 符号位 + 指数位 + 尾数位 (尾数位可能丢失,造成精度的损失)
| 类型 | 占用存储空间 | 范围 |
|---|---|---|
| float (单精度) | 4字节 | -3.403E38 ~ 3.403E38-1 |
| double (双精度) | 8字节 | -1.798E308 ~ 1.798E308-1 |
备注:E38 指的是 10^38
浮点数注意细节
-
浮点型常量默认为double类型
-
float 后面需要添加f 或 F,double后面可加可不加
float num1 = 1.0; // 错误 double num2 = 1.1; // 正确 float num3 = 1.2F; // 正确 double num4 = 1.3f; // 正确 -
浮点型常量的表示形式
double num = 1.0; // 十进制数形式 1.0f .512 == 0.512(小数点必须在可以省略0) double num5 = 5.12e2; // 科学计数法 5.12e2 == 512 5.12E-2 == 0.0512 -
通常情况下我们使用double 精度高
double num = 1.23456789123f; float num1 = 1.23456789123f; System.out.println(num); // 1.23456789123 System.out.println(num1); // 1.2345679 -
比较 小数数字是否相等时要注意:最好不要直接去比较两个浮点数是否 ==,最好是两个浮点数的差值绝对值在某个精度范围内来进行比较(如0.000001)
double num = 8.1 / 3; double num1 = 2.7; System.out.println(num); // 2.6999999999999997 System.out.println(num1); //2.7 if(Math.abs(num - num1) < 0.000001){ System.out.println("相等"); } -
对于使用strictfp关键字标记的方法必须严格的浮点计算来生成结果,好处:不仅让浮点数运算更加精确,而且不会因为不同硬件平台所执行而效果不同;坏处:降低性能
// 主方法下的所有浮点数都严格按照IEEEE-754标准进行运算 public static strictfp void main(String[] args){}
字符类型
| 类型 | 占用存储空间 | 表示 |
|---|---|---|
| char | 2字节 | 表示单个字符 |
字符型注意细节
-
字符常量是用单引号(’‘)括起来的单个字符
char c = 'n'; -
单引号里面可以放入转义字符(虽然有两个字符,但是它是表示一个字符的 比如 // 表示 / )
char ch = '//' -
char 的本质就是一个整数(unicode表) (注意:字符 --> 数字 unicode 数字 --> 字符 )
// unicode 编码 'a' -- 97 // char 类型字符可以进行加减 但是注意超出范围的问题 'a' + 10 -- 107
字符在计算机里的存储方式
存储:‘a’ ==> 97 ==> 二进制数(11000001) ==> 存储
读取: 二进制(11000001) ==> 97 ==> 'a' ==> 读取
字符编码表
- ASCll编码表,一个字节表示,ASCII实际上可以表示256个字符,但是只使用了128个
- Unicode编码表 ,固定两个字节表示字符(字符和汉字统一都是占用2个字节)
- utf-8编码表,大小可变的编码(字母使用1个字节,汉字使用3个字节)
- GBK编码,大小可变的编码(字母使用1个字节,汉字使用2个字节)
- big5编码,繁体字,台湾,香港(了解)
布尔类型
常用于条件判断语句 if - else while
| 类型 | 占用存储空间 | 表示 |
|---|---|---|
| boolean | 1字节 | + / false |
注意:布尔类型不能和整数型相互转换(这里和c/c++不同)
数据类型转换
自动类型转换
精度小的数据类型自动转换为精度大的数据类型
自动类型转换相关的注意细节
-
当一个二元运算符连接两个值时,先将两个操作数转换成同一类型的数据进行计算(转换成操作数两边范围最大的数据类型)
// 伪代码 顺序:double -> float -> long -> int -> short -> byte // double -> float -> long -> int -> char if(两个操作数中有一个是double类型数据){ 另一个操作数也会强制转换成double类型数据 }else if(两个操作数中有一个是float类型数据){ 另一个操作数也会强制转换成float类型数据 }... // 依次下去 -
(byte,short)和 char 之间不会自动转换
-
注意赋值区别(具体数值赋值和变量赋值)
// 具体值赋值会先进行范围的判进行赋值 char c = 10000; short s = 'a'; byte b = 'b'; // 变量赋值就是依据自动类型转换或者强制类型转换 c = (char)s; s = (short)c; -
整数赋值和浮点数赋值的注意点
// 整数之间的赋值 byte n = 10; // 具体数值赋值,先进行判断该数值是否在byte范围,如果在编译就不会出错,便会赋值 int n1 = 10; n = n1; // int类型变量无法直接赋值给byte类型(可以进行强制类型转换) // 小数之间赋值 float f = 10.0; // 错误,float中将无法进行比较,本来都是一个估算值,无法进行比较范围,因此10.0是double类型无法自动转型为float -
byte,char,short 三者进行计算,在计算时首先转换成int类型数据(变量计算都会转换成int类型,不管是否是同类型数据相加减)
-
boolean 数据类型不参与类型转换
强制类型转换
概念: 自动类型转换的逆过程,将范围大的数据类型转换成范围小的数据类型,使用时需要在变量或者具体值前面加()
好处: 根据程序员的意愿进行修改 坏处: 范围超出了想要转换的数据类型,会导致溢出问题
// 例如 double ==> float
float f = (float)10.0;
强制类型转换的注意细节
-
强制符号只针对最近的操作数有效,往往会使用小括号来提升优先级
int n = (int)10*3.5+12*2.3; // 错误 int n = (int)(10*3.5+12*2.3); // 正确 -
注意区别 i++ 和 i = i+1的区别
// 直接上代码 class test{ public static void main(String[] args) { byte j = 10; j++; short k = 11; k += 1; int i = 11; i = i + 1; } } // 反编译看细节 class test { test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: bipush 10 // 将数值10压入栈 2: istore_1 // 栈中弹出一个数(10),赋值给局部变量j(_1表示赋值给第一个局部变量,即j) 3: iload_1 // 将局部变量j(_1表示第一个局部变量,即j)的值入栈,此时栈顶的值为10 4: iconst_1 // 将常量1(_1)压入栈中 5: iadd // 相加常量和局部变量j => 11 6: i2b // 注意!! 强制类型转换 int -> byte 7: istore_1 8: bipush 11 10: istore_2 // 栈中弹出一个数(11),赋值给局部变量k(_2表示赋值给第二个局部变量,即k) 11: iload_2 12: iconst_1 13: iadd 14: i2s // 注意!! 强制类型转换 int -> short 15: istore_2 16: bipush 11 18: istore_3 19: iload_3 20: iconst_1 21: iadd 22: istore_3 23: return } // 总结 i++ && i += 1 // 会进行强制类型转换成原来的类型 i = i+1 // 如果i是byte或者short类型都不能通过编译,因为i+1会自动转换成int类型,int类型必须通过强制类型转换才可以转换成short或者byte类型
基本数据类型和String类型的转换
-
将基本数据类型+"" ==> String类型
String s = 10 + ""; -
通过基本数据类型的包装类调用parseXX方法
String s = "2" Integer.parseInt(s); Double.parseDouble(s); Float.parseFloat(s); Short.parseShort(s); Long.parseLong(s); Boolean.parseBoolean("true"); Byte.parseByte(s); // char 根据索引来判断 String str = "123456789"; char c = str.charAt(0);