Java基础知识
温故而知新,可以为师矣。这篇博客就是补缺之前学习所遗漏的知识,顺便复习一下之前的所学。
注释
Java当中的注释分为两种。 一种格式是: /**/ ,其作用域在其中间,需要写的代码注释编写在其中间,一般使用在需要多行注释的时候。
以种格式是: // ,双斜杠的组合,作用域在从双斜杠开始的一整行,在双斜杠的右边编写注释,一般使用在只需要单行注释的时候。
第一种
/*
代码注释
*/
第二种
// 代码注释
一、基本数据类型
Java中有8种基本数据类型,用来存储数值、字符和布尔值。
而对于基本数据来说,需要重点注意浮点类型的存储与计算。
浮点类型
浮点类型简称浮点型,用于存储含有小数的数值,Java中浮点类型分为两种,单精度(float)与双精度(double),两种浮点类型拥有不同的取值范围。
因为浮点类型需要表示带小数点的数据,所以它的取值计算,不像整数类型那般简单粗暴,浮点数类型采用IEEE规定。百度百科链接:baike.baidu.com/item/浮点数标准/22719915
float的32位由最高位的符号位、中间的8位阶码、与最后的23位尾数构成。
取值范围
符号位表示数值的正负,阶码表示数据的取值范围,尾数表示数据的精度
由于是有符号数,所以8位的阶码可表示 -128~+128的范围,所以取值范围在2^-128 – 2^127之间,大概是 -3.4E38 ~ +3.4E38。
float类型内存图
float能表示的精度由尾数决定,所以23bit大概能表示十进制的7到8位。
所以float能精准表示小数点的后7位。
double类型内存图
double类型取值范围与float类型的计算方式相同。
二、变量与常量
1.关键字
关键字又称保留字,是Java语言中已经被赋予特定意义的一些单词,不可以把这些单词作为变量名等标识符来使用。
注意:Java中的关键字都是小写的字母。
该图片来自百度百科,侵删。
2.标识符
标识符可以简简单单地理解为一个名字,是用来标识类名、变量名、方法名等有效字符序列。Java规定标识符由连续的任意顺序的字母、下划线、美元符号和数字组成,且标识符的第一位不能是数字,也不能是Java中的关键字。
例如:合法标识符
//例如
name;
age;
_user;
$password;
非法标识符
4word;
456;
User name;
3.变量与常量
变量
变量的声明与定义其实在之前的基本数据类型中已经讲过了,这里就不重复叙述了,说点重要的。
变量的声明
变量的申明需要指定数据类型,是因为只有指定的数据类型,编译器才知道需要分配一个多大的内存空间,为了方便使用这块空间,需要取一个变量名,而对变量的操作就是对这块内存空间进行操作。
常量
在程序运行的过程中不会改变的数据称为常量。常量使用 fianl 关键字进行修饰
常量的定义:fianl 数据类型 变量名 = 数据值;常量在定义的时候必须赋初值。
常量的常量名一般使用大写字母
注意!常量在定义并赋初值后,在程序运行后不能改变常量的数据值。
4.变量的有效范围
变量一般分为局部变量与成员变量。
成员变量: 定义在类体中的变量称为成员变量,成员变量的用于范围是整个类中都可以使用。
例如:
public class Main {
static int age=10; //成员变量
static final int number=120; //成员变量
public static void main(String[] args) {
}
}
不过被static关键字修饰的成员变量又被称为静态变量,静态变量可以通过类名.变量的方式在其他的类中使用。
局部变量: 定义在方法内的变量称为局部变量,且作用范围只在本类中或者 { } 大括号内,当前代码块中有效。
注意!!!如果成员变量与局部变量重名的话,使用时会自动遵循就近原则进行调用。
例如
public class Main {
static int age=10; //成员变量
static final int number=120; //成员变量
public static void main(String[] args) {
int number=99;
//遵循就近原则,输出为值为 99
System.out.println(number);
//静态变量使用类名.变量名的方式调用,输出值为120
System.out.println(Main.number);
}
}
三、运算符
运算符是一些特殊符号,主要用于数据值的操作等,一些常用的运算符有,赋值运算符、算术运算符、比较运算符等
1、赋值运算符
赋值运算符就是 = 符号,与数学的 = 符号作用相同,就是将右边的数据值赋值为右边的变量,赋值运算符左边必须是一个变量。
int a=10; //将10赋值给a这个变量代表的内存空间内。
注意:赋值运算符是从最右边的数据开始处理。
2、算数运算符
算术运算符与数学中的加减乘除作用相同。在此就不多重复叙述了。
此图片来自菜鸟教程,https://www.runoob.com/java/java-operators.html ,侵权自删。
在执行自增或自减运算时,以++运算符为例。如果运算符在变量前面,那么此时变量是先进行自增,后参与其他运算。运算符在变量后面,那么会先使得变量值参与运行,后使得变量自增
int num1=10;
//此时运算符在变量前面,先使得num1进行自增
//然后将num1赋值给num2,那么num2的值是11
int num2=++num1;
int number1=10;
//此时运算符在变量后面
//那么会先将number1的值赋值给number2,然后再使得number1进行自增
int number2=number1++; //次数number1的值是11,但number2的值是10
需要注意的是,在进行除法运算时,0不能做除数。例如语句 “int a=5/0;”,在执行这条语句时,编译器会抛出一个异常。
3、比较运算符
比较运算符作用与数学中的作用相同,这里就不多复述了
该表格来自菜鸟教程,侵删
https://www.runoob.com/java/java-operators.html
4、逻辑运算符
逻辑运算符只有三种,逻辑与(&&)、逻辑或(||)、逻辑非(!)。逻辑运算符的操作元必须是结果为Boolean型的变量或表达式。
例图:
注意:当逻辑与或者逻辑或这两种逻辑运算符,多个联合使用的时候,会出现一种被称为 “短路” 的现象,在逻辑表达式中可通过左端的表达式可推断出整个表达式的逻辑值,减少判断所用的时间。逻辑非并不具有此功能
如图:
逻辑或(||) 也是如此,从左往右执行,当有一个表达式的结果为true时,那么整个表达式的结果只会是true,所以后面的表达式也不会去执行。
5、位运算符
数据在计算机内的存储方式是二进位存储的,二进制在计算机内表示方式是一些按一定的排列规定进行排列在一起的数字0和数字1,例如:十进制10在计算机内表示是:0000 1010 (仅展示低八位),而位运算符就是可以对数据的每一位二进制数进行一定操作的运算符。
Java中的位运算符有7种,分别是按位与(&)、按位或(|)、按位取反(~)、按位异或(^)、按位左移( << )、按位右移( >> )和无符号右移(>>>)。
如图:此图来自菜鸟教程,侵删。https://www.runoob.com/java/java-operators.html
按位与
按位或的运算规则是:对于数据的每一个二进制位,有1为1,全0为0。而对于按位取反运算符的话,则是将每一个二进制位取反。
按位取反
需要注意的是,位运算符只能由整形数据进行使用,浮点类型是无法使用位运算符的。
6、移位运算符
除了上述的位运算符之外,Java还提供了对数据按二进制数进行操作的移位操作符。移位操作符有以下三种
左移: ( << )
右移: ( >> )
无符号右移: ( >>> )
左移运算:将数据整体左移n位,空缺位补0
右移的操作也是如此,只不过在进行右移操作时,如果被操作数时正数,那么右移空出来的二进制位就补0,如果被操作数是负数,那么空位处就补1。
而无符号右移,它在运算时,不论被操作数是正数还是负数,空位处都是填入0。
7、三元运算符
前面我们介绍的运算符都是二元操作符与一元操作符,但Java还提供了一个三元操作符供我们使用。
三元运算符使用格式
条件式 ?值1 : 值2
三元运算符的运算规则为,若条件式为true,则整个表达式的结果取值1,否则就取值2。
boolean val= 12 > 45 ? true : false; //此时val的值就是false
三元运算符能够直接代替简单的if判断语句,有时候在代码中合理使用三元运算符,能够简化代码。
8、运算符优先级
运算符的优先级决定了表达式中运算执行的先后顺序,在同一语句中优先级高的运算符会比优先级低的运算符更先执行。如果两个运算符优先级相同,那么左边的运算符要比右边的运算符先被处理。
运算符优先级图
注意,在编写程序时尽量使用圆括号来指定运算次序,以免产生错误的运算顺序。
四、数据类型转换
在编写程序的过程用,我们可能需要使用到不同数据类型的变量,以应对不同的需求,而有时候我们会对不同的数据类型进行运算、赋值的时候,我们就需要进行类型转换了。
1、隐式转换
将低精度的数据赋值给高精度的数据时,系统会自动进行类型转换。这些类型按精度从低到高排列的顺序是:byte<short<int<long<float<double。
例如
int x=50;
float y=x; //此时系统会自动进行隐式转换
2、强制类型转换
把高精度的数据赋给低精度的数据时,必须要进行强制类型转换。如果将高精度的变量赋值给低精度的变量时,超过了低精度变量所能表示的最大范围,那么将会进行溢出,并从低精度变量的另一个极端开始溢出,超过多少,溢出多少。
强制类型转换格式:(类型名)要转换的值
例如
int a=128; //定义一个占四个字节的整形变量,并赋值为128
byte b=(byte)a; //将整形变量赋值给占一个字节的byte类型的变量,并进行强制类型转换
System.out.println(b); //此时输出的却是 -128
上面的代码虽然已经进行了强制类型转换,但是因为byte类型的变量占1个字节,能表示的范围是 -128~+127,此时的+128已经超过了byte类型能表示的数据范围,那么将会出现数据溢出,并且从另一个极端溢出,超过最大表示数多少,就溢出多少。
如图
既然+128溢出后是-128,那么+128的两倍就应该是0了吧?见以下代码。
int a=128*2;
byte b=(byte)a;
System.out.println(b); //此时输出的是 0 ,可以证明上图
注意,除了Boolean类型不能进行强制类型转换外,其他的基本数据类型都可以进行强制类型转换。
五、条件语句
条件语句是根据不同的条件而执行不同的语句,从而产生不同的结果
1.if条件语句
语法如下
if(布尔表达式){
语句序列
}
布尔表达式:可以单纯的一个布尔变量,也可以是复杂的表达式,但最后返回的结果必须是一个布尔值。
例如
int phoneNumber=123456789; //定义一个变量,保存电话号码
if(phoneNumber != 849565423){ //如果此号码不等于849565423
System.out.println("对不起,您拨打的号码不存在!"); //输出
}
流程图
通过上述代码与流程图说明,能够清楚理解if语句的作用。
if else 语句
if(布尔表达式){
语句序列1
}else {
语句序列2
}
如果布尔表达式为真,则执行序列1的内容,否则就执行语句序列2的内容。
int password=987654321; //定义一个变量,保存密码值
if(123456 == password){ //如果密码是123456
System.out.println("密码正确,欢迎登录"); //密码正确
}else { //否则
System.out.println("密码错误,拒绝登录");
}
流程图
if elseif else语句
int count=9; //定义一个变量,表示就餐人数
//输出
System.out.println("欢迎光临,请问有多少人用餐?");
System.out.println("回答"+count+"人");
//低就餐人数进行判断
if(count <= 4){
System.out.println("客人请到大厅4人桌用餐");
}else if(count > 4 && count <= 8){
System.out.println("客人请到大厅8人桌用餐");
}else if(count > 8 && count <= 16){
System.out.println("客人请到楼上包厢用餐");
}else{
System.out.println("抱歉,我们店中暂时没有这么大的包厢!");
}
//end
流程图
2.switch语句
switch是一种多分枝语句,在一定程度上能起到简化代码的作用。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);//打开扫描器
System.out.println("请输入成绩:");//输出字符串
int g= sc.nextInt();//获取控制台输入的数字
switch(g) {//使用switch判断数字,如果输入的值满足对应的case则输出对应的语句
case 10:
case 9: {
System.out.println("成绩为优");
break;
}
case 8: {
System.out.println("成绩为良");
break;
}
case 7:
case 6: {
System.out.println("成绩为中");
break;
}
case 5:
case 4:
case 3:
case 2:
case 1:
case 0: {
System.out.println("成绩为差");
break;
}
default : {
System.out.println("成绩无效");//如果不符合以上任何一个结果,输出 成绩无效
}
}
sc.close();//关闭扫描器
}
}
流程图
六、循环语句
当需要某一个特定的代码在程序中重复执行时,在之前我们可以复制那段需要重复的代码,然后需要执行多少次,我们就复制多少次,虽然效果能达到,但大大提高了程序的简洁度。现在,Java提供了几种循环语句,来使得重新操作变为简单.
1.while循环
语法格式
while(条件表达式)
{
语句序列
}
与if语句内的条件表达式一样,在while语句中的条件表达式也只能返回一个布尔值的结果。
流程图说明
2.do…while循环
此条循环语句的作用其实与while语句的作用类似,不过do…while循环不同于while循环的一点在于,dowhile循环是先执行循环体的内容,最后在进行条件表达式判断,这是与while循环不同之处。
语法格式
do{
语句序列
}while(条件表达式);
流程图说明
3.for循环
for是将 表达式初始化、条件判断、表达式计算,这三种操作集成为一体的一种循环语句。一定程度上简化了代码的变量个数。
语法格式
for(表达式初始化; 条件判断; 表达式计算){
语句序列;
}
流程图说明
七、循环控制语句
在执行了循环操作后,有时根据不同的需求,在符合特定的条件时,需要对循环进行不同的操作。Java提供了两种控制循环的关键字:break、continue。
1.break语句
break语句只能在循环中或者switch语句中使用,它的作用是跳出离它最近的一个循环或switch,或者跳出指定循环。
例题说明:输出1-20之间第一个出现的偶数
public class Main {
public static void main(String[] args) {
//使用for循环获得 1 - 20 之间的每一个数字
for (int i = 1; i < 20; i++) {
//判断是否为偶数
if(i%2 == 0){
System.out.println(i); //输出
break; //直接退出循环
}
}
System.out.println("--- end ---");
}
运行结果
流程图说明
2.continue语句
continue语句是对针对break语句的补充,break语句是立即结束最近的一个循环体,而continue语句是结束本次循环。
例题讲解:输出1-20的奇数
public class Main {
public static void main(String[] args) {
//循环获取 1- 20 之间的每一个数值
for (int i = 0; i < 20; i++) {
//判断是否为偶数
if(i%2 == 0){
continue; //结束本次循环,回到循环体处
}
System.out.print(i+" "); //输出数字
}
}
}
运行结果
流程图说明
八、方法
Java方法是为实现某一功能语句的集合,方法对标于C语言的话就是函数,方法的定义与C语言的基本相同。合理的使用方法能够有效的减少代码的冗余度,能够提高代码的复用性。
定义方法格式
修饰符 返回值类型 方法名(形参){
方法体
return 返回值;
}
图示
注意,若返回值类型是 void 空的话,那么在方法内部无需编写return返回语句
方法的重载
当我们编写一个方法max来比较两个int类型数据的大小关系,那么假如我们需要比较double类型数据时,那么我们需要再编一个方法吗?那方法名怎么取呢?
不需要的,此时我们可以编写一个同为max的方法,但是该方法的参数列表必须与上一个max的方法不同。此时在使用max函数时,如果传入double类型的值,那么虚拟机会自动根据参数的类型调用相同的方法。这就是方法的重载。
方法的重载与方法名有关,与方法的参数列表有关。参数列表主要与形参的类型、顺序、个数有关。
数组就是具有相同数据类型的一组数据的集合。
九、一维数组
一维数组实际上是一组相同类型数据的线性集合
1、创建
在Java中数组作为对象允许使用new关键字进行内存分配。
在创建一维数组时,需要先声明再进行内存的分配。
在Java中,数组的声明有两种方式:
1、数组元素类型 数组名[]; 例如;int array1[];
2、数组元素类型[] 数组名; 例如;int[] array2;
第一种方式是兼容了在C语言中数组的声明,在Java中通常使用第二种方式进行数组的声明。
在进行数组的声明后,需要为数组分配内存空间才能对数组进行操作。
例如:
数组名 = new 数组元素的类型[数组元素的个数];
例:
char[] array;
array=new char[10]; //为char类型数组分配了10个char类型大小的内存空间
图示
在Java中对数组的使用是通过下标来进行的,通过对有效下标来进对数据的操作。
int[] arr=new int[10];
arr[0]; //访问第一个元素
arr[1]; //访问第二个元素
···
arr[9]; //访问最后一个元素
需要注意的是,在Java中数组的有效下标是从0开始的,也就是说,一个数组拥有n个数据的内存空间,但是这个数组的有效下标是在 [0,n-1] 这个闭区间内的,超过这个区间的下标值是无效的,且会造成越界访问引发异常
2、数组的使用
在了解了数组的声明与创建后,那如何使用一维数组内,且看下文。
例:使用一维数组输出1~12月每个月的天数
package yahu;
public class wuhu {
public static void main(String[] args) {
//创建并初始化一维数组,如此进行数组的初始化后,系统会自动的计算数组的长度
int d[]=new int [] {
31,28,31,30,31,30,31,31,30,31,30,31
};
//利用循环输出信息
for(int i=0;i<12;i++) {
//输出每月天数
System.out.println((i+1)+"月有"+d[i]+"天"); //使用下标访问数组中的元素
}
}
}
运行结果
上述代码的有效下标在 [0,11] 之间,对该数组访问第12个下标的数据,那么程序将会报错。
数组下标越界访问
但是如果每次循环都需要从数组0下标访问到数组n-1个下标的话,那么难道我们每次都需要手动计算数组的长度,然后再写一个数字上去吗?不是的,这个不仅不利于程序的可读性,也不利于程序的维护与复用。在Java中创建并声明数组后,系统会自动的计算好该数组的长度,且将这个计算好的数组长度赋值给一个int类型的常量length,且这个length是一个属性值,在数组创建后与数组”绑定在一起了“,通过 数组名.length 调用。
例如:
int[] arr=new int[10];
arr.length; //此时length的值为10
可以将上述程序改进一下,结果是一样的
package yahu;
public class wuhu {
public static void main(String[] args) {
//创建并初始化一维数组,如此进行数组的初始化后,系统会自动的计算数组的长度
int d[]=new int [] {
31,28,31,30,31,30,31,31,30,31,30,31
};
//利用循环输出信息
for(int i=0;i<d.length;i++) {
//输出每月天数
System.out.println((i+1)+"月有"+d[i]+"天"); //使用下标访问数组中的元素
}
}
}
十、二维数组
定义,如果一维数组中的各个元素仍是一个数组,那么它就是二维数组
图示
1、创建
二维数组的常见语法是与一维数组的创建时一样的,只不过多了一个行列的概念
二维数组数据类型 数组名=new 二维数组数据类型(且与前面的一致)[行数][列数];
例如:int[][] arr=new int[3][4]; //声明了一个3行4列,数据类型为int类型的二维数组
二维数组的初始化
数组名= new 数组元素的类型[ ] [ ]{{值1,值2,…},{值1,值2,…},{值1,值2,…}};
二维数组的赋值
数组名[行号] [列号]=值;
2、二维数组的使用
在二维数组中,对数组的每个元素继续访问的方法也是通过效果,对于下标的范围是与一维数组一样的,上文有说过,这里就不再复述了。
例:
package wuhu;
public class yahu{
public static void main(String[] args) {
int a[][]=new int[3][4];//定义一个3行4列的二维数组
//遍历数组
for(int i=0;i<a.length;i++) {
//.length是数组长度
for(int j=0;j<a[i].length;j++) {
System.out.print(a[i][j]);//输出
}
//换行
System.out.println();
}
}
}
运行结果
数组的操作
1.sort(object)
数组元素排序方法
Arrays.sort(数组名);
2.冒泡排序
冒泡算法由双层循环实现,其中外层循环用于控制排序轮数
例如:
package yahu;
public class wuhu {
public static void main(String[] args) {
// TODO Auto-generated method stub
int []arr= {63,4,24,1,3,15};//定义数组
h soter=new h();//创建冒泡排序的对象
soter.sort(arr);//调用排序方法
}
public void sort(int[]arr) {//创建一个
for (int i=1;i<arr.length ;i++) {//比较两个数,大的往后
for (int j=0;j<arr.length-i;j++) {
if(arr[j]>arr[j+1]) {//交换数
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
showArray(arr);//输出
}
public void showArray(int[]arr) {
for(int i:arr) {
System.out.print(">"+i);
}System.out.println();
}
}
运行结果
结尾
上文就是对第一章节的复习了,主要是重温了一遍第一章节的内容,如有错误,望指出。