今天,我们学习Java的一些基础知识,循序渐进,让我们慢慢的发现Java的魅力!
目录
一、Java须知的命名规则和规范
1.1 标识符
1.2 命名规范
二、关键字和保留字
三、八大基本数据类型
3.1、byte
3.2、short
3.3、int
3.4、long
3.5、float/double
3.6、boolean
3.7、char
标识符,通俗意义上讲,就是我们程序员自己定义的名称,例如类名,方法名,变量名等等。也可以这样理解,只要需要我们自己起名字的,就是标识符。
当然,名字也不能随便取,Java定义了合法标识符的规则:
1)由26个英文字母大小写,0-9,_或者$组成
2)数字不可以开头
3)不可以使用关键字和保留字,但是可以包含关键字和保留字
4)Java中严格区分大小写,长度没有限制
5)标识符不能包含空格
我们除了要遵守标识符的规则,还要知道Java中命名的规范,规范的意义就是你不按照这个方式来命名,程序也不会报错,可是会显得很不正规,标准。命名规范就是我们程序员都会默认遵守的一些Java命名“规则”,是一种共识。
1)包名
在多个单词组合时,所有字母全部都小写。
例如:testhelloworld
2)类名、接口名
在多个单词组合时,所有字母的首字母大写。
例如:TestHelloWorld (又名:大驼峰命名法)
3)变量名、方法名
在多个单词组合时,第一个单词全小写,从第二个单词开始,后续单词全部首字母大写。
例如:testHelloWorld (又名:小驼峰命名法)
4)常量名
在多个单词组合时,所以字母都大写,每个单词之间使用 _(下划线)来进行连接。
例如:TEST_HELLO_WORLD
注意:起名字时,我们为了提高阅读性,尽量起的名字做到“见名知意”。
通过上面的学习,我们知道标识符是不能直接使用关键字和保留字来进行命名的,可是关键字和保留字都有哪些呢?让我们继续往下看。
关键字:就是在Java中具有特殊意义的字符,有表示数据类型、权限修饰等等
保留字:可以理解为目前还没有被使用,但是随着版本的更新,有可能会被使用的预备关键字
以上就是目前Java中的所有关键字和保留字了,总共53个。其中goto、const为保留字,其余都是关键字。在之后的学习中,就让我们来一个一个的攻克这些关键字吧!
从上图可以看出,基本的数据类型分成了三大类:数值型、字符型、布尔型。数值型又细分成了两类:整数型和浮点型。
在这里我们引入一个概念:bit(binary digit)。bit是表示数据的最小单位。只有两种表现形式:0,1,可也理解为每一个二进制数字就是1bit。
一个字节(byte)为8个比特,一个英文字母通常占用一个字节,一个汉字通常占用两个字节。普通计算机系统能读取和定位到最小信息单位是字节(byte)。
1 Byte(B)= 8 bit
1 Kilo Byte(KB)= 1024 B
1 Mega Byte(MB)= 1024 KB
1 Giga Byte(GB)= 1024 MB
1 Trillion Byte(TB)=1024 GB
关于基本数据类型,这里先放个表格,以供参考,下面为大家一一解释。
byte 数据类型是8位、有符号的,以二进制补码表示的整数。byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一。我们可以先看一段代码:
public class ByteTest { static byte b; //声明byte类型的变量b public static void main(String[] args) { System.out.println("byte的大小:" + Byte.SIZE); System.out.println("byte的的默认值:" + b); System.out.println("byte的取值范围:[" + Byte.MIN_VALUE + "," + Byte.MAX_VALUE + "]"); } }
运行结果如下:
根据运行结果,我们可以得到三个结论:
1)1 byte 在Java中的大小为 8 bit;
2) byte 在Java中的默认值为 0;
3)byte在Java中 最大值为127,最小值为-128;
//定义byte数据类型 byte x = 100; byte y = -50;
那我们再深入思考一下,为什么byte的取值范围会是[-128,127],而不是[-128,128]呢?
首先,我们先了解一个运算规则:
正数的最高位都是0,正数的值就是二进制表示的值。
负数的最高位都是1,负数的值是取反后加1然后加个负号得到的值
我们简单的举个栗子理解一下:
比如:0000 0001,这个二进制数字,最高位是0为正数,表示的是十进制中的1.
再比如1000 0001,最高位是1为负数,取反后得到0111 1110,再加上1得到0111 1111,换算成10进制值前面再加上负号,就得到了-127.
回到byte,我们已经知道了byte是8位的二进制数,可以推断出byte的最大正整数就是0111 1111,也就是127.那么byte的最小负整数呢?
根据计算规则,我们可以推断出最小的负整数是1000 0000,进行取反就是0111 1111,再加1可以得出1000 0000,然后换算成十进制后加上负号,可以得出是-128
我们现在已经知道了byte的最大正整数是127,那么如果我们将127再加1,结果会怎么样呢?
public class ByteTest { public static void main(String[] args) { byte b = 127; b += 1; System.out.println("b = " + b); } }
让我们看一下运行结果:
我们发现,当byte b = 127 + 1;时,结果居然是-128,这是为什么?
这里我们需要先了解一些概念。对于一个数,计算机要使用一定的编码方式进行存储,而这个存储具体数字的编码方式有三种:原码、反码、补码。
原码:原码就是二进制数的符号位加上真值的绝对值,二进制数的第一位表示符号,其余位表示值。
如:[+1]原 = 0000 0001; [-1]原 = 1000 0001;
反码:反码分为两种:正数的反码还是它本身,而负数的反码是在其基础上,符号位不变,其余位置全部取反。
如: [+1]原 = 0000 0001 ;[+1]反 = 0000 0001;
[-1]原 = 1000 0001 ;[-1]反 = 1111 1110;
补码:补码分为两种:正数的补码还是它本身。负数的补码是在其反码的基础上,再加1。
如:[+1]原 = 0000 0001 ;[+1]反 = 0000 0001 ;[+1]补 = 0000 0001;
[-1]原 = 1000 0001 ;[-1]反 = 1111 1110 ;[-1]补 = 1111 1111;
注意:想要求一个补码的原码,就是对这个补码再次补码。
为什么要使用反码和补码呢?
因为让计算机去辨别符号位,其电路设计将会变得非常复杂,为了简化运算,人们想到了一种让符号位也参与运算的运算方式,我们都知道,减去一个数等于加上这个数的负数, 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了。
例如:
1 + (-1) = [0000 0001] 原+ [1000 0001]原 = [1000 0010]原 = -2
这样结果是错误的,所以引入了反码的概念,加入反码后我们再看:
1 + (-1) = [0000 0001] 原+ [1000 0001]原 = [0000 0001] 反+ [1111 1110]反 = [1111 11111] 反 = [1000 0000]原 = -0.
这里我们可以看到,运算结果是对了,可是多了+0,-0两个数字,是没有意义的。于是,又引入了补码的概念。
1 + (-1) = [0000 0001] 原+ [1000 0001]原 = [0000 0001] 反+ [1111 1110]反 = [0000 0001]补 +[1111 1111]补 = [0000 0000]补 = 0;
这样,之前的问题就都不存在了。
int类型的128原码为0000 0000 0000 0000 0000 0000 1000 0000,在 byte += 1;的时候,发生了强制类型转换,因为byte只有8为二进制数,所以这里就截取了128原码的后8位,即1000 0000,转换成10进制后就得到了-128.
为了加深映像,我们可以再看一段代码:
public class ByteTest { public static void main(String[] args) { byte b = -128; b += -1; System.out.println("b = " + b); } }
运行结果如下:
经过上面的学习,相信这里我们已经不难理解了。
int类型的-129原码为1000 0000 0000 0000 0000 0000 1000 0001;
补码为1111 1111 1111 1111 1111 1111 0111 1111;
强制转换为byte类型,只取后8位为:0111 1111;转换为10进制就为127了。
大家可以去做更多的尝试,这里就不再演示了。
short 数据类型是 16 位、有符号的以二进制补码表示的整数.short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一。
还是先看一下代码:
public class ShortTest { static short s; public static void main(String[] args) { System.out.println("short的大小:" + Short.SIZE); System.out.println("short的的默认值:" + s); System.out.println("short的取值范围:[" + Short.MIN_VALUE + "," + Short.MAX_VALUE + "]"); } }
运行结果如下:
根据运行结果,我们可以得到三个结论:
1)1 short 在Java中的大小为 16 bit;
2) short 在Java中的默认值为 0;
3)short 在Java中 最大值为32767,最小值为-32768;
//定义short数据类型 short s = 1000; short r = -20000;
int 数据类型是32位、有符号的以二进制补码表示的整数。一般地整型变量默认为 int 类型。看以下代码:
public class IntTest { static int i; public static void main(String[] args) { System.out.println("int的大小:" + Integer.SIZE); System.out.println("int的的默认值:" + i); System.out.println("int的取值范围:[" + Integer.MIN_VALUE + "," + Integer.MAX_VALUE + "]"); } }
运行结果如下:
根据运行结果,我们可以得到三个结论:
1)1 int 在Java中的大小为 32 bit,占用4个字节;
2) int 在Java中的默认值为 0;
3)int 在Java中 最大值为2147483647,最小值为-2147483648;
//定义int数据类型 int a = 100000; int b = -200000;
首先我们先来明确一下Java虚拟机在对int型数据进行处理时默认的两条规则:
1. 当程序出现“整型常量”的时候,默认都是以int型存储的
2.如果算术表达式中出现的所有的数字都是int型的,默认运算结果也是int类型
注意:
需要注意一点:在程序编辑过程中,编译器只对直接出现的int常量进行超范围检查,
但是对于在编译中算数运算、表达式产生的int型值则不会进行范围检查;
为了方便我们理解,简单举个栗子:
当我们将long类型数据赋值为9999999999时,并没有超出long类型数据的取值范围,但是编译器还是会报错。
这是因为当程序中出现“整型常量”的时候,默认都是以int类型存储的。而”9999999999“ 就是直接出现的”整型常量“,所以编译器会把他当作int型看待。即使它被赋值给了long类型。
我们知道,编译器会对”直接出现“的int常量进行数据超范围的检查,所以这里编译器将直接出现的整形常量“9999999999”看待int类型,并且进行数据超范围的检查,而经过检查这个数字已经超过了int类型所表示的范围,所以就会报错。
这种情况的解决方法也很简单,只需在赋值的“整数常量”后面加上“L”即可
这是编译器能帮助我们识别的情况,我们还需要注意一些编译器无法帮我们识别的时候:
/** * 计算一天时间有多少微秒 * (1小时=60分钟) * (1分钟=60秒) * (1秒=1,000毫秒) * (1毫秒=1,000微秒) */ public class MicrosecondTest { public static void main(String[] args) { //计算出一天的微秒数,考虑到结果超出了int类型的取值范围,使用long类型接收 long microsecond = 24 * 60 * 60 * 1000 * 1000; //正确结果:86,4000,000,000 System.out.println("microsecond = " + microsecond); } }
运行结果如下:
在上面的算式中,所有计算的整数常量都是int类型,所以每一步的运算结果都会被保存在一个int型的临时变量中,由因为计算出来的整数结果不是“直接出现的整数常量”,所以并不会对其进行范围检查。
随着计算的进行,结果超过了int的取值范围,但是在没有进行范围检查的情况下,编译器还是将结果保留在了int类型的临时变量中,造成了一种“溢出”现像,和之前byte类型中说的情况一样,int类型取值时会将超出取值范围的高位部分舍弃,保留取值范围内的数字,最后得到了一个错误的结果。
想要解决这种情况,只需在计算结果超出int取值范围之前,将其转换成long类型即可。
/** * 计算一天时间有多少微秒 * (1小时=60分钟) * (1分钟=60秒) * (1秒=1,000毫秒) * (1毫秒=1,000微秒) */ public class MicrosecondTest { public static void main(String[] args) { //计算出一天的微秒数,考虑到结果超出了int类型的取值范围,使用long类型接收 long microsecond = 24L * 60 * 60 * 1000 * 1000; //正确结果:86,4000,000,000 System.out.println("microsecond = " + microsecond); } }
运行结果如下:
除此之外,还有一种情况:
public class IntTest { public static void main(String[] args) { //定义一个int类型中的最大值 int a = 2147483647; try { //进行循环,根据代码,好像这个代码只能循环10次 for (int i = a - 9; i <= a; i++) { //将i的值打印出来 System.out.println(i); Thread.sleep(1000);//每循环一次等1秒钟 } } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果如下:
从这个结果中,我们可以看出,看上去只能执行10次循环,可当 i 的值等于int类型的最大数时,再进行 i++运算,其结果就会变成 i = -2147483648。最终,形成一次死循环。
long 数据类型是 64 位、有符号的以二进制补码表示的整数。这种类型主要使用在需要比较大整数的系统上。看以下代码:
public class LongTest { static long l; public static void main(String[] args) { System.out.println("long的大小:" + Long.SIZE); System.out.println("long的:默认值" + l); System.out.println("long的取值范围:[" + Long.MIN_VALUE + "," + Long.MAX_VALUE + "]"); } }
运行结果如下:
根据运行结果,我们可以得到三个结论:
1)long 在Java中的大小为 64 bit,占用8个字节;
2) long 在Java中的默认值为 0;
3)long 在Java中 最大值为9223372036854775807,最小值为-9223372036854775808;
//定义long数据类型 long a = 100000L; long b = -200000L;
这里我们需要注意:
当我们对long类型数据赋值时,被赋值的数值不超过int类型的取值范围时,是可以不用在数值后面添加L的,如:long num = 100; //num long类型,100 int类型 long num2 = 100L; //num2 long类型,100L long类型这两种定义方式都是可以的,因为在Java中,long > int > short > byte, 而小的数据类型转换成大的数据类型,是会自动转换的,不过为了更好地区分int类型和long类型,我们最好在给long类型的赋值的时候,后面都加上一个L。
注意:
"L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。
float和double,都是浮点型数据类型。
float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;float 在储存大型浮点数组的时候可节省内存空间;
double 数据类型是双精度、64 位、符合 IEEE 754 标准的浮点数;浮点数的默认类型为 double 类型;
/** * float和double的测试类 */ public class FloatAndDoubleTest { static float f; static double d; public static void main(String[] args) { //float System.out.println("float的大小:" + Float.SIZE); System.out.println("float的默认值:" + f); System.out.println("float的取值范围:[" + Float.MIN_VALUE + "," + Float.MAX_VALUE + "]"); System.out.println("====================================================="); //double System.out.println("double的大小:" + Double.SIZE); System.out.println("double的默认值:" + d); System.out.println("double的取值范围:[" + Double.MIN_VALUE + "," + Double.MAX_VALUE + "]"); } }
运行结果如下:
单精度的小数位在计算机中只有23位(二进制),换算到十进制只能百分百保证6位十进制数字的精确度。不能百分百保证7位的精度运算。同理,双精度,小数位是52位(二进制),换算为十进制则只能百分百能保证15位。
注意:声明并初始化float是,格式为:float f = 1.0f; 而使用double时,可以有两种写法:(1)double d1 = 10.2d; (2)double d2 = 10.2; 因为浮点数在默认情况下,都是double类型。
boolean数据类型表示一位的信息,只有两个取值:true 和 false,这种类型只作为一种标志来记录 true/false 情况,true表示条件成立,false表示添加不成立。
默认的值为false,其在储存时大小只有1位,由于计算机在处理数据时最小单位为1个字节,所以有些人也会说它是8位。
boolean类型适用于逻辑运算,表示某个条件是否成立。一般用于程序的流程控制。
public class BooleanTest { public static void main(String[] args) { int age = 18; boolean result = age > 20; System.out.println("当age > 20时,result = " + result); result = age < 20; System.out.println("当age < 20时,result = " + result); } }
运行结果如下:
char是字符类型,占2个字节,用单引号' '标识,只能放单个字符。可以直接赋值一个字符:字母、汉子、数字,也可以赋值一个数字范围:0~65565。
根据设计,一个字符集中,每个字符都对应一个数值。比如ASCII 码表中,‘a’对应这数值是97。
/** * char的定义 */ public class CharTest { public static void main(String[] args) { char a = 'a'; //任意单个字符,加单引号 System.out.println("a = " + a); char a2 = '中'; //任意单个中文字,加单引号。 System.out.println("a2 = " + a2); char a3 = 111; //整数。0~65535.输出字符编码表中对应的字符 System.out.println("a3 = " + a3); char a4 = 'a' + 1; //自动转换为int类型,输出对应编码表中的字符 System.out.println("a4 = " + a4); char a5 = 'a' + 'b'; //自动转换为int类型,输出结果 System.out.println("a5 = " + a5); char a6 = '中' + 1; //自动转换为int类型,输出对应的字符 System.out.println("a6 = " + a6); } }
运行结果如下:
根据运行结果,我们可以总结一下:
1)char类型用单引号' '标识,只能放单个字符。
2)char类型为数值时,表示的是这个数值在字符集中对应的字符。
3)两个char字符的加减操作,运算的是其字符集对应的数值进行加减。结果为计算后的数值所对应的字符集
注意:
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中可以存储汉字。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。
转义字符 :\
转义字符出现在特殊字符之前会将特殊字符转换成普通字符。
常见的转义字符有:
我们通过一段代码来演示一下:
/** * 转义字符测试 */ public class ESCTest { public static void main(String[] args) { char c1 = '\n'; // '\n'换行符 System.out.println("Hello," + c1 +"World!"); System.out.println("=================="); c1 = '\t'; // '\t'缩进符 System.out.println("Hello," + c1 +"World!"); System.out.println("=================="); c1 = '\''; // '\''单引号 System.out.println(c1 + "Hello,World!" + c1); System.out.println("=================="); c1 = '\"'; // '\"'双引号 System.out.println(c1 + "Hello,World!" + c1); System.out.println("=================="); c1 = '\\'; // '\\'反斜杠 System.out.println(c1 + "Hello,World!" + c1); System.out.println("=================="); } }
运行结果如下:
以上就是今天学习的全部内容了,有些可能需要学习到后面才能理解,大家可以先了解了解,加深下印象。