Java语法是C++语法的一个"纯净版本",所以Java的数据类型和运算符和C++中的是差不多的,不是很难,下面进行简单的介绍。
整型变量
Java中整型变量byte(1个字节)、short(2个字节)、int(4个字节)、long(8个字节)四种。它们能够表示的数据范围如下:
byte | [-128, 127] |
short | [-32768, 32767] |
int | [-2^31, 2^31 - 1] |
long | [-2^63, 2^63 - 1] |
注意:Java中数据类型所占字节数与操作系统位数无关。
数据的溢出:
首先,我们来打印一下int能够表示的最大值和最小值。
public class Test{
public static void main(String[] args){
System.out.println("Integer.MAX_VALUE: " + Integer.MAX_VALUE);
System.out.println("Integer.MIN_VALUE: " + Integer.MIN_VALUE);
}
}
然后,我们对int能够表示的最大值加1看看结果:
public class Test{
public static void main(String[] args){
int maxValue = Integer.MAX_VALUE;
System.out.println(maxValue + 1);
}
}
可以看到一个很大的正数加1后,变成了最小的负数,这就是溢出。溢出就是一个数据进行运行后,结果超出了该类型能够表示的最大范围而导致的错误。
解决方案:使用范围更大的数据类型来表示。
public class Test{
public static void main(String[] args){
long maxValue = Integer.MAX_VALUE;
System.out.println(maxValue + 1);
}
}
一个字面值整型常量默认是int型,例如:100。如果想要是long型的,可以在数字后加L或l(小写L),下面看一个例子:
public class Test{
public static void main(String[] args){
// 这个200是int型,无法直接赋给byte型变量
byte numA = 200;
// 这个200是long型,无法直接赋给byte型变量
byte numB = 200L;
}
}
注意:Java中没有无符号类型的数据。全都是有符号类型的数据。
- 因为无符号数稍微一不注意,就会出现很大的错误,比如说一个小的无符号数减去一个大的无符号数,得到的结果就是一个很大的无符号数。
浮点型变量
Java中浮点类型有两个,float(4个字节)和double(8个字节),两者都遵循IEEE标准,所以这两种类型浮点数的存储方式和C语言中是一样的。
首先,我们来看一个例子:
public class Test{
public static void main(String[] args){
int numA = 10;
int numB = 20;
System.out.println(numA / numB);
}
}
从上述结果可以看出,和C语言一样,整型相除就是结果还是整型,如果想要精确除,需要将两个变量都转为double型。
public class Test{
public static void main(String[] args){
int numA = 10;
int numB = 20;
System.out.println((double)numA / (double)numB);
}
}
下面,再来看一个例子:
public class Test{
public static void main(String[] args){
double num = 1.1;
System.out.println(num * num);
}
}
我们知道小数的数量是无限的,所以使用有限的内存来表示无限多的小数,必然会存在精度上的误差。float的精度误差在1e-6,double的精度误差在1e-15。
另外,浮点数常量默认是double类型,如:3.14,可以使用3.14F(或3.14f)来表示float型浮点数常量,我们来看一个例子:
public class Test{
public static void main(String[] args){
// 3.14是double型,无法直接赋给float型变量
float numA = 3.14;
float numB = 3.14F;
}
}
字符型变量
我们知道C语言中使用ASCII表示字符,但是ASCII表示的范围是有限的,只能表示100多个字符。所以Java中使用Unicode表示字符,因此一个字符占两个字节,表示的字符种类更多,甚至可以表示中文。
下面先来看一个例子:
public class Test{
public static void main(String[] args){
char c = '蒙';
System.out.println(c);
}
}
出现上述错误不要慌,编译的时候指定一下编码格式就可以了。
布尔类型变量
我们知道,C语言中0表示假,非0表示真。但是在Java中没有这样的说法,Java中使用boolean类型变量表示真假,boolean只有两种取值:true表示真,false表示假。
注意:boolean的底层实现是使用一个字节还是一个比特位,取决于不同的JVM实现,不同的JVM实现的方式是不同的。
字符串类型变量
C语言中使用字符数组来表示字符串,Java中使用一个单独的类型String来表示字符串。
前面的数据类型都是基本类型,String不是基本类型,而是引用类型。
Java中的转义字符和C语言中基本相似:
转义字符 | 解释 |
\n | 换行 |
\t | 水平制表符 |
\' | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
下面看一个简单的例子:
public class Test{
public static void main(String[] args){
String msgA = "hello\nworld!";
System.out.println(msgA);
System.out.println();
String msgB = "hello\tworld!";
System.out.println(msgB);
}
}
字符串的+表示字符串的拼接,如果+的过程中遇到其他类型的变量,其他类型的变量会被自动转成字符串。
public class Test{
public static void main(String[] args){
int num = 10;
// 先将num转为字符串拼接,再将1转为字符串进行拼接
System.out.println("num: " + num + 1);
// 将num + 1的和转为字符串进行拼接
System.out.println("num: " + (num + 1));
}
}
变量的作用域
注意:Java中没有全局变量,所有变量的作用域都是当前大括号。
下面来看一个例子:
public class Test{
public static void main(String[] args){
{
// 作用域仅在当前大括号{}
int num = 10;
}
System.out.println(num);
}
}
变量的命名规则
语法要求:
- 一个变量名只能包含数字、字母和下划线。
- 变量名不能以数字开头。
注意:语法上虽然允许使用中文/美元符($)命名变量,但不建议这么做。
建议:
- 类名使用大驼峰命名风格,如:FirstDemo。
- 变量名和方法名使用小驼峰命名风格,如:firstName。
常量
Java中常量分为两种:
- 字面值常量:
10 | int型字面值常量(十进制) |
010 | int型字面值常量(八进制) 由数字 0 开头,010 也就是十进制的 8 |
0x10 | int型字面值常量(十六进制) 由数字 0x 开头,0x10 也就是十进制的 16 |
10L | long型字面值常量,也可以写作 10l (小写的L) |
1.0 | double型字面值常量,也可以写作 1.0d 或者 1.0D |
1.5e2 | double型字面值常量,科学计数法表示。相当于1.5 * 10^2 |
1.0F | float型字面值常量,也可以写作1.0f |
true | boolean型字面值常量,同样的还有false |
'a' | char型字面值常量,单引号中只能有一个字符 |
"abc" | String字面值常量,双引号中可以有很多个字符 |
- final修饰的常量:
先来看一个例子:
public class Test{
public static void main(String[] args){
final int num = 10;
num = 20;
}
}
这里final的作用相当于C++中的const。
类型转换
Java是一种强类型编程语言,当不同类型之间的变量相互赋值的时候,会有严格的校验。
下面看几个例子:
相关类型小范围数据赋给大范围数据:
public class Test{
public static void main(String[] args){
int numA = 10;
// int型变量赋给long型变量
long numB = numA;
// int型变量赋给double型变量
double numC = numA;
}
}
从上述可以看出,相关类型小范围数据赋给大范围数据是没有任何问题的。
相关类型大范围数据赋给小范围数据:
public class Test{
public static void main(String[] args){
// long型变量赋给int型
long numA = 10L;
int numB = numA;
// double型变量赋给float型
double numC = 3.14;
float numD = numC;
}
}
从上述结果可以看到,大范围数据赋给小范围数据是不可行的,如果想要赋值成功,需要进行强制类型转换。
public class Test{
public static void main(String[] args){
// long型变量赋给int型
long numA = 10L;
int numB = (int)numA;
// double型变量赋给float型
double numC = 3.14;
float numD = (float)numC;
}
}
注意:大范围类型数据强制转换为小范围数据,会产生截断,可能会导致数据的丢失。
不相关类型数据之间的相互转换:
public class Test{
public static void main(String[] args){
int numA = 10;
boolean numB = true;
// int型转为boolean型
numA = numB;
// boolean型转为int型
numB = numA;
}
}
从上述运行结果可以看出,不相关类型数据之间不能相互转换,下面我们试一下使用强制类型转换是否可以:
public class Test{
public static void main(String[] args){
int numA = 10;
boolean numB = true;
// int型转为boolean型
numA = (int)numB;
// boolean型转为int型
numB = (boolean)numA;
}
}
上述运行结果可以看出,强制类型转换也不行,Java认为它们是完全不相关的类型。
int型字面值常量赋给byte:
public class Test{
public static void main(String[] args){
// int型字面值常量赋给byte型变量numA,字面值在byte表示范围内
byte numA = 100;
// int型字面值常量赋给byte型变量numB,字面值不再byte表示范围内
byte numB = 200;
}
}
上述结果可以看出,字面值常量赋给的变量能够表示该字面值常量,则会进行隐式类型转换,否则编译不通过,需要强制类型转换。
char和short之间的相互转换:
public class Test{
public static void main(String[] args){
char numA = 'a';
short numB = 165;
// 将short赋给char型变量
numA = numB;
// 将char赋给short型变量
numB = numA;
// 将short赋给char型变量,强转
numA = (char)numB;
// 将char赋给short型变量,强转
numB = (short)numA;
}
}
从上述结果可以看出,直接转是不行的,但是可以强转。
结论:
- 不同数字类型的变量之间赋值,表示范围小的类型能隐式转换成范围较大的类型。
- 如果需要把范围大的类型赋值给范围小的,需要强制类型转换,但是可能会丢失精度。
- 将一个字面值常量进行赋值的时候,Java会自动针对数字范围进行检查。
类型提升
我们来看两个例子:
int和long混合运算:
public class Test{
public static void main(String[] args){
int numA = 10;
long numB = 20L;
int numC = numA + numB;
long numD = numA + numB;
}
}
从上述运行结果可以看出,当long和ing混合运算的时候,int会提升成long,得到的结果仍然是long类型,需要使用long类型的变量来接收结果。如果非要用int来接收结果,就需要使用类型提升。
byte和byte的运算:
public class Test{
public static void main(String[] args){
byte numA = 10;
byte numB = 20;
byte numC = numA + numB;
}
}
从上述结果可以看出,byte和byte都是相同的类型,但是出现编译报错,这是因为,虽然numA和numB是byte类型,但是在进行计算的时候,会被提升为int类型,再进行计算,所以得到的结果也是int型。
因为计算机的CPU通常都是有32根数据线,所以一次读取32位,即4个字节。为了硬件上的方便,向byte和short这些低于4个字节的类型,会先被提升为int型,再进行计算。
Java中的数据类型如下:
注释
Java中的注释分为三种:
- 单行注释://注释内容(用的最多);
- 多行注释:/* 注释内容 */(不推荐,不支持嵌套使用);
- 文档注释:/** 文档注释 */(常用于方法和类之上,描述方法和类的作用),可用来自动生成文档。
Java中有工具可以将文档注释导出为一个单独的文件。