目录
Java基本结构
java的三大特点:
面向对象(OOP:Object Oriented Programming):两个概念、三大特性:类和对象,封装继承多态
健壮性:无指针,垃圾回收
跨平台性:不同操作系统有不同的JVM
jdk包含jre和一些开发工具和一些核心类库,jre包含jvm和一些核心类库的class文件。
命令行编译:
.java文件(源文件)→编译(javac)→.class文件(字节码文件)→运行(java)→结果
每个Java文件只有一个public class ,且名字跟文件名相同,对源文件编译后会生成一个或多个名字是原文件里类名的字节码文件,运行时只能运行包含main方法的类(建议还是放在public类中更方便)。
注释:单行注释,多行注释,文档注释(用javadoc命令可以生成一个说明文档)
工具:记事本,vs code;IDE:eclipse,idea
命名:包名都是小写; 类名,接口名大驼峰; 变量名,方法名小驼峰; 常量名都是大写
变量:
变量可以先声明后初始化,也可以同时声明和初始化,但是必须先声明后使用。
变量只在作用域中起作用,作用域是定义它的大括号{}。
变量名不能相同。
▲定义相同数据类型的变量时可以只写一次数据类型,不同变量用逗号隔开。
int[] x=1,y=2;
变量按数据类型来分:
变量按类中位置来分:
成员变量:直接在类中定义,在方法体,代码块,构造器外部定义的变量,也叫属性;
局部变量:在方法中,方法形参中,代码块中,构造器形参,构造器内部定义的变量。
JVM内存:
数据类型
整型:
byte:-128~127、short、int、long(定义时要加L或l后缀)
▲整型常量默认为int,long型变量不带后缀默认为int型(不加L默认是int,int转为long是安全的,所以会自动转,能编译通过)
▲bit比特是信息量的最小单位,byte字节是计算机存储的基本单位。
在java中,用0b前缀表示整型二进制数,一个二进制数占1/8个字节(00000001),用0x前缀表示整型十六进制数,一个十六进制数占1/2个字节(00001111)。
浮点型:
float: 需要加上f或F后缀、double
▲浮点型常量默认为double,float型变量不带后缀默认为double型(float浮点数不加F默认是double类型,double转float可能损失精度,不会自动转,编译是通不过的)。
字符型:
char:
1、单引号声明一个字符或转义字符或Unicode;
▲注意\u和0x不一样,\u+16进制表示一个字符,0x+16进制表示整型16进制数。
2、直接用十进制int数字表示Unicode编码集上对应的字符。
也可以用Unicode编码集上的字符表示对应的十进制int数字。
但是涉及到变量还是要使用自动类型提升和强转:
布尔型:
true、false
引用类型String:双引号。可能用到转义字符。
▲除了基本数据类型之外其他的都是引用数据类型
基本数据类型之间的赋值运算:只考虑7种基本数据类型,不考虑布尔型,其中char型取的是字符对应数字
1、类型自动转换:
①、容量小的和容量大的进行混合运算(包括算术运算和比较运算和三元运算)时小的自动提升为大的,输出结果为大的。但byte,char,short三种类型互相作运算时只能用int作结果。
byte、char、short→int→long→float→double
②、小类型可以赋值给大类型(等号右边是小类型,左边可以是比它大的类型)。
2、类型强制转换:
① 自动类型转换的逆过程,从大转小。强转符:()。
② 有强转符的从小到大的类型转换。
缺点: 1、可能会损失精度。
2、如果试图将一个数值从一种类型强制转换为另一种类型, 而又超出了目标类型的表示范围, 结果就会截断成一个完全不同的值。 例如,(byte) 300 的实际值为 44。
计算机底层都以原码的补码形式存储整数!
正数:原码、反码、补码都相同;负数:原码-->反码(除了符号位其他位取反)-->补码(反码加1)
引用数据类型String的赋值运算:和其他8种基本数据类型
引用数据类型变量的赋值:
变量之间的赋值赋的只是地址值和变量类型,堆中的内存结构不变。
若要在内存中新建,用new。
运算符6种:
算术运算符:
+,-,*,/,%
▲对于除号“/”,它的整型除和浮点除是有区别的:整型之间做除法时,只保留整数部分而舍弃小数部分。
取余运算结果正负和被余数相同。
自加自减:
前++ ,后++;前--,后--
▲注意++和+=运算符不会改变变量本身的数据类型,原理是如果不一致,先自动类型提升后自动强制转型
▲注意自加自减的原理:下面这个例子由于temp=0把i=1顶掉了,所以最后结果i还是0,不是1。
赋值运算符:
=,+=,-=,*=,/=,%=
▲注意++和+=运算符不会改变变量本身的数据类型,原理是如果不一致,先自动类型提升后自动强制转型:
比较运算符:
==、>=、<=、!=、>、<
▲比较运算符的结果都是布尔型。
▲注意: 基本数据类型的比较只看值的大小,不看是什么类型,因为存在自动类型提升。
逻辑运算符:
▲逻辑运算符参与和结果的都是布尔型。
&逻辑与 、|逻辑或 、!逻辑非、^逻辑异或 :逻辑与或没有短路效应,前后条件都会计算。
&&短路与 、||短路或 :短路与或有“短路效应”,根据第一个条件判断是否计算第二个条件(&&:左边为真,右边参与计算;左边为假,右边不参与计算;||:左边为假,右边参与计算;左边为真,右边不参与计算),有可能计算不到后面想计算的条件。
相同点:逻辑与或和短路与或的结果相同。
▲注意==和=的区别:答案46
三元运算符:
结构:(条件)?表达式1:表达式2
若条件是T,则返回表达式1;若条件是F,则返回表达式2。
表达式1和表达式2必须可以统一成一个类型(包括自动类型提升);
▲可以使用三元运算符必可以使用if-else,反之不一定。
尽量使用三元运算符。
位运算符:
位运算是直接对整型的二进制进行的运算。
二进制原码:正数最高位为0;负数最高位为1。
优先级:
进制转换:
二进制转十进制:......2^3+2^2+2^1+2^0+2^-1+2^-2......
十进制转二进制:整数位除2取余直到商为1倒着排,小数位乘2取整直到积1正着排
二进制到八进制:整数位和小数位分别从右往左三个三个分为一组,小数位不够后补0,整数位不够前补0,分别相加计算,正着排。
八进制到二进制:从左往右将每个数拆成三个三个的二进制数。
二进制到十六进制:整数位和小数位分别从右往左四个四个分为一组,小数位不够后补0,整数位不够前补0,分别相加计算,正着排。
十六进制到二进制:从左往右将每个数拆成四个四个的二进制数。
输入输出和流程控制
输入:导包,建立Scanner对象,读取;
Scanner sc = new ScannerSystem.in;
int i = sc.nextInt();
▲如果需要重复键入的话,new Scanner 只用写一次,sc.nextxxx最好赋给基本数据类型或字符串。
▲读取时next()/nextLine()是输入字符串(区别在于next()只计入输入字符串中第一次出现空格前面的部分,nextLine()是输入的所有字符串包括空格);nextInt()/nextShort()/nextLong()是输入整型;nextDouble()/nextFloat()是输入浮点型;nextBoolean()是输入布尔型;
输出:System.out.print() / println() / printf();
printf使用占位符%:"…%d…,变量" 格式化输出整数;"…%f…,变量" 浮点数(%.2f 保留两位小数);"…%s…,变量" 字符串;"%%" 输出%
IF判断
三种格式:
1、if…… 2、if……else 3、if……else if……else if……else
▲if和else if判断语句中的条件语句可以有交集也可以没有交集,因为else的原因有没有交集不影响结果。
▲if语句可以在执行语句只有一行时省略大括号,但是仅限一行。
▲else有个就近原则,如果没有大括号,else和离它最近的if配对。
SWITCH判断
两种表达:
1、switch(表达式/变量){
case 可能的常量结果之一:
执行语句;
break;
case 可能的常量结果之一,可能的常量结果之二:
执行语句一;
执行语句二;
break;
default :
执行语句;
break;
}
2、switch(表达式/变量){
case 可能的常量结果之一 ->
执行语句;
case 可能的常量结果之一,可能的常量结果之二 ->
{执行语句;
执行语句;}
default ->
执行语句;
}
3、 int n = switch(表达式/变量){
case 可能的常量结果之一 ->1;
case 可能的常量结果之一,可能的常量结果之二 ->
{int i = 5;yield i;}
default -> 5;
}
▲穿透性:根据可能的结果进入相应的case后,如果没有break,会一直往下执行所有case语句,直到遇到break,跳出switch语句。
所以有时候可以不加break实现累加。
▲switch后面的表达式或变量只能是下面六种数据类型之一:byte、short、char、int、枚举类对象、String。
▲case只能是确定的常量,不能是范围。
▲default一定是在case匹配完之后再匹配,与它在不在最后一个无关。
▲yield关键字用于返回值,用在3这种写法中。
▲如果判断的具体数值不多,而且符合byte、short 、char、int、String、枚举等几种类型。虽然两个语句都可以使用,建议使用swtich语句,因为效率稍高。
其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广。
也就是说,使用switch-case的,都可以改写为if-else,反之不成立。
FOR循环
结构:1、初始化条件;2、循环条件(布尔型);3、循环体;4、迭代条件;
for(初始化条件;循环条件;迭代条件1,迭代条件2){
循环体
};
1234234234….
▲当在 for 语句的第 1 部分中声明了一个变量之后,这个变量的作用域就为 for 循环的整个循环体。
WHILE循环
结构:1、初始化条件;2、循环条件(布尔型);3、循环体;4、迭代条件;
初始化条件;
while(循环条件){
循环体;
迭代条件;
}
1234234234…
DO WHILE循环
结构:1、初始化条件;2、循环条件(布尔型);3、循环体;4、迭代条件;
初始化条件;
do{
循环体;
迭代条件;
}while(循环条件);
134234234…
▲while类循环可以和for循环相互转换;
区别在于for中的i和while类中的i作用域不同。
▲当不限制循环次数时可以用for(;;)和while(true)。这时可以用break跳出语句。
for-each循环:
int[] ns = { 1, 4, 9, 16, 25 };
for (int n : ns) {
System.out.println(n);
}
▲这里的n不是索引,而是直接对应数组中的每个元素。
▲只能获取每个元素的值,当需要以其他顺序遍历数组或改变数组中的元素时,还是必须使用下标变量。
嵌套循环
▲内层循环执行完整个语句,外部循环执行一次。
▲外层循环控制第几行,内层循环控制第几列,可以并列多个内层循环表示不同的列。
break和continue关键字
break表示跳出该循环结构;
continue表示跳出本次循环,前往循环体的首部执行下次循环,不跳出循环体;
▲break和continue关键字后面不能有其他语句。
▲break和continue关键字通常和if语句一起使用,不会单独使用。
▲默认跳出离自己最近的一层循环语句;如果需要跳出不是最近的一层循环,需要在该循环语句前面加“label:”,“label1:”,“label2:”……,然后break/continue label,break/continue label1,break/continue label2……
数组的特点
1、数组是有序排列的。
2、数组属于引用类型,但数组元素可以是引用类型也可以是基本类型。
3、创建数组实例对象时会在内存中创建连续空间。
4、数组的长度一旦确定就不能改变。
数组分类:
1、一维数组、二维数组……
2、引用元素数组、基本元素数组
一维数组的使用:
1、一维数组的声明和初始化:
静态初始化(在定义数组的同时就为数组元素分配空间并赋值,基本类型数组和String类型数组常用这种):
int[] sz = new int[]{…,…,…};
int[] sz = {…,…,…};
动态初始化(数组声明且为其分配空间与赋值的操作分开进行,除了String外的引用类型数组最好用这种):
int[] sz = new int[3];
sz[0]=…,sz[1]=…,sz[2]=…,…
▲只声明的意思就是只赋默认值;初始化的意思是先赋默认值,再赋确定值。
▲初始化完成后数组长度即确定。
2、调用指定位置元素:
通过索引,从0开始,sz[0]=…
3、获取数组长度:
.length属性
4、遍历数组:
for (int i=0; i<sz.length; i++) {
System.out.println(sz[i]);
}
5、数组元素的初始化默认值(数组变量跟其他变量不一样,虽然它也是局部变量,但是它有默认值)
整型:0;浮点型:0.0;char型:0(该0表示Unicode码中的0);布尔型:false;
引用数据类型:null;
6、数组元素的内存解析:
内存的简化结构:
一维数组内存解析:
▲直接打印数组变量输出的是变量指向的地址值。
二维数组的使用:
二维数组的元素恰好是数组。
1、二维数组的声明和初始化:
静态初始化:int[][] sz / int[] sz[]= new int[][]{{…,…,…},{},{}}
int[][] sz / int[] sz[]= {{…,…,…},{},{}}
动态初始化:int[][] sz / int[] sz[]= new int[3][2];(表示三个数组中的元素个数都是2,不能单独指定每个数组 的元素个数)
int[][] sz / int[] sz[]= new int[3][]; 注意二维数组初始化的不同
sz[0]=new int[2],sz[1]=new int[5],sz[2]=new int[4];(表示不指定三个数组的元素个数,达到和静态初始化相同效果)
2、调用指定位置元素:
sz[0][1]=…
3、获取二维数组长度:
sz.length和sz[1].length
4、遍历二维数组:
5、二维数组元素的初始化默认值
对动态初始化方式一:int[][] sz / int[] sz[]= new int[3][2];
外层数组元素默认值为:null
外层数组元素初始化值为:地址值
内层数组元素默认值为:同 一维
对动态初始化方式二:int[][] sz / int[] sz[]= new int[3][];
外层数组元素默认值为:null
6、二维数组元素的内存解析:
数组的工具类Arrays()中的静态方法:
//6、String deepToString(多维数组)
//7、copyOf(各种类型的原数组,int复制后新数组的长度):
如果数组元素是数值型,那么多余的元素将被赋值为 0 ; 如果数组元素是布尔型, 则将赋值为 false。相反, 如果长度小于原始数组的长度,则只拷贝最前面的数据元素。
//8、copyOfRange(各种类型的原数组,int要复制的起点,int要复制的终点)
数组常见异常:
1、数组角标越界异常:
2、空指针异常: