Java基础语法

Java代码有一定规范,需要注意关键字和命名规范。

Java关键字

Java自己使用的,有特殊含义的字符,编码时不能使用关键字命名变量,方法和类,Java中有53个关键字,其中goto和const为保留字,现在都没有使用,其有如下特点:

(1)完全是小写字母

(2)在IDE或者notepad++中会显示颜色

标识符

标识符是在Java程序中自己定义的内容,如类的名字,方法的名字和变量的名字等,它有如下规范:

(1)类名规范:首字母大写,采用驼峰命名方式,如HelloWorld

(2)变量名规范:首字母小写,后面的每个首字母大写,如helloWorld

(3)方法名规范:同变量名规范

标识符不能使用关键字,不能以数字开头,可以包含英文字符,数字,$符号和下划线,一般尽量不使用$符号。

驼峰命名法

(1)类名/接口名:如果名字是多个单词组成,每个单词的首字母都需要大写,只有一个单词首字母也大写,如Demo,HelloWorld。

(2)变量名/方法名:如果名字是多个单词组成,第一个单词的首字母小写,其余的单词首字母大写,只有一个单词首字母小写,如demo,helloWorld。

(3)常量名,无论几个单词组成,所有字母大写,多个字母用下划线隔开,如HELLO_WORLD,DEMO。

(4)包名:所有字母小写,如果有多个单词,使用点隔开,如com.boe.exer。

注释

注释有如下几种,个人第一种和第二种比较熟悉了,第三种以前没注意可以提取形成文档。

(1)单行注释 //注释内容

(2)多行注释 /*注释内容*/

(3)文档注释 /**注释内容*/ 文档注释的内容可以提取出来形成文档,使用JDK的工具javadoc命令来执行。

发现使用命令javadoc -d ./ Demo.java后,会在当前文件夹下生成很多html文件,打开index.html,就会发现跟API文档很像。

index.html文档打开后,test方法的注释也会出现在文档里。

字面量

常量是程序运行期间固定不变的量,有如下几种:

(1)字符串常量,用双引号括起来,如"你好","Hello World"

(2)整数常量,就是数字,没有小数点,如100,200

(3)浮点数常量,包含小数点的数字,如1.23

(4)字符常量,用单引号括起来的字符,如'A','B',不能写2个字符以上,或者空的,如''和'AB'会导致编译错误。

(5)布尔常量,值有true和false

(6)空常量,为null,代表没有任何数据,不能用于打印输出,也不能在后面使用String的API

数据类型分类

包含基本数据类型引用数据类型

基本数据类型,细分的话一共有8种:

(1)整数型,包含byte(1字节),short(2字节),int(4字节)和long(8字节),默认是int类型,如果要区分long型,需要在数字后面加L,如long a=123L,其中a就是long型

byte 字节型,范围-2^7~2^7-1,-128到127;

short 短整形,范围-2^15~2^15-1,-32768到32767;

int 整形,范围-2^31~2^31-1,java中整数默认是整形。

long 长整形,范围-2^63~2^63-1,主要表示长整型需要加L后缀。

从JDK1.7开始可以使用分位符号_的方式表示一个整形。

1 public class test1{
2     public static void main(String[] args){
3         //测试分位,在JDK1.7后才出现的表达方式
4         int i=1_234_567;
5         System.out.println(i);
6     }
7 }

(2)浮点型,包含float(4字节,可以精确到小数点后38位)和double(8字节,可以精确到小数点后308位),不论是单精度还是双精度都只是一个近似值,在程序中默认是double类型,如果要区分是float类型,需要在数字后面加上字符f,如float a=3.14f,这个a就是float类型了。

float 单精度类型 范围-10^38~10^38

double 双精度类型 范围-10^308~10^308

另外还有如下方法表示一个double类型,参考代码。

 1 public class test1{
 2     public static void main(String[] args){
 3         //测试分位,在JDK1.7后才出现的表达方式
 4         int i=1_234_567;
 5         System.out.println(i);
 6         //测试科学计数法
 7         double d1=4e4;//4*10^4
 8         System.out.println(d1);
 9         //测试十六进制的科学计数法
10         double d2=0x4p4;//4*2^4
11         System.out.println(d2);
12     }
13 }

测试结果如下。

(3)字符型,包含char(2字节,可以表示中文字符),范围0~65535,默认为UTF-16编码体系。关于编码有如下几种常见的格式:

ISO-8859-1:西欧码表,一个字节一个字符,向下兼容ASCII,主要区别是ISO-8859-1使用了8位,而ASCII只使用了7位。无论是哪张码表都需要兼容西欧码表,即前面256个字符都是一样的。

gb2312:国标码,类似gbk,二个字节一个字符,收录了绝大部分的简体汉字和部分繁体字

unicode编码体系:常见的有utf-8和utf-16,其中utf-8是变长字节编码,可以参考自己的博客https://www.cnblogs.com/youngchaolin/p/10463887.html,utf-16用在char类型,常用2个字节表示一个字符。在英文的世界里utf-8是比较省空间的,而中文的话utf-16比较合适。

参考:https://www.jianshu.com/p/eb68e3298b0b

 1 public class test1{
 2     public static void main(String[] args){
 3         //测试分位,在JDK1.7后才出现的表达方式
 4         int i=1_234_567;
 5         System.out.println(i);
 6         //测试科学计数法
 7         double d1=4e4;//4*10^4
 8         System.out.println(d1);
 9         //测试十六进制的科学计数法
10         double d2=0x4p4;//4*2^4
11         System.out.println(d2);
12         //测试char类型utf-16的书写方式
13         char c='\u9633';
14         System.out.println(c);
15     }
16 }

如上面例子char类型使用utf-16表示,输出结果为'阳'。

转义字符:用键盘无法输出的字符,如制表符'\t'、回车'\r'、换行'\n'、反斜杠'\\'、单引号'\''、双引号'\"'。

(4)布尔型:boolean(一般1字节)

引用数据类型

(1)字符串

(2)数组

(3)类

(4)接口

(5)Lambda

变量

程序在运行过程中内容可以改变的量,成为变量,它有两种赋值方式,第一种是先定义变量后赋值,第二种是定义变量的同时赋值。其使用过程中需要注意的事项:

(1)定义多个变量,名称不能重复

(2)float和long类型,最后建议使用F和L结尾

(3)使用byte类型或者short类型,变量右边的数据值范围不能超过左边的类型范围

(4)没有赋值的变量不能直接使用,需要赋值后才能使用

(5)变量使用不能超过作用域的范围,作用域就是一对大括号包裹的范围

(6)可以通过一个语句定义多个变量,但是不建议这么写

数据类型转换

当数据类型不一致时,会发生数据类型转换,有自动类型转换(隐式)和强制类型转换(显示)两种。

自动类型转换

只能从数据范围小的往数据范围大的转换。

 1 package com.boe;
 2 
 3 /**
 4  * 数据类型转换,隐式类型转换,数据范围从小到大转换
 5  */
 6 public class VariableChange {
 7 
 8     public static void main(String[] args) {
 9         //1 int类型到long类型转换,从小到大的转换原则
10         long num1 = 100;
11         System.out.println(num1);
12         //2 float类型转换为double类型,从小到大的转换原则
13         double num2 = 3.5F;
14         System.out.println(num2);
15         //3 long类型转换为float类型,其实float类型范围还是比long大,虽然float类型只有4个字节,long类型有8个字节
16         float num3 = 300L;
17         System.out.println(num3);
18     }
19 }

数据类型转换有如下几个规律,具体参考代码注释。最后一个需要注意,short类型和char类型无法通过最后一种方式进行相互转换,编译期就开始报错,但是使用字面量(固定的常量值)就可以编译运行通过。原因是因为short类型和char类型两者虽然都是2个字节,但是两者只是交集,因此使用字面量的情况下,可以在编译期就确定是否可以转换,但是如果使用最后一种方式,c2变成了一个变量,编译期无法确定它的范围,因此编译不通过。

 1 public class TypeChange{
 2     
 3     public static void main(String[] args){
 4         //数据类型自动转换规律1:小类型可以自动转换为大类型,如byte→short→int→long→float→long
 5         //整数类型转换浮点类型时,可能存在精度损失
 6         byte b=10;
 7         short s=b;
 8         System.out.println(s);
 9 
10         short s1=32767;
11         int i=s1;
12         System.out.println(s1);
13 
14         //int范围大概在21亿
15         int i1=2000000000;
16         long l=i1;
17         System.out.println(l);
18 
19         //int超过范围,需用long类型并添加后缀L
20         //int i2=20000000000;
21         long l1=20000000000L;
22         System.out.println(l1);
23 
24         //数据类型自动转换规律2 整数int可以自动转换为小数,可能存在进度损失
25         int i2=2000;
26         float f=i2;
27         System.out.println(f);
28 
29         int i3=123456789;
30         float f1=i3;
31         System.out.println(f1);//存在精度损失
32 
33         //数据类型自动转换规律3 char类型可以自动转换为int类型
34         char c='A';
35         int i4=c;
36         System.out.println(i4);
37 
38         //char类型能否和short类型相互自动转化?
39         char c1=97;
40         short s2='a';
41         System.out.println(c1);//a
42         System.out.println(s2);//97    
43 
44         //以上可以自动转换,如下方式可以继续测试
45         //char c2='a';
46         //short s3=c2;
47         //System.out.println(s3);//编译不通过
48     }
49 }

最后一段代码导致编译报错。

在注释掉最后一段代码后,执行结果如下。

强制类型转换

从数据范围大的往小的转换,需要考虑数据溢出,并添加强制转换后的数据类型 (强制转换数据类型)数据,才可以转。

 1 package com.boe;
 2 
 3 /**
 4  * 数据类型转换,强制类型转换,可能会造成精度丢失,和数据溢出
 5  */
 6 public class VariableChangeAdd {
 7 
 8     public static void main(String[] args) {
 9         //1 long转换为int类型
10         int num1 = (int) 1000L;//没有超出int类型数据的范围
11         System.out.println(num1); //1000
12         //2 long转换为int类型,long范围超出范围时
13         int num2 = (int) 100000000000000L;
14         System.out.println(num2); //276447232
15         //3 double类型转换为int类型
16         int num3 = (int) 3.9999;
17         System.out.println(num3); //3
18         //4 byte,short和char执行简单数学运算时,会先向上转换为int类型后才计算
19         char charter = 'A';
20         System.out.println(charter + 1); //66
21         //5 byte和byte执行加法
22         byte num5 = 20;
23         byte num6 = 30;
24         byte num7 = (byte) (num5 + num6);//计算后,结果为int类型,然后int类型向下转型为byte类型
25         System.out.println(num7);
26         //6 数据溢出
27         byte num8 = 100;
28         byte num9 = 120;
29         byte num10 = (byte) (num8 + num9);//计算后数据为220,超出byte数据范围
30         System.out.println(num10); //-36,数据溢出
31 
32     }
33 }

可以看出上面220转换为byte时,会发生精度损失,为什么会显示-36呢?可以先看220,其为int类型一共32位,因此表示为二进制就是00000000 00000000 00000000 11011100,当转换为byte类型时将高位24个0全部截取,剩下为11011100,然后byte类型高位1代表负数,使用互补对称公式计算-n=~n+1,-n=001000011+1,即-n=36因此n=-36。

注意事项:

(1)不推荐使用强制类型转换,可能会发生精度损失,数据溢出

(2)byte/short/char这三种类型都可以发生数学运算,例如加法'+',这三种类型在进行运算的时候,首先会被提升为int类型,然后再进行计算。

(3)boolean类型数据,不能做数据类型转换。

编码初识

美国人刚开始使用计算机采用ASCII(American Standard Code for Information Interchange)编码规范,使用8位即1个字节来表示一个字符或者字母,已经可以满足他们的需要。其中编码有一定的规律,主要记住以下几个:

(1)ASCII 48→ 数字 0

(2)ASCII 65→ 字符 'A'

(3)ASCII 97→ 字符 'a'

如果使用中文,ASCII不能满足需要,后面首先诞生了Unicode万国码,这样中文就可以用Unicode来表示了,底层依然是二进制数字,最后都可以转换为int类型的数字。

 1 package com.boe;
 2 
 3 /**
 4  * 字符转化为数字,复习编码知识
 5  */
 6 public class VariableChar2Number {
 7 
 8     public static void main(String[] args) {
 9         //char类型转换为数字
10         char charter='1';
11         System.out.println(charter+0); //49
12 
13         char charter1='b';
14         System.out.println(charter1+0); //98
15 
16         char charter2='C';
17         System.out.println(charter2+0); //67
18 
19         //自动类型转换,char类型转换为int类型
20         int num='C';
21         System.out.println(num); //67
22 
23         //中文字符
24         char charter3='阳';
25         System.out.println(charter3+0); //38451 这是字符'阳'对应unicode编码所对应的十进制数字,ASCII里无法表示
26     }
27 }

运算符

(1)算数运算符

a byte/short/char类型在参与运算时自动提升为int类型

b 运算中如果有不同类型的数据,结果将按照数据类型大的返回,如int和double,最后运算结果为double

c 同一类型运算结果是同一类型

d 小数运算不保证精确性

e 注意除法运算分母为0的情况

 1 public class Operation{
 2     public static void main(String[] args){
 3         //算术运算
 4         short s1=1;
 5         short s2=2;
 6         int i=(int)(s1+s2);//自动向上转换为int
 7         System.out.println(i);
 8 
 9         //字面量可以,java为了提高运行效率,直接编译时计算得到8,然后赋值给short类型
10         short s3=3+5;
11         System.out.println(s3);
12 
13         //同类型计算计算返回同类型
14         int i1=4500;
15         int i2=i1/1000*1000;
16         System.out.println(i2);
17 
18         //小类型和大类型计算,结果一定是大类型
19         int i3=4500;
20         double i4=i3/1000.0*1000;
21         System.out.println(i4);
22 
23         //小数运算不保证精确性
24         double d1=2.88888;
25         double d2=1.11111;
26         System.out.println(d1-d2);
27 
28         //非零整数/0
29         //System.out.println(5/0);
30         //报异常 ArithmeticException: / by zero
31 
32         //非零小数/0
33         //System.out.println(5.0/0);
34         //报异常 Infinity
35 
36         //非0数字/0.0
37         //System.out.println(5/0.0);
38         //报异常 Infinity 如果是非0负数,则报-Infinity
39 
40 
41         //0/0.0 0.0/0 0.0/0.0
42         //System.out.println(0/0.0);//NaN
43         //System.out.println(0.0/0);//NaN
44         System.out.println(0.0/0.0);//NaN
45 
46     }
47 }

运行结果如下。

另外还有取模运算,可以参考如下代码,计算结果的符号跟%左边的符号一样。

 1 public class Module{
 2     public static void main(String[] args){
 3         //取模运算,类似数学中的取余数,计算机中计算结果会有不同
 4         System.out.println(87%5);//2
 5         System.out.println(-87%5);//-2
 6         System.out.println(87%-5);//2
 7         System.out.println(-87%-5);//-2
 8 
 9         /*
10         取模运算的结果和%左边的数字符号有关,计算时先依据绝对值先计算得到结果,然后通过%左边数字符号得到结果符号
11         */
12 
13         //小数也可以进行取模运算
14         System.out.println(4.5%2);//0.5
15         System.out.println(4.5%2.5);//2.0
16         System.out.println(4.5%2.1);//0.3
17         System.out.println(5%2.1);//0.8
18 
19     }
20 }

控制台输出结果,虽然有精度损失,但是结果是没问题的。

另外还有自增和自减运算,其使用时byte/short/char会自动进行类型转换为int进行计算,然后再强制转换为对应类型。

 1 public class operatorDemo{
 2 
 3     public static void main(String[] args){
 4         //测试自增自减类型转换
 5         byte b=20;
 6         //b+=1;//这样写没问题
 7         //b=b+1;//这样写编译不通过
 8         b++;//这样写没问题
 9         System.out.println(b);
10     }
11     
12 }

使用javap -v -s -p 类名 命令可以查看内存中情况,如下先将20的数字push到byte变量中,然后执行储存加载常量化操作就前缀变成了i,代表int类型,最后执行自增后有一个i2b,代表int向下强制转换为byte,自增自减运算其底层执行了类型转换。

(2)赋值运算符

赋值运算符一般有=、+=、-=、*=、/=、%=等,除了=外,其他几个赋值运算符意思都是在这个变量本身的基础上进行计算,需注意赋值运算符的连等运算。

 1 public class Operator{
 2     public static void main(String[] args){
 3         //测试赋值运算符
 4         byte b=120;
 5         b+=5;
 6         System.out.println(b);//125
 7 
 8         byte b1=120;
 9         b1+=55;
10         System.out.println(b1);//-81
11     
12         //int i,j=5;//编译错误,提示i未初始化,java中不支持连等定义
13         // System.out.println(i);
14         // System.out.println(j);
15 
16         //赋值运算符的连等运算,编译从左往右,运算从右向左
17         int i=5;
18         i+=i-=5;
19         //i=5+(5-5)
20         System.out.println(i);//5
21 
22         int j=5;
23         j+=j-=j/=5;
24         //j=5+(5-(5/5))
25         System.out.println(j);//9
26 
27         int k=5;
28         k-=k*=k++;
29         //k=5-(5*5),这里会先执行k=5*5后再k自增为6,但是最后又执行k=5-(5*5)最后又覆盖6
30         System.out.println(k);//-20
31 
32         int a=5;
33         a=a++;//赋值运算比自增运算靠后,即先取出5准备好用于赋值,发现有自增先将a自增为6,然后再进行赋值运算a又变成5
34         System.out.println(a);//5
35 
36     }
37 }

控制台结果。

(3)位运算符

参考博客:https://www.cnblogs.com/youngchaolin/p/11291809.html

(4)比较运算符

比较运算有==、!=、>、<、>=、<=。

(5)逻辑运算符,注意&&和||的短路逻辑运算符

a 与(and)或(or)非(not) --> &、|、!

b 异或(xor)、短路与、短路或 -->^、&&、||,其中异或本人比较少用已经忘记差不多了,可以参考同极相斥异极相吸来理解,true^true为false,false^false为false,true^false为true,false^true为true。另外如果同时存在短路与和短路或,有如下规则:

&&在||前面,不能将||短路掉: 意思是&&左边为false,还不能判断整个结果为false,继续往后执行看||右边的结果

||在&&前面,可以将&&短路掉: 意思是||左边为true,就能确定整个结果为true,就算右边有&&也无需判断结果

(6)三元运算符

三元运算符必须返回结果被使用,并且=号左右数据类型需一致。语法形式为 返回值类型 返回值=逻辑判断?表达式1:表达式2,逻辑判断为true取表达式1的值,否则取表达式2的值。

 1 import java.util.Scanner;
 2 public class OperatorTriple{
 3     public static void main(String[] args){
 4         //三目运算符
 5         //判断一个数是奇数还是偶数
 6         Scanner scan=new Scanner(System.in);
 7         System.out.println("请输入一个整数");
 8         int i=scan.nextInt();
 9         //String result=i%2==1?"奇数":"偶数";
10         //使用按位与运算 奇数&1=1,偶数&1=0
11         String result=(i&1)==1?"奇数":"偶数";
12         System.out.println(result);
13 
14         //根据分数等级判断学生成绩区间
15         System.out.println("请输入一个分数");
16         int score=scan.nextInt();
17         char rank=score>90?'A':(score>80?'B':(score>70?'C':(score>60?'D':'E')));
18         System.out.println(rank);
19     }
20 }

控制台结果

整体参考如下代码

 1 package com.boe;
 2 
 3 /**
 4  * 运算符:赋值,比较,逻辑,三元,前面的自增自减,四则运算和取模等略去
 5  */
 6 public class OperationCharacter {
 7 
 8     public static void main(String[] args) {
 9         //赋值运算符:
10         //复合赋值运算符,常量不能用于赋值运算符,即常量不能写在运算符的左边
11         int a = 10;
12         a += 5;
13         System.out.println(a); //15
14 
15         int b = 10;
16         b %= 3;
17         System.out.println(b); //1
18         //复合赋值运算会隐含强制类型转换
19         short c = 10;
20         c += 5;//执行时,会执行short+int,结果为int,然后再将int强制类型转换为short
21         System.out.println(c);
22 
23         //比较运算符:
24         System.out.println(10 > 5);
25         System.out.println(10 < 5);
26         System.out.println(10 == 9);
27         System.out.println(10 != 9);
28 
29         //逻辑运算符:与或非
30         //与&&和或||的短路逻辑,如果可以根据左边得到判断的结果,则右边的代码将不再执行,可以节省部分性能
31         int m = 10;
32         int n = 5;
33         int l = 1;
34         if (m > 20 && (++n) > 1) {
35             l++;
36         }
37         System.out.println(m + ":" + n + ":" + l);//10:5:1,说明m>20判断完后就不再执行后面的判断
38         if (m < 20 || (++n) > 1) {
39             l++;
40         }
41         System.out.println(m + ":" + n + ":" + l); //10:5:2,说明判断完m<20后就不再执行后面的判断
42 
43         //三元运算符,需要三个数据才能操作的运算符
44         int x = 10;
45         int y = 5;
46         int z = x > y ? x : y;
47         System.out.println(z); //10
48 
49         //必须同时保证等号左侧数据类型和右侧运算的数据类型一致
50         //int num=3>4?2.5:10; 编译不通过
51 
52         //三元的运算结果必须被使用
53         //x>y?x:y; 编译不通过
54 
55 
56     }
57 }

运算符优先级

关于这一块,参考自己博客:https://www.cnblogs.com/youngchaolin/p/11294056.html

方法

方法定义里面不能嵌套定义方法。

 1 package com.boe;
 2 
 3 /**
 4  * 方法,方法里不能再定义方法
 5  */
 6 public class Method {
 7 
 8     public static void main(String[] args) {
 9         int myMoney = 10000;
10         int myHouseCount = 0;
11         //方法调用
12         marry(myMoney, myHouseCount);
13 
14     }
15 
16     //自定义一个方法,方法名使用小驼峰命名规则
17     public static void marry(int money, int housecount) {
18         if (money >= 1000000 || housecount >= 1) {
19             System.out.println("可以继续谈");
20         } else {
21             System.out.println("分手吧!");
22         }
23     }
24 
25 }

Java9的Jshell

Java9中添加了Jshell的功能,可以在终端像python一样,一句一句的写代码并执行,这个是针对轻量级的代码使用的,不需要建类就可以运行得到结果,会比较方便。

 1 package com.boe;
 2 
 3 public class JShell {
 4     /**
 5      * Java 9中添加了Jshell的功能,类似于python的解释器,可以一句一句的执行代码,可以在终端写java代码直接运行
 6      * 另外java中编译器有两点优化:
 7      * (1)byte,char,short在赋值时,如果右侧值没有超过范围,会自动在值前面加(byte),(char),(short)进行强转,
 8      * 如果右侧超过了左侧的范围,编译器直接报错
 9      * (2)byte,char,short类型变量右侧赋值如果全是常量,那么会将常量的计算结果直接赋值给左侧变量,如果右侧有变量则编译不通过,因为
10      * byte,char和short三者进行运算都会自动向上转型为int。
11      */
12 
13     public static void main(String[] args) {
14         byte a=10; //自动在10前面加上了(byte)10
15         byte b=10;
16 
17         //byte d=128; 128超过了byte范围,直接编译报错
18 
19         char chacter=97; //97没有超过char的范围,会自动在前面加上(char)97,对应字母a
20         System.out.println(chacter); //a
21 
22         //byte c=a+b; 编译不通过,a+b的结果为int,而数据类型为byte,因此报错。
23         //但是下面的情况却可以计算,这是一种优化
24         byte c=10+10;
25         System.out.println(c);// 20 如果右侧是常量,则结果不报错,如果右侧全是常量,则编译器会直接计算出值,并将右侧常量的值赋值给左侧变量
26 
27 
28     }
29 }

条件语句

条件语句中如果代码块只有一句,大括号可以省略不写。

 1 package day03;
 2 
 3 import java.util.Scanner;
 4 
 5 public class IFElse {
 6 
 7     public static void main(String[] args) {
 8         /*if语句*/
 9         //step1:定义两个变量
10         int getOn=0;//上车人数=10人
11         int getOff=0;//下车人数=5人
12         //Step2:火车开过来了
13         System.out.println("火车开过来了:呼呼呼呼呼...");
14         //Step3:只要遇到条件判断,就使用if结构
15         //如果(上车人数>0或者下车人数>0){ 则停车...}
16         if(getOn>0||getOff<0){
17         System.out.println("火车停车→上下乘客→再开车");
18         }
19         System.out.println("火车开走了");
20         
21         /*多分支:if-else*/
22         //step1:定义两个变量
23         boolean hg=false;//有黄瓜
24         boolean hlb=false;//有胡萝卜
25         //step2:判断
26         //如果有黄瓜,就输出“黄瓜沙拉”
27         if(hg){
28         System.out.println("黄瓜沙拉");    
29         }
30         //否者
31         else{
32                 //如果有胡萝卜,就输出“胡萝卜沙拉”
33                 if(hlb){
34                 System.out.println("胡萝卜");    
35                 }
36                 //否者,就输出“不吃了“
37                 else{
38                 System.out.println("不吃了");    
39                 }
40         }
41         
42     /*多分支:else-if语句*/
43     //step1:声明成绩变量int score=0;
44     int score=0;
45     //step2:获得用户输入的成绩
46     Scanner sc=new Scanner(System.in);
47     System.out.println("请输入成绩:");
48     score=sc.nextInt();
49     //step3:根据用户输入的成绩,输出对应等级:A,B,C,D
50     //第一个判断条件
51     //step3.1如果成绩小于0或者大于100,直接输出"成绩无效"
52     if(score<0||score>100){
53     System.out.println("成绩无效");    
54     }
55     //step3.2 :否则,如果成绩>=90,输出A    
56     /*              否则,如果成绩>=80,输出B
57      *              否则,如果成绩>=60,输出C
58      *              否则,所有条件都不满足,就输出D
59      */
60     else if(score>=90){
61     System.out.println("A");
62     }
63     else if(score>=80){
64     System.out.println("B");
65     }
66     else if(score>=60){
67     System.out.println("C");    
68     }
69     else{
70     System.out.println("D");    
71     }
72     
73     /*多分支:switch-case*/
74     //switch语句可以根据一个整数表达式的不同值,选择不同的程序入口
75     //只能对整数和字符串进行判断
76     //step1:定:1个变量,保存变量
77     char L='B';//char类型,本质上是一个整数
78     switch(L){//L的整数值是65
79     case 'A'://如果等于'A'
80                 //就输出"出众"
81         System.out.println("出众");
82         break;
83     case 'B'://如果等于'B'
84                 //就输出"优秀"
85         System.out.println("优秀");
86         break;
87     case 'C'://如果等于'C'
88                 //就输出"及格"
89         System.out.println("及格");
90         break;
91     case 'D'://如果是'D'
92                 //就输出"不及格"
93         System.out.println("不及格");
94         break;
95     //使用break后才能真正实现分支
96     }
97     }
98 
99 }

 

循环结构

while循环,do-while循环:

 1 package day04;
 2 
 3 import java.util.Scanner;
 4 
 5 public class Loop {
 6 
 7     public static void main(String[] args) {
 8         /*while循环:第一次循环就需要判断条件时使用*/
 9         //step1:初始化循环变量
10         int round=0;//用一个变量记录转的圈数
11         double money=0;//用一个变量记录转的圈数
12         //step2:定义循环条件:必须交一块钱,圈数<3,就继续,否则就退出
13         while(money==1&&round<3){
14         //step3:循环体
15         System.out.println("转一圈");
16         //step4:循环变量都要朝着退出循环的趋势不断变化
17         round++;
18         if(round==2){
19         System.out.println("停电了");
20         break;//中断并退出循环
21         }
22         }
23         System.out.println("去玩别的了");
24         /*break用于循环中退出当前循环*/
25         
26         /*猜数字*/
27         //1.定义循环变量
28         int num=(int)(Math.random()*10+1);//保存程序随机生成的一个整数
29         //范围为1<=num<11;因此可以取到1到10,但是取不到11,因为范围小于11
30         /*如何获得一个随机的整数
31          * 使用Math.random(),返回0<=x<1;
32          * 方法返回任意min~max之间
33          * (int)(Math.random()*(max-min+1)+min)
34          */
35         int guess=-1;//保存用户输入的整数
36         //只要获得用户输入的数据,就使用Scanner
37         Scanner sc=new Scanner(System.in);
38         //2.Process阶段
39         //用让用户反复玩游戏,不确定次数,就得使用while循环
40         //2.1循环变量:num保存随机数,guess保存用户输入
41         //2.2循环条件:
42         //退出的情况:guess==0或则用户猜对了guess==num
43         //相反,循环的条件为:guess!=0,并且guess!=num
44         while(guess!=0&&guess!=num){
45         //2.3循环体
46         //先获得用户输入的整数
47         System.out.println("请输入一个整数:");
48         guess=sc.nextInt();
49         //然后比较guess和num,使用三目运算
50         /*
51          *如果guess==0,就返回"下次再来" 
52          *如果guess>num,就返回"大了"
53          *如果guess<num,就返回"小了"
54          *否则                      猜对了
55          */
56          System.out.println(
57          guess==0?"下次再来":
58          guess>num?"大了":
59          guess<num?"小了":
60                          "猜对了!!");
61     }
62         
63     /*do-while循环:不管条件是否成立,至少要执行一次循环时使用*/
64     //step1:初始化循环变量
65     int round1=0;//用一个变量记录转的圈数
66     double money1=1;//用一个变量记录转的圈数
67     //step2:定义循环条件:必须交一块钱,圈数<3,就继续,否则就退出
68     do{
69     //step3:循环体
70     System.out.println("转一圈");
71     round1++;
72     }while(money1==1&&round1<3);
73     //如果第一次判断的结果为true,do-while和while没有差别
74     //用do-while循环实现猜数字游戏
75     int num1=(int)(Math.random()*10+1);//保存程序随机生成的一个整数
76     int guess1=-1;//保存用户输入的整数
77     do{
78         //1.定义循环变量
79         Scanner sc1=new Scanner(System.in);
80         //先获得用户输入的整数
81         System.out.println("请输入一个整数:");
82         guess1=sc1.nextInt();
83         System.out.println(
84         guess1==0?"下次再来":
85         guess1>num1?"大了":
86         guess1<num1?"小了":
87                          "猜对了!!");
88     }while(guess1!=0&&guess1!=num1);
89     }
90 }

for循环:

 1 package day04;
 2 
 3 public class Loop1 {
 4 
 5     public static void main(String[] args) {
 6         /*for循环:只要变化的规律固定,优先使用for循环*/
 7         //计算从1加到100
 8         //I.定义输入变量
 9         int sum=0;//保存累加后的结果
10         int i;
11         int max=4000;//保存累加的上限,如果突破上限就退出循环
12         //P:每次得到一个整数,反复累加到变量上
13         //循环三要素
14         /*1.循环变量:整数i,i从1开始,每次累加1
15          * 2.循环条件:i<100;
16          * 3.循环体:sum+=i;
17          * 4.迭代循环变量:i++
18          * */
19          for(i=1,sum=0;i<=100;i++){
20          sum+=i; 
21          //如果累加结果sum已经超过max的上限,则退出循环
22          /*if(sum>=4000){
23          break; //用break终止循环,简单粗暴
24          }**/
25          }
26          System.out.println(sum);
27          //作用域:限定一个变量的可用范围,就是这个变量的作用域
28          //当进入一个变量的作用域时,创建变量,退出一个变量的作用域时,销毁变量
29          //for语句和其所属大括号属于同一作用域
30          
31          /*循环变量中使用continue语句*/
32          //跳过本轮循环,直接进入下一轮循环
33          //1.定义变量bao,保存包扔在哪个格子中
34          int bao=5;
35          //2.从1开始,循环跳每个格子,但是要跳过包所在的格子
36          for(int n=1;n<=10;n++){
37              if(n==bao){
38              continue;//跳过本轮循环,直接进入下一轮     
39              }
40          System.out.println("跳到"+n);    
41        
42          }
43          
44     }
45 
46 }

另外if、switch-case、while和for循环详细内容可以参考博客:https://www.cnblogs.com/youngchaolin/p/11297402.html

方法重载

方法的重载,就是为业务功能类似,参数列表不一样的情况下使用的,具体参考下面代码。

 1 package com.boe;
 2 
 3 /**
 4  * 如果方法的功能类似,只是参数列表不一样,这样没必要为不同的参数的列表写不同的方法名,会显得麻烦,这样方法的重载应用而生。
 5  * 方法重载(overload),方法名称一样,只是方法参数列表不一样,这样就是方法的重载。
 6  * 方法签名:方法名和方法参数。程序选择方法运行时,会根据参数的不同,选择不同的方法签名对应的方法来执行
 7  * 方法重载与下面的因素有关:
 8  * (1)参数个数
 9  * (2)参数类型
10  * (3)参数的多类型顺序不一样
11  * 方法重载与下面的因素无关:
12  * (1)参数名
13  * (2)方法的返回值
14  */
15 public class MethodOverload {
16 
17     public static void main(String[] args) {
18         //测试方法重载
19         System.out.println(sum(1,2));
20         System.out.println(sum(1,2,3));
21         System.out.println(sum(1,2,3,4));
22 
23     }
24     //计算两个数的和
25     public static int sum(int a,int b){
26         return a+b;
27     }
28     //计算三个数的和
29     public static int sum(int a,int b,int c){
30         return a+b+c;
31     }
32     //计算四个数的和
33     public static int sum(int a,int b,int c,int d){
34         return a+b+c+d;
35     }
36     //以上三个是方法的重载,下面的方法测试是否为方法重载,看编译是否通过
37     public static int sum(int a,double b){
38         return (int)(a+b);
39     }
40     public static int sum(double a,int b){
41         return (int)(a+b);
42     }
43     //跟参数名称无关
44     /*public static int sum(int c,int d){
45         return (int)(c+d);
46     }*/
47     //跟方法返回值无关
48     /*public static double sum(int a,double b){
49         return a+b;
50     }*/
51 
52 }

数组

数组相关内容如下,还有几个关于数组的应用,如查找数组中最值,排序,二分查找等知识,参考博文:https://www.cnblogs.com/youngchaolin/p/11390935.html

(1)数组的初始化

 1 package com.boe;
 2 
 3 /**
 4  * 数组是一种容器,可以存放多个同类型的数据
 5  * 特点:
 6  * (1)数组是一种引用数据类型
 7  * (2)数组当中的多个数据,类型必须统一
 8  * (3)数组的长度在程序运行期间不可以改变
 9  *
10  * 两种常用的初始化方式:
11  * (1)动态初始化(指定数组的长度)数据类型[] 数组名称=new 数据类型[数组长度]
12  * (2)静态初始化(指定数组的内容)
13  *   常规写法:数据类型[] 数组名称=new 数据类型[]{元素1,元素2,...}
14  *   省略写法:数据类型[] 数组名称={元素1,元素2,...}
15  *
16  * 动态初始化和静态初始化可以拆分成两步初始化,第一步先定义一个数组,第二步就是给这个数组赋值,但是省略写法不能分两步来走
17  *
18  * 使用建议:
19  * (1)不确定数组元素的具体内容,用动态初始化,确定数组内容就用静态
20  */
21 public class ArrayBase {
22 
23     public static void main(String[] args) {
24         //动态初始化
25         //创建一个数组,里面存放300个数据
26         int[] array1 = new int[300];
27 
28         //静态初始化
29         int[] array2 = new int[]{1, 2, 3, 4};
30         String[] array3=new String[]{"hello world","hello linux","hello python"};
31         int[] array4={1,2,3,4};
32 
33         //测试两步写
34         int[] array5;
35         array5=new int[10];
36 
37         int[] array6;
38         array6=new int[]{1,2,3,4};
39 
40         //以下编译会报错,省略写法不能分两步来写。
41         /*int[] array7;
42         array7={1,2,3,4};*/
43 
44 
45     }
46 
47 }

(2)数组创建后的默认值,根据数据类型,有不同的初始值。

 1 package com.boe;
 2 
 3 /**
 4  * 直接打印数组,得到的结果是数组对应的内存地址哈希值
 5  * <p>
 6  * 数组中的索引值,是从0开始,到(数组长度-1)为止
 7  * <p>
 8  * 使用动态初始化创建创组时,其中的元素会默认拥有一个初始值,有如下规则。
 9  * 如果是基本数据类型:
10  * (1)4种整数类型,默认为0
11  * (2)2种浮点类型,默认为0.0
12  * (3)1种字符类型,默认为'\u0000'
13  * (4)布尔类型,默认为false
14  * 注意:其实静态初始化创建数组,数组元素也有默认值,只是随后马上被大括号中的值给覆盖了
15  */
16 public class ArrayBaseOne {
17 
18     public static void main(String[] args) {
19         //静态初始化
20         int[] array1 = new int[]{1, 2, 3};
21         System.out.println(array1); //[I@61bbe9ba [代表数组,I代表整数类型,@后面的数组是十六进制数值
22 
23         double[] array2 = new double[]{12.0, 13.0};
24         System.out.println(array2); //[D@610455d6
25 
26         //访问数组元素
27         System.out.println(array1[0]); //1
28 
29         //动态初始化
30         int[] array3 = new int[4];
31         System.out.println(array3[0]);//0
32         System.out.println(array3[1]);//0
33         System.out.println(array3[2]);//0
34         System.out.println(array3[3]);//0
35         //以上动态初始化后,得到的初始值默认是0
36 
37         double[] array4 = new double[2];
38         System.out.println(array4[0]);//0.0
39 
40         boolean[] array5 = new boolean[2];
41         System.out.println(array5[0]); //false
42 
43         char[] array6 = new char[2];
44         System.out.println(array6[0]);//
45     }
46 }

(3)数组的长度,数组的遍历,数组的比较,数组的反转等

  1 package com.boe;
  2 
  3 /**
  4  * 获取数组的长度,数组名称.length,得到数组的长度
  5  * 数组一旦创建,程序运行期间,长度不可以改变
  6  * 数组的遍历
  7  */
  8 public class ArrayBaseThree {
  9 
 10     public static void main(String[] args) {
 11         //获取数组的长度
 12         int[] array = new int[]{1, 4, 56, 7, 6, 89, 5, 6, 3, 5, 6, 7};
 13         int length = array.length;
 14         System.out.println("数组的长度为:" + length);
 15 
 16         //数组长度在程序运行期间不可以改变
 17         int[] array1 = new int[3];
 18         System.out.println(array1.length);//3
 19         array1 = new int[5];
 20         System.out.println(array1.length);//5
 21         /**
 22          * 打印结果看好像数组的长度发生了改变,其实是数组的内存地址发生了改变,所指向的数组不一样,
 23          * 但实现上,在堆内存中开辟的两个数组的长度是不变的,一个为3一个为5
 24          */
 25 
 26         //数组遍历,使用for循环,IDE快捷生成方式array.fori
 27         for (int i = 0; i < array.length; i++) {
 28             System.out.println(array[i]);
 29         }
 30 
 31         //如何求出一个数组中的最大值
 32         int max = array[0];
 33         for (int i = 0; i < array.length; i++) {
 34             if (array[i] > max) {
 35                 max = array[i];
 36             }
 37         }
 38         //比较完后打印
 39         System.out.println("数组的最大值为:" + max);
 40 
 41         //数组元素的反转,就是将数组原封不动的颠倒过来
 42         System.out.println("=======创建新数组=======");
 43         int[] newArray = new int[array.length];//创建一个新数组
 44         for (int i = 0; i < array.length; i++) {
 45             newArray[newArray.length - 1 - i] = array[i];//利用下标之和为数组长度-1
 46         }
 47         //打印反转前后的数组
 48         for (int i = 0; i < array.length; i++) {
 49             System.out.print(array[i] + " ");
 50         }
 51         System.out.println();//换行
 52         for (int i = 0; i < newArray.length; i++) {
 53             System.out.print(newArray[i] + " ");
 54         }
 55 
 56         //同样数组反转,不创建新数组,只准使用原来数组的情况
 57         System.out.println();
 58         System.out.println("=======不创建新数组=======");
 59         //反转前打印
 60         for (int i = 0; i < array.length; i++) {
 61             System.out.print(array[i] + " ");
 62         }
 63         System.out.println();
 64         //反转
 65         for (int i = 0; i < array.length; i++) {
 66             //终止循环条件,考虑到了数组长度奇数偶数的情况
 67             /*if (array.length % 2 == 0) {
 68                 if (i == array.length / 2) {
 69                     break;
 70                 }
 71             } else {
 72                 if (i == (array.length - 1) / 2) {
 73                     break;
 74                 }
 75             }*/
 76             //另外一种判断是,当左边索引小于右边就可以更换,否则终止
 77             if (i >= array.length - 1 - i) {
 78                 break;
 79             }
 80             //调换array[i]和array[array.length-1-i]的元素
 81             int buf;
 82             buf = array[i];
 83             array[i] = array[array.length - 1 - i];
 84             array[array.length - 1 - i] = buf;
 85         }
 86         //反转完后打印
 87         for (int i = 0; i < array.length; i++) {
 88             System.out.print(array[i] + " ");
 89         }
 90 
 91         System.out.println();
 92         System.out.println("=======不创建数组,更加简洁的写法=======");
 93         //反转前打印
 94         for (int i = 0; i < array.length; i++) {
 95             System.out.print(array[i] + " ");
 96         }
 97         System.out.println();
 98         //反转
 99         for (int minIndex = 0, maxIndex = array.length - 1; minIndex < maxIndex; minIndex++, maxIndex--) {
100             int buf;
101             buf = array[minIndex];
102             array[minIndex] = array[maxIndex];
103             array[maxIndex] = buf;
104         }
105         //反转后打印
106         for (int i = 0; i < array.length; i++) {
107             System.out.print(array[i] + " ");
108         }
109     }
110 }

控制台输出数组反转结果:

(4)数组作为方法参数,传递的是内存地址值。

 1 package com.boe;
 2 
 3 /**
 4  * 数组作为方法中的参数,传递的其实是数组的内存地址值
 5  */
 6 public class ArrayBaseFour {
 7 
 8     public static void main(String[] args) {
 9 
10         int[] arr = new int[]{30, 40, 1000};
11         System.out.println(arr);//main方法中打印数组内存地址哈希值
12         printArray(arr);
13 
14     }
15 
16     //自定义方法,打印输出数组
17     public static void printArray(int[] array) {
18         System.out.println(array);//自定义方法中打印数组的内存地址哈希值
19         for (int i = 0; i < array.length; i++) {
20             System.out.println(array[i]);
21         }
22     }
23 
24     /**
25      * 执行后发现,main方法中打印的内存地址和方法中打印的一样,说明数组作为参数,传递的其实不是值,而是内存地址值
26      */
27 }

控制台输出结果,其中"["代表数组,"I"代表数据类型为Int,@跟邮箱类似,代表后面是地址,最后@后面的数值为数组内存地址哈希值。

(5)数组作为方法返回值,传递的也是数组的内存地址值。

 1 package com.boe;
 2 
 3 /**
 4  * 数组作为方法返回值,返回的也是数组的内存地址值
 5  */
 6 public class ArrayBaseFive {
 7 
 8     public static void main(String[] args) {
 9         int[] mainArray=getCalculate(1,2,4);
10         System.out.println("main方法中数组的内存地址哈希值:"+mainArray);
11 
12     }
13     //自定义一个方法,返回一个数组
14     public static int[] getCalculate(int a,int b,int c){
15         //计算和并返回
16         int sum=a+b+c;
17         //计算乘积并返回
18         int product=a*b*c;
19         //当需要返回两个值得时候,可以使用数组装载返回
20         int[] array=new int[2];
21         System.out.println("方法中数组的内存地址哈希值:"+array);
22         array[0]=sum;
23         array[1]=product;
24         //返回
25         return array;
26 
27     }
28 }

控制台输出结果:

(6)数组与内存

 1 package com.boe;
 2 
 3 public class Memory {
 4     /**
 5      * 内存的划分
 6      * (1)栈(stack):存放的都是方法中的局部变量,局部变量常见的有方法中的参数,方法体{}中的变量,一旦超出作用域就会从栈内存中消失
 7      * (2)堆(heap):凡是new出来的东西,如对象,就保存在堆中,堆内存中的东西都有一个地址值,为16进制,堆内存中的数据,都有默认值。
 8      * (3)方法区(method area):存储编译后的.class文件,其中包含方法相关的信息,今后学习的反射就会调用方法区中的信息
 9      * (4)本地方法栈(native method stack):与操作系统相关
10      * (5)寄存器(pc register):与CPU相关
11      */
12 
13     public static void main(String[] args) {
14         int[] array=new int[3];
15         System.out.println(array);
16         System.out.println(array[0]);
17         System.out.println(array[1]);
18 
19         //对数组中的元素重新进行赋值
20         array[0]=13;
21         array[1]=14;
22         //重新打印
23         System.out.println(array);
24         System.out.println(array[0]);
25         System.out.println(array[1]);
26     }
27     /**
28      * 执行完上述方法后发现,数组的内存地址没变化,只是数组内容发生了变化,执行这个方法的过程中内存中发生了什么呢?
29      * 1 首先需要在内存中开辟栈堆和方法区三块区域,为方法执行做准备
30      * 2 java代码编译后都是.class文件,其中包含代码方法的关键信息会存在方法区,如上面例子中public static void main(String[] args)这个头会保存在方法区
31      * 里面包含方法的关键信息,如方法名,参数类型,返回值类型等。
32      * 3 程序运行都是从main方法开始进入的,所以会从方法区寻找方法名为main的,找到后将关键信息main(String[] args)加载到栈内存中,并为其开辟一块区域执行方法,这个
33      * 过程就是进栈。
34      * 4 main方法执行后,发现需要创建一个int[]数组,int[] array为局部变量保存在栈内存中,右边new方法创建的是对象,保存到堆内存中,其根据数组大小开辟了一块内存区域,
35      * 这块内存区域有一个内存地址,这个内存地址,就保存在了array局部变量里。
36      * 5 想打印数组元素,会先通过数组的内存地址,找到堆中对应的对象,然后通过数组索引来找到对应的值
37      * 6 如果对数组中的值进行了改变,只是改变了堆中数组元素的值,但是不会改变数组对象的内存地址
38      * 7 因此最后再次打印时,内存地址还是原来的内存地址,但是对应的数组元素值却发生了变化。
39      */
40 }
posted @ 2019-06-13 10:46  斐波那切  阅读(735)  评论(0编辑  收藏  举报