文章前言:
本文是笔者在学习的时候边学边敲,可能有疏忽,我们一起进步
##1.关键字(在Java中严肃区分大小写,在任何场景下)
被赋予了专门的含义与用途
保留关键字是指目前官方先行占用这个作为关键字,但是含义还没有赋予
##2. 标识符
Java中方法,变量,类等要素命名的时候是使用的字符序列称为标识符
即:凡是可以自己起名字的地方都叫标识符
标识符的命名规则
·
最好定义标识符的时候能够见名知意
还有规范(非强制):
##三.变量
变量的概念:
内存中的一个存储区域该区域的数据可以在同一类型范围内不断变化
变量构成的三个要素:
数据类型 变量名 储存的值
Java中变量声明的格式:
数据类型 变量名 = 变量值
Java是强类型的语言**会专门建立文档
在Java中数据类型分为八种
基本数据类型(8种)
整型:byte\short\int\long
浮点型:float\double
字符型:char
布尔型:boolean
引用数据类型:
类(class)
数组(array)
接口(interface)
枚举(enum)
注解(annotation)
记录(record)
*定义变量的时候要遵循标识符命名的规则和规范
作用域
变量前后最近的大括号是他的作用域
超出作用域无法调用,即超出作用域会失效
在一个作用域内无法声明两个同名变量
定义好变量之后就可以通过变量名进行调用来进行运算等
对应于变量的定义,可以分开声明与定义,也可以把声明与定义直接一行写出来
在同一个作用域内,不能对于一个声明过的变量进行再次声明,但是可以强制转换类型,可以进行再次赋值,会进行覆盖
在变量三要素中,值最重要,三要素:
类型 变量名 值
基本数据类型介绍
###1.整数类型
byte short int long
四种整数数据类型字节长度不一样,依次递增
*定义long变量,赋值时通常需要以l或者L作为后缀
java程序中变量通常声明为int类型,除非不足以表示较大的数,才使用long
Java中整数型常默认为int类型
字节Byte:
是计算机用于计量存储容量的单位,一个字节等于8bit
位bit:
是数据存储的最小单位,二进制数系统中,,每个0/1就是一个位,叫做bit,其中8bit就称为一个字节Byte
转换关系
8bit=1Byte
1024Byte = 1kb
1024kb = 1MB
1024MB =1GB
1024GB = 1TB
###2.浮点类型
*与整数类型类似,Java浮点类型也有固定的表数范围和字段长度
不受具体操作系统影响
float:
单精度,尾数可以精确到七位有效数字,很多情况下,精度很难满足需求
double:
双精度,精度是float的两倍
通常采用此类型
Java的浮点型常量默认是double型
声明float变量的时候,后面要加上f
float f1 = 12.3f
System.out.println(“f1=” + f1)
//这两句是声明变量并赋值进行打印的标准操作
其中第一行不过多赘述
第二行打印时,“f1=”这部分是字符串,而后面的+f1是表示进行拼接,加号表示前后拼接
拼接操作
拼接操作的全过程
JVM看到字符串和变量之间用加号,决定执行拼接操作
把非字符串类型转换成字符串
在上面Java底层会悄悄调用
String.valueOf(f1) // 把 float 12.3 转成字符串 “12.3”
对于基本类型(int、float、double、boolean 等),拼接时都会自动调用对应的 String.valueOf(参数) 方法转成字符串。
接着就是拼接并且输出
底层原理:为什么拼接不会弄乱原来的字符串?
你可能会好奇:“f1=” 本身没变,怎么就多出了 “f1=12.3”?
这是因为 Java 的 String 是不可变的(Immutable)。
● “f1=” 这个字符串对象一旦创建,内容永远不会改变。
● 拼接时,Java 会创建一个新的字符串对象来存放拼接后的结果,原来的 “f1=” 和 “12.3” 都还在内存里(或者说被回收,但没被修改)。
关于浮点数精度的说明
***float表数范围大于long,但是精度不高
并不是所有小数都能可以精确的用二进制浮点数表示,二进制浮点数不能精确的表示0.1,0.01,0.001这样的10的负次幂
浮点类型float,double数据不适合在不容许四舍五入等误差的金融计算领域,如果需要精确数字计算或保留指定位数的精度,需要使用BigDecimal类替换浮点型变量
字符串类型
char型数据用来表示通常意义上的“字符”占两个字节,与short占用空间大小一样
Java中所有字符都是用Unicode编码,故一个字符可以储存一个字母,一个汉字,或者其他书面语的一个字符
字符串变量的三种表现形式
形式一
使用单引号‘ ’括起来的单个字符,有且只能有一个
例如
char c1 = ‘a’
char c2 = ‘中’
形式二
直接使用Unicode值来表示字符型常量:
‘\uxxxx’,其中xxxx表示一个十六进制整数
在Unicode编码集当中,基本有世界上全部字符都能识别
例如
\u0023表示’#’
形式三
Java中还允许使用转义字符’'来将其后的字符转变为特殊字符型常量
例如
char c3 = ‘\n’; //‘\n’表示换行符
形式四:
使用具体字符对应的数值,比如(ASCII码)
char c11 = 97 //在ASCII码中 97代表的是a,因此这里实际存储的是a
System.out.println(c11);
布尔类型
boolean类型用来判断逻辑条件,一般用于流程控制语句当中
*if条件控制语句
*while循环控制语句
*
基本数据类型变量间的运算规则
整型常量规定是int类型,比如直接输入的1
byte b5 =10
//这里想要对10+1运算,下面得到的结果必须是声明为int类型
int m1 =b5 +1
这里的一就是整型常量
相同的,浮点数常量规定为double
关于变量名为什么不能是数字开头的
int 123l =12
long 16 =123l
两者相互冲突,不知道究竟第二行的123l是变量还是值,即为了自洽
1.这里提到的数据类型有七种,不包含布尔类型
2.运算规则包括:
①自动类型提升
当容量小的变量与容量大的变量运算时,结果自动转换为容量大的数据类型
说明:此时的容量大或者小,并不是指占用内存空间的大小
而是指表示数据范围的大小
比如
int l1= 10
long s1 = l1
long c1 = l1 + s1
byte·short·char类型之间运算过后会自动转换为int
其余的提升规则是
int→long→float→double
例子
long l1 = 123l//正常声明long数据
long l2 = 123 //这里也能正常
原因就是自动类型提升,会先处理成int进一步转换为long,但是如果本身数值超出int,在这里就无法转换
比如
long c12 = 123456789 //这里就不行
这就会把数据类型变为c1,如果在这里所声明的类型数据不正确,也会报错
②强制类型转换
在上面的数据转换顺序中,如果从后往前赋值转换,会有损失精度得到报错
如
double b =12
int c = b
这里就会报错
强制类型转换就是,在符合标准的前提下,运用转换语法,就能达到转换的目的
把上面的一行改为,但是会有相应的精度损失,损失规则为截断,而不是四舍五入
int c = (int)b
就是把要更改的变量用小括号在它前面标注想要改成的类型
这里,()就是强制转换符
在自动类型提升中 小类型转换为大类型,也可以在后面标注应转换为大的数据类型,不过一般省略
精度损失的其他例子
int i =128
byte k = (byte)i
这里转换之后,结果是负128,详细原理见另一个笔记(ai)
例子
short k =5
k =k-2
这段代码讲解
其中,5是int常量,但是其二进制表示在short可以表示的范围之内
因此,第一行没问题
第二行的操作其实是分步骤进行的,第一步执行k-2,这里k是short类型,而5整型常量表示的是int类型,因此运算结果会被自动升级为int类型,问题是,k常量前面已经声明过了,是short类型,而第二步会把运算后的结果自动赋值给前面的变量,这时候就会有冲突,因此,这样子写无法通过编译
更改方法
s -= 2; 或者 s = (short)(s - 2)
其中第一种能够通过是因为,系统在用符合运算符的时候(+= -= *=等)会自动强制转换
char c = ‘a’;
int i = 5;
float d = .314F;
double result = c + i + d; // 判断:yes(正确)
这段代码,char类型参与计算的时候会先转换为int类型,也就是其对应的ASCII编码,这里a对应的就是97
float行,赋值变量要在末尾加上f
结果应该是102.314
基本数据类型与String类型的运算
1…String类,属于引用数据类型
2.String类型的变量,可以使用一对"“得方式进行赋值
3.String类型的字符串内部,可以包含任意数量的字符,也可以是零个
4.String类型与基本数据类型之间的运算
这里可以与八种类型,包含布尔
String类型只能与其他类型做连接运算使用+号表示,这个加号必须紧跟着String类型数据的后面,不然如果用String类型数据接收的时候,可能被识别成不被允许的加法运算
运算结果只能用String类型声明
如何实现将一个string类型的数字转变为int数字呢?
比如
int b =10
String c = b +”"
//“10”
int f = Integer.parseInt(str9)
这样就可以将数字从引号当中剥离出来结果就是int类型的
运算符
运算符是一种特殊的符号,用来表示数据的运算,赋值与比较等
按照功能有以下分类
按照操作个数分为:
一元运算符(单目运算符)
二元运算符(双目运算符)
三元运算符(三目运算符)
算术运算符的基本语法
/表示取商,而%表示的是取余
%在开发中一般用来判断是否能整除,也就是看结果与0的关系
除数与被除数也称为,模数与被模数
需要注意的是
取模之后,结果与被模数的符号相同
int c = -12
int d = 2
int f = c%d
结果是-5
重点
(前)++与(后)++(前后–的用法一样)
++的位置不同会导致结果有些不同
++都表示自增1运算
而++i与i++有区别
定义int a =10
若int b =++a
则运算过程如下,先自增1运算,然后再将值赋值给b
而
若int b = a++
则表示先赋值给b,再把a进行自增运算
在一般的运用场景中,一般两者没有区别
便捷使用:
当你声明一种不是int类型的数字的时候,如果想要它加一,1是常量,在不强制转换的情况下,会造成精度损失,也就是报错
但是当我们使用自增益就可以
赋值运算符=
1.当两侧数据类型不一致的时候,可以使用自动类型转换或者使用强制类型转换原则进行处理,注意,是使用,而不是自动的特性
2.支持连续赋值
int a = b=10;
或者合并
int a,b=10;
以=为根本,有如下拓展
+=,-=,/=,=
用法与python类似,但在处理不同的数据类型时,拓展的赋值运算符不会改变数据本身的数据类型
也就是说,对于不同类型的数据处理后,结果等同于强制转换,可能会有精度损失
特别需要注意的练习题
int m =2;
int n =3;
n=m++
因为是后加加,所以m是在最后才进行迭代加一
等同于
n = nm++;
这样子,先进行nm,并赋值,最后才是m迭代
比较运算符
其中大部分等同于python中的,不多赘述
说明:
1.最后一种在面向对象的多态性的位置会进行讲解
2.上面几种比较运算符适用于基本数据类型(有的适用细节不同)
理解即可,不需要死记硬背
3.补充,== !=可以适用于引用数据类型(了解即可,这是合乎逻辑的,因为其他的比较运算符也无法比较引用数据类型)
逻辑运算符
逻辑运算符,操作的都是boolean类型的变量或者常量,而且运算结果也是boolean类型的值
运算符说明
&与&&:
表示‘且’的关系当左右两边布尔类型的值都是true的时候,结果才能是true,否则为false
需要注意,如果两个结果都是false,结果仍然是false,不可把其简单地看为是一种只要类型一样就返回true
|与||(或的关系,前者是):
表示‘或’关系,当符号两边布尔值有一边为true的时候,结果为true,如果没有,那就是false
!(非):
表示‘非’的关系,当变量布尔值为true的时候,结果为false,变量值为false时,结果为true
^(异或):
当符号两边布尔值不同的时候,结果为true,两边的布尔值相同的时候,结果为false
理解“异或”,追求的是“异”,只要不一样,结果就是true
对于逻辑运算符的补充说明
逻辑运算符,操作的都是boolean类型的变量或者常量,而且运算结果也是boolean类型的值,这说明逻辑运算符常用于条件判断结构与循环结构中
对于初学者看到这些运算符可能不是很能理解,或者很懵,现做出如下补充:
运算符 名称 作用
&& 短路与 两边都为 true,结果才为 true
|| 短路或 只要一边为 true,结果就为 true
! 逻辑非 取反,true 变 false,false 变 true
1.短路与
规则,只有左右两边的条件同时成立,才为true,有一个不成立就是false
int age = 25;
boolean result = (age > 18) && (age < 30);
// 左边 true,右边 true → 结果 true
int score = 85;
boolean pass = (score >= 90) && (score <= 100);
// 左边 false,右边不执行了 → 结果 false
关键点:
如果左边已经是false,那么右侧根本不会执行,因为这是“短路”
相电流里面的开关断开,电流过不去一样
2.短路或
||
规则:左右至少有一个成立,也就是有true,那么结果就是true,如果两个都不成立
那么结果就是false,因为短路,就是左侧识别到true,结果就会是true,后面就不管了
3.逻辑非!
规则,单目运算符,只对一个条件取反
最容易混淆的点
运算符 是否短路 举例说明
&& ✅ 短路 左边 false,右边不执行
& ❌ 不短路 左边 false,右边仍然执行
|| ✅ 短路 左边 true,右边不执行
| ❌ 不短路 左边 true,右边仍然执行
在日常开发中,基本都是使用短路版本,因为安全性和效率都高于非短路版本
注意的坑:
优先级问题
逻辑非!优先级最高
接着是短路与&&
最后是短路或||
boolean r = true || false && false; // 等价于 true || (false && false) → true
一般这种建议多用括号
记忆:
建议把短路与记忆为一条电路上的两个开关,只有都闭合,才有电流(结果是true)
第一个结果只要不是true,第二道门就没有必要开了
而短路或就是,两条能到家的并且距离一样的路,只要有一个走的通就行,但是当第一条路能走得通,就不看第二条路了,也就是结果为true
这样会导致第二个语句可能不执行,会更安全,并且也要注重结果与非短路逻辑的区别
位运算符
这些符号区分是位运算符还是逻辑运算符只需要看操作的对象是不是布尔类型数据就行
1.第一个框中的运算符,都是对于数字的二进制进行操作的,因此与二进制的特性有关,所以每左右移,就相当于对于数字进行二的几次幂的操作
2.<<左移,相当于在原有的二进制表示上在末尾添加零,类比十进制,十进制每加一个零,那么就会扩大十倍,二进制每增加一个零,就是会扩大2倍
3.在处理一个数据的时候,如果对一个数据左移的位数过多的时候,可能数据结果会发生偏差
4.>>右移,就是和左移相反,相当于每次右移就除以二,取得是商,因为对于负数来讲,操作的是补码,所以不能补0,而是补一
5.无符号右移,只要一移动,取得就是正,也就是只要一操作就会变成正数
那无符号右移的操作情景是?
比如处理一个int数据,他有三十二位,用无符号右移与按位与结合就可以比较它的前后16位是否相同
与运算&
操作两个数字,比如9&7
就是对其二进制进行操作
逐位判断,对于负数就是操作其补码
剩余的几个运算符也是类似的对于二进制操作的逻辑
如果不理解也没问题,课上说这节目前还不重要,等用到的时候细讲
条件运算符
*基本语法
(条件表达式)? 表达式1 :表达式二
说明:条件表达式是boolean类型的结果,根据boolean的值选择表达式1或者表达式2
如果条件表达式是true,那么运算后的结果是表达式1
反之,如果条件表达式的结果是false,那么结果就是表达式二
这样的结果可以用对应的变量类型进行接收
注意的是,表达式一和表达式二需要是可以兼容的类型或者是相同的类型
当三个数字比大小的这种用两次条件运算符就可以做到的,可以合并到一行,不过较为难读懂,因此一般用分开写
结论:
凡是可以使用条件运算符的地方,都可以改写为if slse结构,但是反过来就不一定
建议,在二者都能够使用的前提下,优先使用条件运算符,因为执行效率高
优先级顺序表(第一个是小括号,截图长度原因)
开发建议,不要过度依赖运算的优先级来控制表达式的执行顺序,这样可读性太差
不要把一个表达式写的过于复杂,如果一个表达式写的过于复杂,就最好把它分成几步来写
章末小结
1.关键字,保留字
关键字:倍Java赋予特殊含义的字符串
*true false null虽然不是关键字,但是可以当做关键字来看待(虽然他们可以复制给变量)
2.标识符
*凡是自己可以命名的,都称为标识符
必须遵守标识符的命名规则,否则编译不通过
(
2.1
26字母,0-9,_或$可以参与构成标识符
2.2
数字不可以开头,这样强制规定可以让系统的判断效率提升,遇到数字开头,一定是数字字面量,遇到其他的开头,一定是标识符,这种设计让编译器的词法分析器能够单遍扫描,无需回溯,高效且没有歧义
不可以使用关键字与保留字,但是能包含关键字与保留字
Java中严格区分大小写,长度没有限制
标识符不能包含空格
)
*标识符命名的规范
包名:所有单词组成都小写
类名接口名:所有单词首字母大写,多单词拼接也是
变量名方法名多单词组成时第一个单词首字母小写,第二个单词开始每个单词的首字母大写
常量名:所有字母都大写,不同单词之间用下划线连接
“见名知义”
3.变量的基本使用(重点)
(
对于变量的理解:内存中的一个存储区域,该区域的数据可以在同一类型范围内不断地变化
变量的构成包含三个要素,数据类型,变量名,储存的值
Java中声明变量的格式:
数据类型 变量名 = 变量值
)
变量具有作用域,只在作用域中有效
不能在同一作用域中声明两个同名变量
4.基本数据类型变量的使用(重点)
通常在开发中,没有特殊情况,那么就定义整型变量为int,浮点型变量为double
对于char类型的补充
是Java中唯一一个无符号的基本数据类型,不能储存负数
可以凭借对应的ASCII码直接参与运算
char只能存储一个字符,并且存储的字符对应的字符集是unicode字符集,非常庞大,基本可以包含全球的字符,而ASCII是unicode的一部分
5.自动类型提升
6.String类的使用,与基本数据类型变量的运算(重要)
String的认识:“字符串”,用“”表示
包含任意个字符,可以为空
它与其他类型的运算只有连接运算,并且+是连接还是加法,取决于左边紧跟着的类型是否是字符串,+具有向左识别,左边类型决定它这里的作用
7.对于进制的认识
熟悉各种进制在Java中的声明方式
八进制0开头
二进制0b、0B
十六进制0x开头
对于二进制的理解
正数三码合一
负数原码,反码,补码都不相同
计算机底层以补码的方式存储数据
8.各种运算符的讲解(比较常用的重点)
一般地,交换两个变量的值,都是通过引用第三个临时变量来做到交换效果,比如
int n =2;
int m =1;
int c = m;
m = n;
n = c;
这样就完成了最基本的交换两个整型变量的值,以后这样的方法也会在数组里面运用,不推荐使用其他的方法,比如
如果想体现运算符的优先级,一般推荐使用()来进行区分,因为根据系统本身的运算符优先级来进行区分,这样可读性比较差,我们在编写一行执行语句的时候,不要出现太多的运算符
企业真题
1.高效的方式计算2*8的值
使用左移<<
2.&与&&的区别:
略,注意短路是否
3.Java中基本的数据类型都有哪些
String是基本的数据类型吗
8中基本数据类型
String不是,属于引用数据类型
基本数据类型
类型 占用字节 默认值 取值范围
byte 1 0 -128 ~ 127
short 2 0 -32,768 ~ 32,767
int 4 0 -2³¹ ~ 2³¹-1
long 8 0L -2⁶³ ~ 2⁶³-1
float 4 0.0f 约 ±3.4E-38 ~ ±3.4E+38
double 8 0.0d 约 ±1.7E-308 ~ ±1.7E+308
char 2 ‘\u0000’ 0 ~ 65,535(Unicode字符)
boolean 未严格定义(JVM依赖) false true / false
基本类型存储在栈内存中,直接保存值,效率高。
所有非基本数据类型都是引用数据类型,他们存储的是对象的地址(引用)实际数据在堆内存中
引用数据类型分为
类class
接口Interface
数组Array
枚举Enum
注解Annotation
引用数据类型的默认值是null(除了数组对象本身)
总结:String 是引用类型中的类,而 Java 全部数据类型就是8种基本类型 + 无数种引用类型(因为你可以自己定义类和接口)等到后面学到引用数据类型的时候再回来看
栈内存与堆内存拓展:
这个放在学完基础,Java进阶的笔记中讲解
4.Java开发中计算金额时使用什么数据类型?
不能使用float或者double,因为精度没有BigDecimal类替换,可以实现任意精度的数据运算】
5.char型变量中还能不能储存一个中文汉字,为什么?
可以,因为char使用的是Unicode字符集,虽然ASCII码里面没有汉字,但是汉字表示使用Unicode的其他部分
6.int i =0
i = i++
这时i的值为?
0,后加加先赋值再进行自增一
7.如何将两个变量的值互换
同上面的交换两个整型变量,只需要定义为String就行
8.boolean占几个字节
编译的时候不谈占几个字节,但是jvm在给boolean类型变量分配内存空间的时候,它占一个槽位(slot 4个字节)
拓展:
byte\short\char\boolean\int\float类型的变量占用一个槽位slot
double、long占用两个槽位slot
- 日常所说的字节数(语言规范/教材)
这是 Java 语言层面规定的逻辑大小,通常来源于 C/C++ 的习惯或 Java 语言规范的推荐实现:
类型 日常认为的字节数
byte 1 字节
short 2 字节
char 2 字节
int 4 字节
long 8 字节
float 4 字节
double 8 字节
boolean 1 字节(规范未强制,但普遍如此理解) - 图中描述的 JVM 局部变量表 Slot 大小
这是 JVM 运行时栈帧局部变量表的物理分配规则:
类型 局部变量表中的实际占用
byte 4 字节(1 Slot)
short 4 字节(1 Slot)
char 4 字节(1 Slot)
int 4 字节(1 Slot)
long 8 字节(2 Slots)
float 4 字节(1 Slot)
double 8 字节(2 Slots)
boolean 4 字节(1 Slot)
原因:
● 日常字节数是逻辑上的“最小存储单元”,便于理解和计算内存(例如数组连续存储时的偏移量)。
● JVM 局部变量表为了简化字节码指令集(复用 int 的加载/存储指令)以及 CPU 内存对齐(32 位架构一次读取 4 字节更高效),将小于 32 位的类型统一提升为 32 位存储。
9.为什么Java中0.1+0.2不是0.3?
结果是0.3000……4,这是所有编程语言面临的通病,原因是他们都采用了IEEE 754标准
具体的
并不是每一个小数都能够有对应的二进制小数表示