Java语言里分号、花括号、方括号、圆括号、空格、圆点都具有特殊的分隔作用,统称为分隔符
标识符就是用于给程序中变量、类、方法命名的符号,必须以字母、下划线、美元符开头,后边可以跟任意数目的字母数字下划线美元符,此处的字母并不局限于英文26个字母,还可以是中文字符、日文字符等等
jshell> String 中国="China"
中国 ==> "China"
jshell> System.out.println(中国)
China
Java的关键字是一些具有特殊用途的单词,有特殊的使用因此不能当成变量名来用
Java是强类型语言,强类型意味着两个方面。1:所有的变量必须先声明后使用;2:指定类型的变量只能接受类型与之匹配的值,这意味着每个变量和每个表达式都有一个在编译时就确定的类型,类型限制了一个变量能被赋的值,限制了一个表达式可以长生的值,限制了在这些值上可以进行的操作,并确定了这些操作的含义。
强类型语言在编译时会进行更严格的语法检查,声明变量的语法非常简单,只需要指定变量的类型和变量名即可,变量还可以使用其他修饰符,但变量至少需要指定变量类型和变量名,其中变量类型可以是Java语言支持的所有类型。
type varName[ = 初始值];
Java语言支持的类型分为两类:基本类型(Primitive Type)和引用类型(Reference Type);
int是最常用的整数类型,因此通常直接给出一个整数值默认就是当作是int类型,除此之外有几种情况:
public class IntegerValTest
{
public static void main(String[] args)
{
// 下面代码是正确的,系统会自动把56当成byte类型处理
byte a = 56;
/*
下面代码是错的,系统不会把9999999999999当成long类型处理,
所以超出int的表数范围,从而引起错误
*/
// long bigValue = 9999999999999;
// 下面代码是正确的,在巨大的整数值后使用L后缀,强制使用long类型
long bigValue2 = 9223372036854775807L;
// 以0开头的整数值是8进制的整数
int octalValue = 013;
System.out.println(octalValue);
// 以0x或0X开头的整数值是16进制的整数
int hexValue1 = 0x13;
int hexValue2 = 0XaF;
System.out.println(hexValue1);
System.out.println(hexValue2);
// 定义二个8位的二进制数,二进制的整数以0b或者0B开头
int binVal1 = 0b11010100;
byte binVal2 = 0B01101001;
// 定义一个32位的二进制数,最高位是符号位,符号位是1的时候表示他是个负数
int binVal3 = 0B10000000000000000000000000000011;
System.out.println(binVal1); // 输出212
System.out.println(binVal2); // 输出105
System.out.println(binVal3); // 输出-2147483645
/*
定义一个8位的二进制,该数值默认占32位,因此它是一个正数。
只是强制类型转换成byte时产生了溢出,最终导致binVal4变成了-23
*/
byte binVal4 = (byte) 0b11101001;
/*
定义一个32位的二进制数,最高位是1。
但由于数值后添加了L后缀,因此该整数的实际占64位,第32位的1不是符号位。
因此binVal5的值等于2的31次方 + 2 + 1
*/
long binVal5 = 0B10000000000000000000000000000011L;
System.out.println(binVal4); // 输出-23
System.out.println(binVal5); // 输出2147483651
}
}
所有数字在计算机底层是以二进制形式存在的,原码是直接将一个数值换算成二进制数,但计算机以补码的形式保存所有整数,补码的计算规则是,正数的补码和原码完全相同,负数的补码是其反码加1,反码就是对原码按位取反,只是最高位(符号位)不变
前边说到整数值默认是int类型,因此使用二进制形式定义整数时,默认占32位,第32位是符号位,如果在二进制整数后添加l或L后缀,这个二进制就占64位,第64位是符号位,因此long binVal5 = 0B10000000000000000000000000000011L;是个正数,然而0b11101001依然是个32位正整数,只是程序进行强制类型转换时发生了溢出,导致它变成了负数
字符型通常用于表示单个字符,字符型值必须用单引号括起来,Java使用16位的Unicode字符集作为编码方式,而Unicode被设计成支持世界上所有书面语言的字符,包括中文字符,因此Java程序支持各种语言的字符。
早期对英文字符、数字、标点符号等字符进行编号(8位,256个字符编号),计算机通过将这些编号转换为二进制进行保存,而ASCII字符集就是这些编号的总和,但是ASCII字符集不包含亚洲国家文字,因此又对世界上所有书面语言的字符进行了统一编号(16位,65536个字符编号),就有了Unicode字符集
字符型值有如下三种表示形式:
因为计算机底层保存字符时,实际是保存该字符对应编码的二进制,因此char类型的值也可直接作为整型值来使用,相当于一个16位的无符号整数,范围是0~65535,因此其变量、值完全可以参与加减乘除等数学运算,也可以比较大小
如果把0~65535范围内的一个int整数赋给char类型变量,系统会自动把这个int整数当成char类型来处理
public class CharTest
{
public static void main(String[] args)
{
// 直接指定单个字符作为字符值
char aChar = 'a';
// 使用转义字符来作为字符值
char enterChar = '\r';
// 使用Unicode编码值来指定字符值
char ch = '\u9999';
// 将输出一个'香'字符
System.out.println(ch);
// 定义一个'疯'字符值
char zhong = '疯';
// 直接将一个char变量当成int类型变量使用
int zhongValue = zhong;
System.out.println(zhongValue);
// 直接把一个0~65535范围内的int整数赋给一个char变量
char c = 97;
System.out.println(c);
}
}
char类型使用单引号括起来,而字符串使用双引号括起来,在Java语言中单引号,双引号和反斜杠都有特殊的用途,如果字符串中包含了这些特殊字符,则必须使用转义字符的表示形式,例如绝对路径“c:\code”则必须携程“c:\code”才会是期望的结果。
Java的浮点类型有两种,float和double,他们有固定的范围和字段长度,并且字段长度和范围与机器无关,是遵循IEEE754标准,采用二进制数据的科学计数法来表示浮点数
Java语言的浮点数有两种表示形式:
Java语言的浮点数默认都是double类型,如果希望Java把一个浮点类型值当成float类型处理,应该在这个浮点类型值后紧跟f或F,当然也可以在一个浮点数后添加d或D后缀,强制指定是double类型
Java还提供了3个特殊的浮点数:正无穷大、负无穷大和非数,用于表示溢出和出错,例如一个正数(浮点型)除以0将得到正无穷大(用Double或Float类的POSITIVE_INFINITY表示),负数(浮点型)除以0则得到负无穷大(用Double或Float类的NEGATIVE_INFINITY表示)0.0(浮点型)除以0.0(浮点型)或对一个负数开方将得到一个非数(用Double或Float类的NaN表示)。
所有正无穷大数值都是相等的,所有负无穷大数值都是相等的,而NaN不与任何数值相等,甚至和NaN都不相等。
public class FloatTest
{
public static void main(String[] args)
{
float af = 5.2345556f;
// 下面将看到af的值已经发生了改变
System.out.println(af);
double a = 0.0;
double c = Double.NEGATIVE_INFINITY;
float d = Float.NEGATIVE_INFINITY;
// 看到float和double的负无穷大是相等的。
System.out.println(c == d);
// 0.0除以0.0将出现非数
System.out.println(a / a);
// 两个非数之间是不相等的
System.out.println(a / a == Float.NaN);
// 所有正无穷大都是相等的
System.out.println(6.0 / 0 == 555.0/0);
// 负数除以0.0得到负无穷大
System.out.println(-8 / a);
// 下面代码将抛出除以0的异常
// System.out.println(0 / 0);
}
}
Java7引入了新特性,数值中使用下划线,无论是整型数值还是浮点型数值,都可以自由的使用下划线,用于清楚的分辨数值位数
public class UnderscoreTest
{
public static void main(String[] args)
{
// 定义一个32位的二进制数,最高位是符号位。
int binVal = 0B1000_0000_0000_0000_0000_0000_0000_0011;
double pi = 3.14_15_92_65_36;
System.out.println(binVal);
System.out.println(pi);
double height = 8_8_4_8.23;
System.out.println(height);
}
}
布尔型只有一个boolean类型,用于表示逻辑上的“真”和“假”,在Java中,boolean类型数值只能是true或false,不能用0或者非0来表示,其他基本数据类型的值也不能转换成boolean类型
public class BooleanTest
{
public static void main(String[] args)
{
boolean b1 = true;
boolean b2 = false;
// 下面代码将出现错误:字符串不能直接变成boolean型的值
// boolean b3 = "true";
// 使用boolean和字符串进行连接运算,boolean会自动转换成字符串
String str = true + "";
// 下面将输出true
System.out.println(str);
}
}
在Java程序中不同的基本类型的值经常需要进行相互转换,类型转换方式有两种,一种是自动类型转换,另一种是强制类型转换
Java所有的数值型变量可以相互转换,如果系统支持把某种基本类型的值直接赋给另一种基本类型的变量,则这种方式称为自动类型转换,只有一个数值范围小的值或变量直接赋给另一个范围大的变量时,系统才支持自动类型转换
public class AutoConversion
{
public static void main(String[] args)
{
int a = 6;
// int可以自动转换为float类型
float f = a;
// 下面将输出6.0
System.out.println(f);
// 定义一个byte类型的整数变量
byte b = 9;
// 下面代码将出错,byte型不能自动类型转换为char型
// char c = b;
// 下面是byte型变量可以自动类型转换为double型
double d = b;
// 下面将输出9.0
System.out.println(d);
}
}
当把任何基本类型的值与字符串进行连接运算时,基本类型的值将自动转换为字符串类型
public class PrimitiveAndString
{
public static void main(String[] args)
{
// 下面代码是错的,因为5是一个整数,不能直接赋给一个字符串
// String str1 = 5;
// 一个基本类型值和字符串进行连接运算时,基本类型值自动转换为字符串
String str2 = 3.5f + "";
// 下面输出3.5
System.out.println(str2);
// 下面语句输出7Hello!
System.out.println(3 + 4 + "Hello!");
// 下面语句输出Hello!34,因为Hello! + 3会把3当成字符串处理,
// 而后再把4当成字符串处理
System.out.println("Hello!" + 3 + 4);
}
}
自动类型转换的图中,如果将箭头发过来,则必须进行强制类型转换(targetType)value,将范围大的往范围小的转换将会导致溢出,从而造成数据丢失,这种转换被称为“缩小转换(Narrow Conversion)”
public class NarrowConversion
{
public static void main(String[] args)
{
var iValue = 233;
// 强制把一个int类型的值转换为byte类型的值
byte bValue = (byte) iValue;
// 将输出-23
System.out.println(bValue);
var dValue = 3.98;
// 强制把一个double类型的值转换为int
int tol = (int) dValue;
// 将输出3
System.out.println(tol);
}
}
public class RandomStr
{
public static void main(String[] args)
{
// 定义一个空字符串
var result = "";
// 进行6次循环
for (var i = 0; i < 6; i++)
{
// 生成一个97~122的int型的整数
var intVal = (int) (Math.random() * 26 + 97);
// 将intValue强制转换为char后连接到result后面
result = result + (char) intVal;
}
// 输出随机字符串
System.out.println(result);
}
}
当一个算数表达式中包含多个基本类型的值时,整个算数表达式的数据类型将发生自动提升:
public class AutoPromote
{
public static void main(String[] args)
{
// 定义一个short类型变量
short sValue = 5;
// 下面代码将出错:表达式中的sValue将自动提升到int类型,
// 则右边的表达式类型为int,将一个int类型赋给short类型的变量将发生错误。
// sValue = sValue - 2;
byte b = 40;
var c = 'a';
var i = 23;
var d = .314;
// 右边表达式中在最高等级操作数为d(double型)
// 则右边表达式的类型为double型,故赋给一个double型变量
double result = b + c + i * d;
// 将输出144.222
System.out.println(result);
var val = 3;
// 右边表达式中2个操作数都是int,故右边表达式的类型为int
// 因此,虽然23/3不能除尽,依然得到一个int整数
int intResult = 23 / val;
System.out.println(intResult); // 将输出7
// 输出字符串Hello!a7
System.out.println("Hello!" + 'a' + 7);
// 输出字符串104Hello!
System.out.println('a' + 7 + "Hello!");
}
}
并不是所有的数据类型都可以指定直接量,能指定直接量的通常只有3种类型:基本类型、字符串类型和null类型,具体可以给直接量的数据类型有:int、long、float、double、boolean、char、String和null
字符串直接量有一点需要指出,当程序第一次使用某个字符串直接量时,Java会使用常量池(constant pool)来缓存该字符串直接量,如果程序后面的部分需要用到该字符串直接量时,Java会直接使用常量池中的字符串直接量。
常量池,指的是在编译期间被确定,并保存在已编译的.class文件中的一些数据,它包括关于类、方法、接口中的常量,也包括字符串直接量
int a = 5;
char c = 'a';
boolean b = true;
float f = 5.12f;
double d = 4.12;
String author = "davieyang";
String book = "自动化测试";
String s1 = "hello";
String s2 = "hello";
String s3 = "he" + "llo";
System.out.println(s1 == s2);
System.out.printlb(s1 == s2);