Java中的注释、标识符和关键字
Java中的注释
a.单行注释 使用“//”注释掉当前行代码
b.多行注释 使用“/* */”注释掉当中的代码
c.文档注释 使用“/** */”生成文档注释
Java标识符的命名规范
标识符是在java中需要我们进行自我命名的变量,常量、类名等等
标识符可以由大小写字母、数字、下划线和美元符号,但是不能以数字开头、不能有空格、不能包含java中的保留关键字,java区分大小写,长度没有限制,但是要求必须要有意义,建议采用英文单词拼接的形式,采用驼峰法进行命名。大驼峰法主要用于对类名的命名,小驼峰法主要用于对变量以及方法进行命名。
Java中的关键字
PS:1、在Java中goto 和const没有任何意义。
2、assert是在JDK 1.4之后增加进来的。
3、enum是在JDK 1.5之后增加进来的。
Java中的基本数据类型
八种基本数据类型,以及所对应的包装类、内存的空间、数值的有效范围
Java要能够处理现实的实物,java需要将这些数据转换成变量来进行处理,java中数据类型主要分为两大类:基本数据类型、引用数据类型。
基本数据类型包含:byte、short、int、long、float、double、char、boolean
Java中的基本数据类型的取值范围如下:
基本数据类型的使用
基本数据类型的使用主要掌握其表示的值的范围即可,或者把握其占有的空间就可以了,如果是正数那么默认是int类型,如果是小数那么默认是double类型
基本数据类型的转换
在java中基本数据类型的转换有两种形式:显示的转换、隐式的转换。
从小范围向大范围转换、从低精度向高精度转换可以自动的隐式完成,如果是从大范围向小范围、从高精度向低精度转换,那么必须强制的显示转换。
例如:
从以上的代码执行结果看出,将一个long型数值转换成int类型的值应该是没有问题,但是要注意一下的情况:
以上的long型变量的值已经超出了int所能表示的范围,这样强转出来的数据时没有意义的,这也是常见数据溢出问题。当然这种情况在double向float转换时也会发生。
数据溢出问题
数据溢出是在进行数值运算时经常会哦遇到的问题,那么接下来通过以下的代码来进行说明
从运算的结果来看,运算的是结果肯定是不对,主要的问题就出在运算出的数已经超出了int的便是范围。运算的结果的数据类型是由参与运算的变量中范围较大的和精度较高的变量的类型来决定。要解决数据溢出的问题最简单的范式就是让较大的数据类型的变量参与运算就可以了。
运算符和表达式
赋值运算:=
三目运算:布尔表达式 ? 条件满足 : 条不满足
数学运算符:+、-、*、/、%
关系运算符:>、>=、<、<=、==、! =
位运算:>>、<<、>>>、^、~
逻辑运算:&&、&、||、|、!
简便运算符:++、--
算术运算符
Java中的算术运算符包括四则运算符和取余运算,+、-、*、/、%
以上的运算非常简单,但是需要注意在进行处罚操作时,需要保证除数不能为0 ,如果除数为0将发生异常Exception in thread “main” java.lang.ArithmeticException: / by zero。
取余的运算虽然简单,但是有些时候可以解决一些意象不到的问题,使得算法速录变得更加的简单。
关系运算符
关系运算符在java中使用非常的普遍,主要是进行变量的比较用的>、>=、<、<=、==、!=,其中需要注意的有”==”和”!=”,首先”==”需要与赋值符号做一个区分,”!=”又是会出现意想不到的错误。
关系运算最终返回的都是boolean类型的结果,用来表示真还是假。
位运算符
位运算是一种相对麻烦的运算,但是其中也有一些规律可以使用,这里还是以理解位运算的推导过程来进行讲解。位运算包含以下几种:&,|、^、~、>>、<<、>>>
&表示的是一个并且,参与运算的所有条件都为真的情况下,结果为真。|表示的就是活着关系,参与运算的所有条件都为假,结果为假。表示的是将参与运算的数全部转换成字节码形式,同为上都为1,&的结果为1,如果有一个为0 ,结果为0。
异或表示的是相同为0,不同为1:
~表示的是按位取反:
除此之外还有唯一运算符,主要是针对于01代码进行的位移操作,如果是向左位移,右边空出来的位用0补充:
如果右移操作以后,左边会空出的位数补符号位,正数补0,负数补1:
负数的无符号右移:
逻辑运算符
在java中逻辑运算符逻辑与和逻辑或、逻辑非,逻辑与和逻辑或有两种:一种逻辑与(&)和逻辑或(|);另一种叫做短路与和短路或。正常使用的是短路与(&&)和短路或(||)。
逻辑与和短路与的主要区别在于:逻辑与会从头到尾判断每一个条件,如果所有条件为真,那么结果为真,有一个条件为假,结果为假;短路与会从头开始依次判断每一个条件,如果存在一个条件为假,那么后面的条件将不再判断,结果为假,所有条件为真,结果为真。
逻辑或和短路或主要区别在于,逻辑或会从头到尾判断每一个条件,如果条件都为假,结果为假,有一个条件为真,结果为真;短路或从头到尾依次判断每一个条件,如果说某一个条件为真,后面的条件不在判断,结果为真,如果全部条件都为假,结果为假。
逻辑非的操作时非常简单的,就是将真变为假,假变为真:
三目运算符
三目运算符主要是由一个布尔表达式来构成的,除此之外还有针对于布尔表达式的结果分别执行的两个表达式,其语法如下:布尔表达式?条件为真的表达式:条件为假的表达式
自加和自减运算符
自加和自减运算符是在早期内存相对比较珍贵的情况下经常使用的运算符,那么现在对于该运算符的使用,主要根据个人的喜好就可以了
自加运算符:++
自减运算符:--;
在使用的过程中,主要掌握运算的步骤就行了
以上的代码是先运算再自加,但是如果使用++i,那么应该是先自加再运算:
表达式
由运算符和变量、常量所组成的算式就叫做表达式
程序的流程控制
在java中程序的流程控制主要有三种:顺序结构、选择结构、循环结构
顺序结构
顺序结构是最简单的程序流程,主要是从主方法依次往下执行,一直到程序的末尾,就叫做顺序结构
选择结构
选择结构通常伴随着条件的判断,来决定执行一些列的相关代码。在选择结构中叶包含多种形式,首先最简单的一种就是if语句,其语法如下:
if(布尔表达式){}
如果说if条件满足执行的代码只有一行的话,那么这个大括号可以省略。但是这种写法,只要知道,不要用。
如果需要判断条件,条件满足执行一些操作,条件不满足执行另一些操作,需要if…else…
当然还有其他的形式:if…else if….else….那么这种语法形式也叫做分支语句
以上的代码结构思路非常清晰,只要满足相应的条件去执行相应的代码就可以了。但是要注意一下的情况:
分支语句如果一个条件满足,那么会执行这个分支的语句,不会再去执行其他的分支。
分支语句除了以上的语法结构之外还有一种switch…case….来实现分支语句。语法形式如下:
Switch(匹配的变量){
Case 匹配的值1:执行的代码块;
Case 匹配的值2:执行的代码块;
Default:默认情况下执行的代码;
}
import java.util.Scanner;
public class SwitchDemo
{
public static void main(String[] args)
{
// 获取用户输入的值
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
// 根据用户的输入来执行分支语句
switch (n)
{
case 1:
System.out.println("星期一,猴子穿新衣");
break;
case 2:
System.out.println("星期二,猴子做老二");
break;
case 3:
System.out.println("星期三,猴子爬雪山");
break;
case 4:
System.out.println("星期四,猴子看电视");
break;
case 5:
System.out.println("星期五,猴子打老虎");
break;
case 6:
System.out.println("星期六,猴子在家休息");
break;
case 7:
System.out.println("星期日,猴子在家休息");
break;
default:
System.out.println("您的输入有误");
break;
}
}
}
以上的代码是相对比较容易理解的,但是要注意的是:分支语句中的break千万不要忘记,同时switch单词不要写错。除此之外还有一点需要注意:switch不能用来表示范围的判断。
以上的代码,可以发现switch分支语句只能进行某种数据类型的值的匹配,不能用来进行区间的判断,可以使用if分支语句来实现。在java中swicth所能支持的数据类型有byte、short、int、char,jdk1.7以后加入了对String的支持、枚举。
循环结构
循环结构是最常用也是最重要的一种控制结构,同时也是相对较难理解的一种程序控制结构。尤其是循环的嵌套,是需要花时间去好好理解的。循环结构主要有三种:while循环、do…while和for循环。
while循环
While循环主要是针对于已知循环结束条件的情况下使用的循环结构。其语法结构如下:
While(循环的判断条件){
循环体;
循环变量的变化;
}
从以上的语法可以看出,while是当循环的判断条件满足的情况下去执行循环体的操作,已知到循环的条件不满足为止。而循环变量的变化一定不要忘记,否则会出现死循环。
do…while循环
除了while循环以外那么还有一个相对应的循环do…while循环,其语法如下:
do{
循环体;
循环变量的变化;
}while(循环条件的判断);
从以上的语法来看,do…while循环是先执行后判断,如果条件满足则继续执行循环体,知道条件不满足为止。
从以上的代码的执行结果可以看出,do…while循环先执行再判断,循环体至少执行一次,而while循环有可能一次都不执行的。While有时候也被称为当型循环,do…while也被称为直到型循环。
for循环
for循环以其语法上的特点,经常被大家使用。for循环的基本语法如下:
for(循环变量的定义;循环条件的判断;循环变量的变化){
循环体;
}
for循环除了以上的这种语法形式之外,还可以进行一些变形
循环的中断
如果在循环执行过程中希望认为中断循环的执行,需要使用break和continue,两者的区别在于continue表示的是结束本次循环,然后回到循环的起点,继续下一次循环。
break表示的是结束整个循环体,然后退出循环的操作
break来结束循环指的是结束当前的这一层的循环,如果外部还有其他的循环将继续执行。
循环的嵌套
循环的嵌套是一个相对比较难理解的操作,主要是因为当嵌套的层数多了以后,对于变量的变化将变得难以区分,在实际的开发中,循环的嵌套正常最多只能有三层。
public class ForDemo
{
public static void main(String[] args)
{
// 打印99乘法表
// 定义一个外层循环用来控制当前的行数
for (int i = 1; i <= 9; i++)
{
// 定义一个内层循环用来控制列数
for (int j = 1; j <= i; j++)
{
System.out.print(j + "*" + i + "=" + j * i + "\t"); // \t表示的是跳转一个制表位
}
// 进行换行
System.out.println();
}
}
}
结果是一张99乘法表:
从以上的问题的解决思路可以发现,两层循环的嵌套可以理解位一种表格的形式。
如果遇到三层循环的嵌套可以理解位一种空间结果。
方法的使用
所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块
方法的定义
方法的定义形式语法如下:
public static 返回值类型 方法名称(参数列表){
方法体;
[return 运算的结果;]
}
-public static:这里定义的方法指的是由main直接调用的方法,main方法是public static,那么自定义的方法也必须是public static。
-返回值类型:指的是方法处理完以后返回的数据的类型,如果方法没有明确的返回值类型使用void代替。
-方法名称:只需要满足标识符的命名规范就可以了,具体可以根据实际的需要进行定义。
-参数列表:值得是调用方法时传递的运算的参数,参数可以有一个或者多个,用逗号进行分割。同时还要区分实参和形参的概念。
-return:表示结束方法,返回运算的结果,但是需要注意返回的数据类型不惜要与生命的返回值类型一致。
无参无返回值的方法:
public class Test{
public static void main(String[] args){
say();
say();
say();
}
//定义一个方法
public static void say(){
System.out.println("大家好,我叫张三");
}
}
以上的代码非常简单,那么接下来看一下无参有返回值的方法的调用
public class Test{
public static void main(String[] args){
//调用的方法具有返回值,那么需要在方法的调用出定义一个相同类型的变量进行接收
double pi = getPi();
//控制台输出
System.out.println(pi);
}
//定义一个方法
public static double getPi(){
return Math.PI;
}
}
除此之外还有一种叫做有参有返回值:
public class Test{
public static void main(String[] args){
//调用的方法具有返回值,那么需要在方法的调用出定义一个相同类型的变量进行接收
int n = 10 ;
int m = 20 ;
//调用方法进行运算
int sum = sum(n,m);
//控制台输出
System.out.println(sum);
}
public static int sum(int x , int y){
int sum = x + y;
return sum;
}
}
方法的使用时没有什么难度的,但是需要根据实际的业务逻辑来进行方法的模块划分,这是需要一定的业务经验才能做好的。
方法的执行流程
方法的执行指的是程序在主方法中遇到方法的调用会转到方法中往下执行,知道方法执行完成以后返回到方法的调用处继续往下执行一直到程序的末尾。需要注意在方法中可以使用return关键字来结束方法的执行。
public class Test{
public static void main(String[] args){
//调用的方法具有返回值,那么需要在方法的调用出定义一个相同类型的变量进行接收
int n = 10 ;
int m = 20 ;
//调用方法进行运算
System.out.println("方法调用开始");
fun();
System.out.println("方法调用结束");
}
public static void fun(){
for(int i = 1 ; i <=10 ; i++){
System.out.println(i);
}
return;
System.out.println("方法执行的末尾");
}
}
语句块和变量的作用域
使用大括号括起来的代码就成为语句块,这个概念的提出主要是为变量的作用域来服务。语句块确定了变量的作用域。语句块内也能定义变量,但是这个变量的作用域只能在这个块内有效,如果在这个语句块外部再去引用这个变量将会发生编译错误。另外,不允许在嵌套的两个块内声明同名的变量。
方法的重载
在解释方法的重载之前,先来分析一下如下的情况:
public class Test{
public static void main(String[] args){
int sum = sum(10.0F,20.0F);
}
public static int sum(int x ,int y){
return x + y ;
}
public static float sum3(float x , float y){
return x + y;
}
public static int sum2(int x, int y ,int z){
return x + y + z;
}
}
针对于以上的问题可以使用重载,那么什么叫重载呢?
重载指的是:在一个类中定义的方法名称相同,参数列表(参数的类型或者参数的个数或者参数的顺序)不同的方法。这样在方法调用时,jvm会自动根据参数的类型和参数的个数来找到相应的方法来进行调用。
public class Test{
public static void main(String[] args){
int sum = sum(10,20,30);
System.out.println(sum);
}
public static int sum(int x ,int y){
return x + y ;
}
public static float sum(float x , float y){
return x + y;
}
public static int sum(int x, int y ,int z){
return x + y + z;
}
}
但是需要注意方法的重载只是与参数列表有关与方法的返回值类型无关。
方法的递归调用
方法的递归调用需要具有一定的逻辑思维能力,在一开始相对是有难度的,这里也不强制大家立即掌握,随着代码量的增加,递归会逐渐的容易理解,那么在这里介绍大家一种解决递归问题的思路。
递归指的是方法自身调用自身,但是必须明确递归结束的标记。
public class Test{
public static void main(String[] args){
int sum = digui(10);
System.out.println(sum);
}
//使用递归必须首先定义一个方法
public static int digui(int n){
if(n==1){
return 1;
}
return n + digui(n-1);
}
}
以上的代码经过分析以后思路还是比较清晰的,那么接下来就来实现通过递归来计算!n。针对于递归的操作,主要分为两个步骤:1找出递归的出口,2、怎样向出口逼近
public class Test{
public static void main(String[] args){
int num = jiecheng(4);
System.out.println(num);
}
public static int jiecheng(int n){
//递归的出口是1,返回1
if(n==1){
return 1;
}
//向出口逼近
return n*jiecheng(n-1);
}
}
在实际的使用中还有一个经典的递归问题:斐波那契数列
public class Test{
public static void main(String[] args){
//1 1 2 3 5 8 13 21 34
int num = fbnq(6);
System.out.println(num);
}
public static int fbnq(int n){
//递归的出口
if(n==1||n==2){
return 1;
}
//向出口逼近
return fbnq(n-2)+fbnq(n-1);
}
}
数组的使用
数组是一组相关数据的集合,一个数组实际上就是一连串的变量。数组实际上是一组连续的内存空间,访问效率是比较高,同时提供索引来方便我们访问数组中的元素。
数组的定义
数组的种类可以根据数组的维数来进行划分,这里我们先来介绍一位数组。其定义语法如下:
声明:数据类型[] 数组名称
直接声明的数组是无法直接使用的,那么要使用数组,必须进行数组的实例化操作。使用new关键字来进行
实例化:数组名 = new 数据类型[数组长度];
实例化以后的数组实际上完成了对内存的开辟。内存的分配也分为两个步骤。声明数组时,在栈内存中开辟了一块空间,命名为数组名;实例化数组对象时开辟堆内存空间,大小由数组的数据类型和长度来决定,并且将开辟内存的首地址保存在栈内存中,这样形成了一个占内存中的变量对堆内存的引用。
public class Test{
public static void main(String[] args){
//声明一个整型数组
int[] nums = null;
//为数组开辟内存空间
nums = new int[4];
//数组实例化以后会进行自动的编号就是索引
nums[0] = 10;
nums[1] = 20;
nums[2] = 30;
//数组可以与for循环相结合来访问数组中元素的数值
for(int i = 0 ; i < 4 ; i++){
System.out.println(nums[i]);
}
}
}
以上的操作完成了对数组元素的赋值以及取值操作。数组中的元素都有其默认值。接下来验证一下数组却是是在栈内存中保存堆内存地址。
public class Test{
public static void main(String[] args){
//声明一个整型数组
int[] nums = null;
//为数组开辟内存空间
nums = new int[4];
//直接访问数组对象
System.out.println(nums);
}
}
数组的初始化的操作
在java中数组的初始化有两种方式:一种叫做静态初始化,一种叫做动态初始化
静态初始化:指的是在维数组开辟对内存空间的同时,完成对数组元素的初始化赋值操作。
public class Test{
public static void main(String[] args){
//声明一个整型数组,并完成静态初始化
int[] nums = {10,20,30,40,50};
//遍历数组中的元素
for(int i = 0 ; i < 5 ; i++){
System.out.println(nums[i]);
}
}
}
静态初始化除了这种方式以外还可以有其他的形式
public class Test{
public static void main(String[] args){
//声明一个整型数组,并完成静态初始化
int[] nums = new int[]{10,20,30,40,50};
//遍历数组中的元素
for(int i = 0 ; i < 5 ; i++){
System.out.println(nums[i]);
}
}
}
以上的这种形式不要制定数组长度,否则会出现编译错误。
针对于数组的使用,还有一个问题需要大家注意:在访问数组元素的时候,索引值一定不要超出数组的长度。
public class Test{
public static void main(String[] args){
//声明一个整型数组,并完成静态初始化
int[] nums = new int[5];
System.out.println(nums[5]);
}
}
以上的代码发生异常: java.lang.ArrayIndexOutOfBoundsException: 5,表示的是数组索引越界异常。
对数组的新的支持
对数组的新的支持主要体现在:1、可变参数;2、增强型for循环
可变参数指的是在方法中,可以不明确参数的个数,参数的个数由方法的调用出来决定。
public class Test{
public static void main(String[] args){
int sum = sum(10,20,30);
System.out.println(sum);
}
public static int sum(int ... n){
int sum = 0;
for(int i = 0 ; i < n.length ; i++){
sum += n[i];
}
return sum;
}
}
public class Test{
public static void main(String[] args){
//定义一个数组
int[] nums = {10,20,30,40,50};
//遍历
for(int n : nums){
System.out.println(n);
}
}
}
针对于这两种新的支持,根据自己的喜好进行使用就行了。
多维数组的使用
多维数组的使用通常只会用到二维和三维数组,其他的形式在实际开发中很少用到,那么在这里,我们只介绍二维和三维的数组的使用。
二维数组跟一维数组比较相似,可以理解位一种表结构。其语法如下:
数据类型[][] 数组名 = new 数据类型[行数][列数];
二维数组可以进行静态初始化:
public class Test{
public static void main(String[] args){
//定义一个二维数组
int[][] nums = new int[3][4];
//访问数组中的元素进行赋值操作
nums[0][0] = 1;
nums[0][1] = 2;
nums[0][2] = 3;
nums[0][3] = 4;
nums[1][0] = 11;
nums[1][1] = 12;
nums[1][2] = 13;
nums[1][3] = 14;
nums[2][0] = 21;
nums[2][1] = 22;
nums[2][2] = 23;
nums[2][3] = 24;
//遍历数组中的元素
for(int i = 0 ; i < nums.length ; i++){
for(int j = 0 ; j < nums[i].length ; j++){
System.out.print(nums[i][j]+"\t");
}
System.out.println();
}
}
}
public class Test{
public static void main(String[] args){
//定义一个二维数组
int[][] nums = {{1,2},{3,4,5},{6,7,8,9}};
System.out.println(nums[0][2]);
//遍历数组中的元素
for(int i = 0 ; i < nums.length ; i++){
for(int j = 0 ; j < nums[i].length ; j++){
System.out.print(nums[i][j]+"\t");
}
System.out.println();
}
}
}
通过以上代码的执行结果发现,每一行的元素的个数由用户进行静态的指定,不会开辟额外的数据的空间。
三维数组就是在二维的基础上再加一维,但是实际的使用时相对麻烦许多。
public class Test{
public static void main(String[] args){
//定义一个二维数组
int[][][] nums = new int[2][3][4];
//赋值操作
nums[0][0][0] = 10;
//遍历
for(int i = 0 ; i < nums.length ; i++){
for(int j = 0 ; j < nums[i].length ; j++){
for(int k = 0 ; k < nums[i][j].length ; k++){
System.out.println(nums[i][j][k]);
}
}
}
}
}
三维数组的静态初始化:
public class Test{
public static void main(String[] args){
//定义一个二维数组
int[][][] nums = {{{1,2},{3,4,5},{6,7,8}},{{0,1},{3,4,5,6}}};
//赋值操作
nums[0][0][0] = 10;
//遍历
for(int i = 0 ; i < nums.length ; i++){
for(int j = 0 ; j < nums[i].length ; j++){
for(int k = 0 ; k < nums[i][j].length ; k++){
System.out.println(nums[i][j][k]);
}
}
}
}
}
数组的排序问题
数组的使用过程中经常需要对数组元素进行排序操作:排序的算法有很多,其中比较常见的就是冒泡排序、选择排序。
冒泡排序:主要是指将大的数值一步一步向后移动,经过一轮以后,会将最大的值排到数组的末尾。
public class Test{
public static void main(String[] args){
//定义一个一维数组
int[] scores = {75,68,80,79,53};
//要进行冒泡排序
//定义一个外层循环用来控制轮数
for(int i = 0 ; i < scores.length-1 ; i++){
//定义内层循环用来控制比较开始的数据的索引
for(int j = 0 ; j < scores.length-i-1 ; j++){
if(scores[j]>scores[j+1]){
//交换两个数的为止
int temp = scores[j];
scores[j] = scores[j+1];
scores[j+1] = temp;
}
}
}
//遍历数组中元素
for(int n : scores){
System.out.print(n+" ");
}
}
}
选择排序也是一种常用的排序方式:
public class Test{
public static void main(String[] args){
//定义一个一维数组
int[] scores = {75,68,80,79,53};
//要进行选择排序
//定义一个外层循环用来控制轮数
for(int i = 0 ; i < scores.length-1 ; i++){
for(int j = i+1 ; j < scores.length ; j++){
if(scores[i]>scores[j]){
int temp = scores[i];
scores[i] = scores[j];
scores[j] = temp;
}
}
}
//遍历数组中元素
for(int n : scores){
System.out.print(n+" ");
}
}
}
但是除了笔试以外的其他场合,要进行数组的排序,不需要自己定义方法解决,只需要调用系统提供的方法就行了。
import java.util.Arrays;
public class Test{
public static void main(String[] args){
//定义一个一维数组
int[] scores = {75,68,80,79,53};
//调用系统API进行排序
Arrays.sort(scores);
//遍历数组中元素
for(int n : scores){
System.out.print(n+" ");
}
}
}