本节课程主要把最基本的、必备的知识梳理一遍。认真学完本节课程,可以直接跳到web应用阶段,等有一定的代码功底了再回过头来继续学习java语言更高级的用法。
为什么不先学完了《java语言入门到精通》再学web应用开发?因为你现在很菜,菜到连庐山的全貌都没见过,如果给你讲某亭子在山上的某某位置,你有概念吗,有画面感吗?
几乎所有培训机构,第一个月都在讲《java语言》,每天连续讲,整整一个多月。这些学生一个小案例都没有实现过,给他们讲多线程、设计模式、面向对象,这不是存心恐吓小学生嘛。最终的结果是,这一个月学的东西能真正消化两三成就已经不错了,很多学生学着学着开始怀疑自己,学了这么久,学得这么困难,还没看到大山的影子。就如同一个人在沙漠中迷路,只知道自己每走一步都很艰难,不断鼓励自己再坚持,但内心早都快崩溃了。
在有一定的编程体验、对实现业务流程有一定的功底、了解前后端数据库大概是怎么回事之后,再回过头来补充java语言高级知识,事半功倍,掌握更轻松,理解更深入、具体。
必须认清一个现实,掌握java高级用法和能独立开发项目是两码事。现在,我们只需要能用java语言实现基本的、常用的逻辑就可以了,这并不影响我们做项目。
学习之前,请确保你的开发环境已经准备好,已经可以在开发工具中运行main方法。因为下面讲的内容,都是可以复制到main方法中运行的(最起码什么是main方法要先搞清楚)。
1、数据类型
我们先学习三种:
int 整数数字(不带小数点)
float 小数数字(可以带小数点也可以不带)
String 字符串(注意第一个字母是大写,准确说这不是一种基本数据类型,但目前可以勉强认为它是)
了解它们的用法之前,首先思考一个问题:1+1=?
你会告诉我,这当然是等于2了。没错,这种场景下,你是把它当作数字来处理了。那有没有可能等于“11”呢?也是有可能的,来看一个例子:
以前看过一个段子,讲的是一对夫妻为了公平,取钱的时候必须两人都在场,于是他们想了一个办法,就是把密码分成两段,老公掌握前三位(假设是123),老婆掌握后三位(假设是456)。假如有一天,他们一起去取钱,先后向柜员提供了123和456两组数字,并告诉柜员把两个加起来就是密码。当然,柜员是人类,按照常识,这里说的加起来肯定是两组数字前后拼在一起,而不是123+456=579,这是很显然的。然而,我们程序员面对的是机器,并不是人类,我们写的代码都是为了和计算机对话,你告诉它加起来,它并不懂那么多的人类活常识。
所以说,我们给计算机提供数据时候,是不是应该告诉它数据类型是什么,这样它才知道是按数字的方式进行加减,还是只是把给它的数据拼在一起。由此,就有了数字和字符两种数据类型。其中,数字类型根据是否带小数点、精度范围,又有好几种小类型,我们这里只需要先掌握int和float就可以了,会用之后其它的数字类型几乎完全一样的用法。
根据以上案例,我们来实现一下计算机的运算。
1)要求计算机以数字方式进行处理
int a = 123; // 双斜线是单行注释,这一行从双斜线开始,后面的内容被计算机忽略,不计入语法。这种注释方式经常用,通常用于表达代码写到这里你的想法是什么,有什么需要注意的,以便后面你自己或者其它程序员几年这后来看这些代码都能很快搞清楚思路。
int b = 456;
int c = a + b; // 让计算机执行一下a+b运算
System.out.println("运算结果为:"+c);
可以看到,由于我们给计算机的是数字类型,所以计算机按数字来处理,得到的结果c是579,这和我们平时的数学运算是一个道理。
2)要求计算机按字符方式运算
String a = "123";
String b = "456";
String c = a + b; // 加号的意思就是拼接起来
System.out.println("运算结果为:"+c);
可以看到,由于我们给计算机的是字符类型,所以计算机按字符来处理,得到的结果c是,并不是579,这就和数字运算有很大的区别了。好好对比一下段代码和运算结果,总结一下什么是数字类型,什么是字符类型,运算区别在哪里。
我们还提到了另一种数字类型float(带小数点的数字),这里我建议自己去研究尝试,因为它的道理和int基本一样,只不过它允许带小数,而int只能是整数。
我只写一句,其它的你们自己发挥:
float a = 1.0f;
数字后面要带一个f,否则会报语法错误。
另外,注意到我们写了很多类似于“int a = 1;”这样的代码。这里有必要简单解释一下:
这是定义一个变量,或者说定义一个数据出来,这样方便后续的一些运算。比如,用户消费金额为100元,我们后续要用这个金额来进行积分计算,还要用来计算余额,所以我们要想办法把这个金额传给后续步骤。怎么传呢,把鸡蛋放在篮子里面,再传过去,对方拿到篮子,再从里面取出鸡蛋。
所以,我们会这样写:
float payMoney = 100.0f;
在这里,100.0f就是实际的鸡蛋,payMoney就是篮子,float是告诉别人这个篮子里面放的东西是鸡蛋而不是石头。
说专业一点呢,float是数据类型,表示它接下来修饰的变量是一个小数点数字类型。payMoney是变量,它指向一个实际的值100.0f,通过等号把变量和值连在一起,这叫做赋值(这个名词一定要记住)。每一行代码末尾用分号,相当于我们人类语言中写完一句话要用句号。
提醒:我们写代码,用到的所有符号,都是英文状态下的,一般不会有中文状态下的符号(最容易搞错的就是双引号和逗号),自己要小心,要学会对字符敏感。
2、条件判断
假设有这样一个场景:
我们目前正在写一段给用户计算积分的代码逻辑,根据用户的等级(假设有0级和1级两种级别),执行不同的计算逻辑。0级的按消费金额1%计算积分,1级的按消费金额2%计算积分。所以我们会设定好这两种选择,写好相关的代码逻辑。然后,是不是应该告诉计算机,哪种情况下该执行1%的计算,哪种情况下该执行2%的计算。
所以,我们要通过条件判断语句来告诉计算机!
以下代码叫做伪代码,意思大概列一下代码逻辑,并不能真正用于执行:
if(用户等级=0){
积分=金额*1%
}else{
积分=金额*2%
}
其中,if可以理解为“如果”,后面紧跟着一个小括号,写“如果”所对应的条件,当代码运行到这里满足这个条件,就会进入到这个if后面的大括号内执行。
else可以理解为否则,假设前面的if没有满足条件,就代码就会进入到else后面的大括号内执行。
也就是说,代码运行到这里,会有几个分支,根据一些条件选择其中一条路走。
那我们写代码,又该怎么来写呢?接下来我们认真写一遍:
int userLevel = 0; // 这是用户等级,我们在这里写死是为了便于简化代码,把注意力放在跟我们课程相关的方向。实际场景中,这个数据应该是从某个地方获取到的,我们这里就暂且认为我们已经不择手段获取到它了。
float payMoney = 100.0f; // 这里消费金额,同理,这个数据也应该是从某个地方获取,我们暂且认为我们通过某种方式已经拿到了,所以直接写死。至于如何拿到,并不是我们本次讲解的重点,后续会讲。
float score = 0.0f; // 积分,定义出来应该是0
if( userLevel == 0 ){
score = payMoney * 0.01f;
}else{
score = payMoney * 0.02f;
}
System.out.println("计算出来的用户积分为:" + score); // 可以尝试修改userLevel,假设我们取到了其它的级别,会怎么样。
/
* 这是多行注释,当我们需要写一段注释时使用。
* 至于它有什么特点,以什么开头,以什么结尾,自己观察,然后在开发工具上试试。
*
* userLevel == 0 可以看到我们想表达两个数据是否相等,用的是连续的两个等号,因为在编程语言里,两个等号的意思才是是否相等,而一个等号的意思是赋值。这就是语法,没什么好解释的,记住就行。
* 乘号用的是一个星号,而1%用的是0.01道理是一样的,java语言的1%并不是百分之一的意思,所以我们要用另一种表达方式。
* 这里的金额用到了float,因为金额有可能带小数点。但是,我要提醒的一点是,以后工作中凡是涉及到金额,千万不能用float(会有精度问题),而应该用另一个类型(后面会讲到),否则会出人命的!
* 由于我们目前对于小数点只学到float,所以先凑合一下,不影响我们目前的需要。
*/
到目前为止,我们已经对if-else语句有了一个初步的认识。在这个基础之上,我们现在把需求变一下:
假设有用户等级0、1、2、3和更高,积分计算方式分别为1%、2%、3%、4%、5%,用if-else来实现。这种情况下,我们的if是不是就不止一个了,而是多个。但不管有多少个if,代码运行到这里只会选择一个进入,而放弃其它几个。
由此,我们引入了else if,意思是,多个if并列,当前面一个if的条件不满足时,再判断我的条件。由于和之前的单个if道理差不多,下面,我就直接贴代码了:
int userLevel = 4; // 这是用户等级,我们在这里写死是为了便于简化代码,把注意力放在跟我们课程相关的方向。实际场景中,这个数据应该是从某个地方获取到的,我们这里就暂且认为我们已经不择手段获取到它了。
float payMoney = 100.0f; // 这里消费金额,同理,这个数据也应该是从某个地方获取,我们暂且认为我们通过某种方式已经拿到了,所以直接写死。至于如何拿到,并不是我们本次讲解的重点,后续会讲。
float score = 0.0f; // 积分,定义出来应该是0
if( userLevel == 0 ){
score = payMoney * 0.01f;
}else if( userLevel == 1 ){
score = payMoney * 0.02f;
}else if( userLevel == 2 ){
score = payMoney * 0.03f;
}else if( userLevel == 3 ){
score = payMoney * 0.04f;
}else{
score = payMoney * 0.05f; // 前面几个if选择一个满足条件的进入,如果前面几个if一个都没进,就进else
}
System.out.println("计算出来的用户积分为:" + score); // 可以尝试修改userLevel,假设我们取到了其它的级别(比如1或4),会怎么样。
3、循环
假设让你写三行代码,第一行输出1,第二行输出2,第三行输出3,你怎么写?
像这样:
System.out.println(1);
System.out.println(2);
System.out.println(3);
显然是不可能的。难道如果要求你输出到100,你就要写100行?
所以,我们可以用循环来自动帮我们生成代码,不管写100行还是1000行,我们通过循环语句,要写的也就那么几行。
下面,据以上需求,我直接贴一个代码:
int index = 1;
while(index<4){
System.out.println(index);
index = index + 1;
}
System.out.println("end");
就是这么简单。下面我解释一下这几行代码的含义:
定义一个初始变量index,初始值为1,当index小于4时,进入循环语句块执行相关逻辑。
由于index目前为1,所以是满足条件的,所以进入了while代码块。进去之后,输出了index,此时为1,然后给index变量重新赋值,新的值为原先的值加1,也是是2,程序到此终止。
但程序并没有到此结束,而是回过头去再次判断一下while后面小括号里面的条件。由于此时的index为2,满足小于4的条件,所以程序再次进入到对应的大括号,再次执行刚才一样的流程,只不过这一次的index为2,执行完index=index+1之后,被重新赋值为3,以此类推。
直到当index为3时,再次进入,并被赋值为4,再次回去判断,发现已经不满足小于4的条件,所以跳出循环,循环终止(但会继续执行while语句块后面的代码)。
也就是说如果我们把while(index<4)改为了while(index<400),这个循环就会执行399次。
搞清楚while循环之后,再看另一个相似的用法:
for(int index=1;index<4;index=index+1){
System.out.println(index);
}
System.out.println("end");
这个写法和while的执行原理基本一致,我就不重复介绍了。区别在于,把原先分成多行的几句代码写在了一行,放在了括号里。
我们仔细看for后面的括号,以分号拆开,是不是相当于有三句代码,而且这三句代码似曾相识。
其实是,由于像刚刚while循环那样,定义一个变量,然后以这个变量判断是否进入循环,并在末尾将这个变量加1,这样的操作太常见了,所以java帮我们优化了一下,从语法上支持他们在一起。
那我们通常用哪种循环?先别想那么多,先记住这两种,这是必备知识。
4、异常处理
我们写的代码都比较顺利,只要没有语法错误,都可以按照我们预想的流程去执行。但在实际开发中,经常都会有一些错误,只有在运行中才会出现,这是无法避免的。
那么,假设我们写了1-2-3行代码,其中,第2行代码出错了,会怎么样呢,这三行代码都能顺序执行吗?
下面,我们就来看一个例子:
String payMoneyStr = "100"; // 假设从某处传递了一个消费金额过来,但这小子居然给我们传的字符类型。所以如果我们要用来计算积分,必须把它转换为数字再计算,否则计算机会把它当成字符来处理,后果你可以试试。
float payMoney = Float.parseFloat(payMoneyStr); // 别管那么多,这句代码你看不懂,你只需要知道我们是把字符转换为数字就行了,又不是必须每句代码都要搞懂才能看懂逻辑。
float score = payMoney * 0.01f;
System.out.println("积分为:"+score); // 完美输出,与我们想要的结果一致
以上是一个故事,接下来我们看看事故是怎么发生的:
String payMoneyStr = "100元"; // 同样给我们传了一个消费金额过来,但这傻子居然带了单位!"100元"是数字吗?明显不是吧,“100”可以勉强算是数字,但“100元”绝对不是。
float payMoney = Float.parseFloat(payMoneyStr); // 然而我们的计算并不知道有人会害它啊,还傻傻的把“100元”转换为数字,结果...
float score = payMoney * 0.01f; // 放心,到不了这里的!
System.out.println("积分为:"+score); // 放心,到不了这里的!
运行之后看到控制台并没有输出我们预想的结果,而是报了一个错误:
Exception in thread "main" java.lang.NumberFormatException: For input string: "100元"
根据我深厚的英文功底,我来给大家翻译一下:
你给我传个”100元”过来让我转成数字,你当我是傻子啊,“元”字是什么鬼,一边儿凉快去!
综上所述,我们明白了一个真理:
字符“100”转换为数字是符合道德规范的,而字符“100元”会被机智的计算机拒绝执行。
到这里,我们已经深刻地认识到,有些问题,只有在程序运行过程中,数据有问题,才会导致出错,从而引起程序被打断。所以,写完之后没看到语法错误,这时候高兴绝对是太早。
那么,有没有办法让程序出错的情况下,继续往下走,而不要打断呢?
当然可以,前提是你提前预知了那一块代码可能有风险,所以你在那里安排了一个锦囊妙计,在危机出现时成功化解,保证工作继续开展。
我们来看下面一段代码:
String payMoneyStr = "100元";
float payMoney = 0.0f;
try{
payMoney = Float.parseFloat(payMoneyStr);
}catch (Exception e){
e.printStackTrace();
}
float score = payMoney * 0.01f;
System.out.println("积分为:"+score);
可以看到,运行结果是,依然无法避免报错。但即使报了错,并没有影响最末两行代码的执行。只不过,payMoney的转换和重新赋值执行失败,但并不影响payMoney继续等于0,并参与积分计算。
这就是try-catch代码块,这个组合目前并不建议完全搞懂,你只需要会抄过去改就可以了,然后重点搞清楚它的运行流程:
try后面的大括号,如果这个范围内的代码运行报错,就会中止这个括号内的后面的代码,并进入到catch后面的大括号中执行。至于catch后面的小括号Exception e是什么意思,先不用管,e.printStackTrace()是输出报错的意思,如果把这行去掉,你会发出控制台就不会再输出错误(不输出报错并不代表没错)。说起来有点难抽象,不如再看看下面这段代码的运行结果,你就明白代码的流程是怎么走的了(一定要结合代码好好理解,try-catch很常用,很关键,一定要真正搞懂):
String payMoneyStr = "100元";
float payMoney = 0.0f;
try{
System.out.println("try-1");
payMoney = Float.parseFloat(payMoneyStr);
System.out.println("try-2");
}catch (Exception e){
System.out.println("catch-1");
// e.printStackTrace();
}
System.out.println("3");
float score = payMoney * 0.01f;
System.out.println("积分为:"+score);
在这个基础上,还有一个finally语句块,只不过这个是可选项,可写可不写(也就是说try-catch必须一起出现,但finally可以随try-catch出现,也可以不出现)。如果写了,运行结果是:
不论前面的try-catch怎么运行,是否进入catch,在try-catch执行完之后,一定会进入finally语句块:
String payMoneyStr = "100元";
float payMoney = 0.0f;
try{
System.out.println("try-1");
payMoney = Float.parseFloat(payMoneyStr);
System.out.println("try-2");
}catch (Exception e){
System.out.println("catch-1");
// e.printStackTrace();
}finally {
System.out.println("finally");
}
System.out.println("3");
float score = payMoney * 0.01f;
System.out.println("积分为:"+score);
以上内容,重点是要把代码运行起来试,还要注意我写在代码里面的注释。光看我写的文字并没有什么卵用,不如好好体会代码,多去试试按自己的想法修改一下,看看运行结果。这很关键。
5、方法
前面说了那么多,我们都在讲把代码放在main方法里面执行。如果我们真的在开发项目了,这个项目的代码可能几万行到几十万行,甚至更多,难道我们要把这么多代码从头到尾写在一个main方法里面,并且在里面写一大堆的if-else用来处理不同的业务吗?显然不现实。
什么是方法(method)?我也不知道为什么会叫这个名字,我也表示花了好几年时间再慢慢接受了这个难听的名字。我们先来搞清楚它的概念吧(非官方解释,考试请勿用,扣分了别怨我):
把某一独立的业务逻辑代码块封装起来,并给它定义一个名字(方法名),同时支持往里面传入一些数据和向外部传出一些数据(当然也可以不传入和传出)。
你看看电影院的爆米花机器是不是很奇妙?
那台机器就可以看作是一个方法,倒进去的玉米就是传入数据(专业名称叫做输入参数),在机器内部进行一系列的加工,最后出来很多爆米花,这就是传出数据(专业名称叫做输出参数)。
废话不多说,我们来看一个简单的方法定义:
public int computePlus(int a,int b){
int c = a + b;
return c ;
}
这个方法很简单,传入a和b两个整数,方法内部对它们做了加法运算,并把运算结果赋值给c,最终把c传出。
其中方法上面”public int computePlus”中的int就是定义输出参数的类型,定义之后必须在方法里面写return,而且return对应的变量类型必须与方法定义的一致。
而(int a,int b)是在定义方法的输入参数类型,也就是说这里要求了当调用这个方法时,必须传入两个int类型的变量进来。变量名称不重要,关键是类型和位置要对应得上。
方法的基础必学java定义是在类里面,与main方法平级。main方法是个什么方法?这是一个很特殊的方法,是java虚拟机专用的,因为java虚拟机根本不会管你定义了多少方法,写了多少代码,一但程序运行,它直接进入main方法,从main方法的第一行代码开始运行。
那么,我们怎样让程序运行到我们的方法?
既然我刚才说了嘛,main方法是程序入口,程序一但运行起来,会从main方法第一行代码开始执行。说到这里,有点想法没?
所以,我们只需要在main方法里面调用我们定义的方法就行了。
完整代码如下:
public class MyTest {
public static void main(String[] args){
System.out.println("main----1");
int number1 = 1;
int number2 = 3;
int result = computePlus(number1,number2);
System.out.println("方法返回给我们的数据是:" + result);
}
public static int computePlus(int a,int b){
System.out.println("computePlus-----1");
int c = a + b;
return c ;
}
}
在这里,我们定义的两个传入参数a和b,而实际传入的参数名叫number1和number2,这并不影响,只要传入的数据类型能对应上就可以。
而返回值c,我们把它赋给了result,也不影响,只要数据类型对应得上就可以。
其实,看一下下面两行代码你就明白为什么了,因为无论是传入参数还是传出的参数,差不多都是经历了以下过程:
int number1 = 1;
int a = number1;
说白了,调用一个方法,就是相当于把那个方法里面的代码copy过来执行,只不过把输入和输出参数稍微重新赋值一下。
说到这里,你又想问我,既然这样,那为什么我们还要定义方法再调用方法,多麻烦,直接把代码全部写在main方法里面不好吗?
对,我在刚刚学习java的时候也是这样想的,因为我觉得让我掌握新的知识是一种负担,总希望没那么多用法和规则。而且关键是,把代码从头到尾写在一起,写起来确实爽,一直写一直爽,直到后来你要回过头来修改一些逻辑,或者你把代码交接给其它程序员。无论谁看到这样的代码,都会生无可恋的。
所以,虽然你有点难以接受,以后写代码,都要尽量把业务逻辑相对独立的代码拆分出去,定义成一个方法,再去调用。同时,一定要尽量写清楚注释。这是一个程序员的基本品德。
接着讲刚刚的例子。如果我们的方法返回了数据,但我并不在main方法里面去接收它并把它赋值给result,会怎么样呢?当然不会怎么样,爆米花从机器里面出来,你不拿个碗去接住,也不会影响什么,只不过会掉地上然后被保洁阿姨清理走而已。
不信你试试注释掉那两行代码,其它保留不变,运行一下看看(当然,注释掉的两行代码肯定是不会执行的),main方法里面这样写:
System.out.println("main----1");
int number1 = 1;
int number2 = 3;
computePlus(number1,number2);
//int result = computePlus(number1,number2);
//System.out.println("方法返回给我们的数据是:" + result);
如果你不需要获取方法运行完之后的数据,我建议你不要给方法定义返回值,比如:
public static void main(String[] args){
System.out.println("main----1");
int number1 = 1;
int number2 = 3;
computTest(number1,number2);
}
public static void computTest(int a,int b){
System.out.println("computTest-----1");
int c = a + b;
}
你不需要返回值,就把返回值的位置写void,这样就不用写return了。当然,方法里面的逻辑你可以任意写,我这里只是写个示例。同理,输入参数也可以不用定义,这都是根据你的需求而定:
public static void main(String[] args){
System.out.println("main----1");
playTest();
}
public static void playTest(){
System.out.println("playTest-----1");
}
6、类(class)
最后,我们再来讲什么是类。
首先,创建类的步骤,是鼠标选中src下面的包名(如果没有建包,要先创建包,具体步骤参考我的上一篇文章),右键,new,java class,然后输入类名,类名的第一个字母是大写。
来看一个完整的类:
package com.zaki.mytest;
public class MyTest {
public static void main(String[] args){
System.out.println("main----1");
int num1 = 1;
int num2 = 2;
computePlus(num1,num2);
}
public static int computePlus(int a,int b){
System.out.println("computePlus-----1");
int c = a + b;
return c ;
}
}
其中,package定义的是包名,也就是当前这个类是在哪个包路径下,包的层级是以点隔开的。
public class MyTest就是定义了一个类,后面的大括号之间的内容就是这个类的内容。
在这个类的内容里面,定义了两个方法,一个是main,一个是computePlus,同理,每个方法后面的大括号,就是这个方法对应的内容。
在每个方法里面,就是具体的代码逻辑了。
有没有发现,或者体会到,大括号,是个很神奇的东西,在我们的代码世界里,它就是国界线、省界线、市界线、区界线……
类包含方法,方法包含代码逻辑和一些语句块(例如if-else、try-catch),语句块里面还可以再包含语句块和代码逻辑。总结下来,就是这样的关系。
定义方法的时候,你可能注意到了,有些方法带有static而有些没有。目前,我只能简单说带有static的方法是属于类方法,定义方法时都带上,我们先这么玩(虽然很low,但并不影响我们发挥智慧去实现代码逻辑),后面再详细讲。
作业:
经过以上六个步骤,我们已经把java语言最基础的,能用来写代码逻辑的知识,都梳理了一遍。如果真的掌握了,下一步我们可以跳到web应用的学习了,并且很快,你就能做一些实用的小项目了。为了综合运用和巩固学习成果,我们来做一个小练习。
还是刚刚我们说的那个计算积分的例子:
假设有用户等级0、1、2、3和更高,积分计算方式分别为消费金额的1%、2%、3%、4%、5%.
定义一个方法,传入用户等级和消费金额,方法内部用if-else if-else来判断并计算出相应的积分,并返回积分。main方法调用这个方法,取到返回值,并用systemout输出到控制台。
我来大概写一下(伪代码):
public static void main(String[] args){
// ---------假设我们已经从某处获取到了userLevel和payMoney-------------
int userLevel = 1; // 可以修改一下这个等级,然后运行验证一下你的逻辑
float payMoney = 100.0f;
// ----------下面开始计算输打印到控制台-----------------
float scoreResult = 调用方法computScore并传入参数,得到返回值并赋级scoreResult;
System.out.println("scoreResult:" +scoreResult);
}
// 定义方法computScore,注意设置输入和输出参数
public static xxx computScore(x,y){
z = xxxxxxx;
return z
}
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/924.html