这章是来讲Java的基本程序设计结构
一先看一个最简单的Java应用程序
public class FirstSample {
public static void main(String[] args) {
System.out.println(‘我会到阿里工作“);
}
}
(1)首先Java区分大小写的,如果发生大小写编写错误,那么它不会执行(如main改成Main)
(2)public 是访问修饰符,控制其他程序对这段代码的访问级别
(3)class·表明Java程序中的全部内容都包含在类中,这边需要把类作为一个加载程序的容器,程序逻辑定义了应用程序的行为
(4)class后面紧接类名,类名必须以字母开头,后面可以和字母和数字结合,但是不能使用Java的保留字(命名规则:类名以大写字母开头,如果名字以多个字母组成,每个单词的首字母需要大写,这也叫骆驼命名法)
(5)源代码的文件名必须和公共类的名字相同,并以.Java作为扩展名
(6)运行已经编译的程序,Java虚拟机将从指定类的main方法开始执行,所以为了代码能够执行,类中必须含有一个main方法,用户也可以自定义方法添加到类中,并在main方法中去使用它(main方法必须是用public修饰)
(7)对于{}这个叫做块,任何方法的代码都是以”{“开始,”}“结束
(8)main方法必须是静态的,void代表没有返回值,如果Java应用程序正常退出,那么它的退出代码为0,如果想要终止程序时返回其他代码,那么就需要调用System.exit方法
(9)在Java中每个句子都必须以分号作为结束,回车不是语句的结束标志,所以可以把一条语句写在多行上面
(10)这里使用了System.out对象,并调用了它的println方法,点号(.)用于调用方法
(11)Java采用双引号分隔字符串
(12)Java的方法中可以没有参数,也可以有一个或是多个参数,不带参数的println方法只打印一个空行
二注释
(1)使用//,其注释内容从//到本行结尾
(2)使用/* 和*/将一段比较长的注释括起来
(3)最后的/** 开始以*/结束,可以自动生成文档
注意:/* */不能嵌套,也就是说不能简单地把代码用/* 和*/括起来作为注释,因为这段代码本身可能也有一个*/
三数据类型
Java是一种强类型语言,说明它必须为每一个变量声明一种类型
Java有八种基本类型,其中有4种整型,2种浮点型,一种用于Uniocide编码的字符类型char,一种用于表示真值的boolean
注意:java中有一个能够表示任意精度的算术包,我们经常叫为“大数值”,但是它并不是一种Java类型,而是一个Java对象
(1)整形:用于没有小数的数值,可以是负数
int :4字节
short:2字节
long: 8字节
byte : 1字节
int经常用,但是超过20亿就使用long,byte和short用于特定的场景,如底层的文件处理和需要控制占用存储空间的大数组
在Java中,整型的范围于运行代码的机器无关,Java程序必须保证在所有的机器上都能得到相同的运行结果,所以各种数据类型的取值范围必须固定
长整形数值的后面有一个后缀 L,十六进制数值有一个0x或是0X的前缀,八进制有一个0前缀,从Java7后使用0b或是0B就可以写入二进制,还可以在数字下面写下划线,这种下划线让人容易看清,Java编译器可以去除这种下划线如1_000_000表示一百万
java没有任何无符号的形式int long short byte
二浮点类型
float :4字节
double : 8字节
double是float类型的两倍,所以称为双精度数值,float类型后面有F或f,没有后缀的话都认为是double类型,也可以在双精度的后面添加D后缀
下面有三个值用于表示溢出和出错
1.正无穷大(Double.POSITIVE_INFINITY)
2.负无穷大(Double.NEGATIVE_INFINITY)
3.NaN(不是一个数字) 当求负数的平方根时的结果(Double.NaN)
要检测一个特定值是不是属于Double.NaN,应该使用Double.isNaN(x)
浮点类型不适合于无法接受舍入误差的金融计算,如果数值中不允许有任何舍入误差,那么就应该使用BigDecimal类
三char类型
char原是用于表示单个字符,不过现在有一些Unicode字符需要两个字符
char类型的字面量值要用单引号跨起来 ' ',如'A'就是65对应的字符常量,它与“A”不同,后面指的是A这个字符串。char也可以表示16进制,范围从\u0000到\Uffff,还有一些转义字符,这些字符可以出现在加引号的字符字面量或字符串中,
转义字符\u还可以出现在加引号的字符常量和字符串之外(而其他所有转义字符不可以),下面是特殊的转义字符
\b 退格
\t 制表
\n 换行
\r 回车
\" 双引号
\' 单引号
\\ 反斜杠
对于转义字符来说,它会在解析代码之前就得到处理,如"\u0022 + \u0022" 实际上等于" " + " " ,\u0022解析之前会转换成 "(双引号)
注意:我们需要注意在注释中是不是有\u的存在
四boolean类型
这个类型有两个值,一个是false,一个是true,用来表示逻辑条件,整形和布尔值之间不能进行转换
五变量
在Java中,每一个变量都有一个类型,在声明变量的时候,变量的类型位于变量名之前,如下面
double salary;
int vacationDays;
(1)每一个声明都必须以分号作为结束
(2)变量名必须以字母开头并由字母或是数字构成
(3)变量名所有的字符都是有意义的,而且大小写敏感
(4)$尽管是一个合法的字母但是最好不要去使用它,它只用于Java编译器或其他工具生成的名字中,也最好不要使用Java的保留字作为变量名
(5)变量名取名时可以是m加类型名
六变量初始化
(1)声明一个变量后必须使用赋值语句进行显式初始化,千万不要使用没有初始化的变量
(2)要对一个变量进行初始化 就应该 vacation = 12这样子
(3)在Java中变量的声明尽可能地靠近变量第一次使用的地方
七在Java中利用final关键字指示常量
final这个字表明这个变量只能被赋值一次,一旦被赋值就不能被修改了,常量名经常是大写
在Java中经常希望某个常量可以在一个类的多个方法中使用,那么就通常将这些常量称为类常量
public static final double CM_PRE_INCH = 2.21;
类常量的定义在于main方法的外部,因此同一个类的其他方法都可以去使用这个常量
八运算符
算术运算符+ - * / 而对于/来说,当参与/运算的两个数字都是整数的时候,那么就表示整数除法,不然就是表示浮点除法,%这个表示整数的求余
注意:整数被0除将胡会产生一个异常,而浮点数被0除将会得到无穷大或是NaN的结果
使用strictfp 会使用严格的浮点计算
(1)在Math类中,它包含了各种各样的数学函数,如计算一个数值的平均值可以使用sqrt(x),这个方法处理的不是对象,它也被称为静态方法
(2)在Java中没有幂运算,因此需要借助y = Math.pow(x,a)方法,这样就可以把y设置为x的a次幂
(3)floorMod方法的目的是为了解决一个长期存在的整数求余的问题,就像计算一个时钟的位置,运用floorMod(position+adjustment,12)总会得到一个0~11的数
(4)java还提供了两个表示常量 Math.PI和Math.E
注意:在Math类中,为了达到最块的性能,所有的方法都使用计算机浮点单元的算法,如果得到一个完全可以预测的结果比运行速度还重要的话,那么就应该使用StrictMath类,它可以确保在所有平台上得到相同的结果
九.数值类型转换
我们经常需要把一种数值转换成另一种数值,两个不同类型之间进行运算时,会先转换为同一种类型然后再计算,它的转换总是向比较大的类型变换,其中有一些转换会导致信息丢失,就像int 转为float类型,123456789变成1.2345679E8同样大小,但是丢失了一定的精度
十.强制类型转换
从大的类型转换为小的类型就需要强制类型转换了,如下面
double x = 9.991;
int xn = (int)x;
这样变量的值就是9,强制转换通过截断小数部分将浮点值转换为整形,如果想要对浮点数进行摄入运算,以便得到最接近的整数,那么就需要使用Math.round()方法
double x = 9.991;
int xn = (int)Math.round(x);
这样就得出变量xn的值为10,调用这个方法也需要使用强制类型转换,原因是因为round返回的结果是long类型,由于存在信息丢失的可能性,所以就需要使用显示的强制类型转换
注意:如果将一种类型转换为另一种类型,而又超出了目标类型的表示范围,那么它可能就会变成另一个不同的值
如果需要将布尔类型转换为数值类型,可以使用下面的表达式
b?1:0
十一.可以再赋值中使用二元运算符,如下面
x +=4;等于x = x + 4;
(正常将运算符放在=号的左边,如*=)如果运算符得到一个值,其类型与左侧操作符的类型不同,那么就会发生强制类型转换
如x是一个int,下面
x +=3.5;是合法的,它将会把x设置为(int)(x+3.5);
(1)自增,自减符
int n =12;
n++;//这是自增加1变成13 (因为这些运算符会改变变量的值,所以他们的操作符不能是数值,就像4++这个就不是合法的语句)
这种符号有两种形式,一种是前缀(也就是先完成加1再使用变量的值,而后缀是先使用变量的值然后再加1)
建议:不要使用这种形式,容易让人迷惑
(2)关系和boolean运算符
要检测相等性,可以使用两个等号 == ,不相等 !=
&& 短路与,确定表达式的值,那如果第一个操作符已经第二个操作数就不用计算
|| 短路或,确定表达式的值,那如果第一个操作符已经第二个操作数就不用计算
! 逻辑非
三元运算符 ?:,如condition ? exprission : exprission,如果表达式为true,那么值就是第一个表达式的值,不然就是第二个表达式的值‘
(3)位运算
在处理整形类型的时候,我们可以直接对组成整形数值的各个位完成操作,这就意味可以用掩码技术得到整数的各个位
位运算包含 :&("and") |("or") ^("xor") ~("not")
上面那些位按照位模式处理,如果n是一个整数变量,而且用二进制表示的n从右边数第四位为1 那么
int fourthBitmap = (n&0b1000)/0b1000就·会·返回1,不然就会返回 0
使用&并结合使用2的幂可以把其他位隐掉
注意:在布尔值上,& 和 | 运算符也会得到一个布尔值,这种运算和上面的 && 和 || 很相似,但是它不会采用“短路方式”,也就是第一个式子对了,第二个也会执行
>>和<<表示将位模式左移和右移,需要建立位模式来完成位掩码时这两个运算符会很方便
最后>>>运算符会用0填充高位,这与>>不同,它会用符号位填充高位,不存在<<<符号
警告:移位符的右操作数要完成模32的运算,除非左操作数是long类型,不然此时1<<35等于1<<3
(4)运算符级别
对于级别这个最好建议使用()而不是去记住各种级别,这样方便别人看代码
(5)枚举类型
枚举类型包含有限个命名的值
enum Size{SMALL,MEDIUM,LARGE,EXTRA};
现在就可以声明这种类型的变量
Size s = Size.MEDIUM;//这个变量只能存储这个类型声明中给定的某个枚举值,或是null值
(6)字符串
用双引号括起来的字符串都是String的一个实例
String e = " ";
String greeting = "hello";
String s = greeting.substring(0,3);//可以得到一个"hel",第二个参数是不想复制的第一个位置,这个方法也容易计算子串的长度
1.对于字串,可以使用String类的substring方法
2.拼接,在Java语言中,它允许使用 + 号来连接两个字符串
String ex = "exp";
String pgn = "pdn";
String message = ex + pgn;
上面就把exppdn赋给了变量message
注意:当一个字符串和一个非字符串的值进行拼接,那么后者会转换为字符串,任何一个Java对象都可以转换为字符串
3.如果需要把多个字符串放在一起,那么就可以用一个定界符分隔,使用join方法
String all = String.join("/","S","M","L");//这样就有了S/M/L/XL
(7)不可变的字符串
对于String,他没有提供修改字符串的方法,如果想要把"helio"改为"help!",那么就可以先提取需要的字符串然后再拼接上要替换的字符串
String greeting = "hello";
greeting = greeting.substring(0,3) + "p!";
java把String对象称为不可变字符串,如同数字3永远是数字3,不能去改变
不可变字符串有一个优点,那就是编译器可以让字符串共享(可以想象将各种字符串存放在公共的存储池中,字符串变量指向存储池相应的位置,如果复制一个字符串变量,原始字符串和复制的字符串共享相同的字符),Java的设计者认为共享带来的高效率胜过拼接,提取字符串所带来的效率,这是因为在程序中很少会去修改,而是往往需要对字符串进行比较
(8)检测字符串是不是相等
s.equal(t);
如果相等就返回true,不然就返回false,注意s与t可以是字符串变量也可以是字符串字面量
如果想检测字符串是不是相等,而不区别大小写,那么就可以使用下面的
"Hello".equalsIgnoreCase("hello");
注意:一定不要使用 == 来检测两个字符串是不是相等,因为这个运算符只能确定两个字符串是不是放在同一个位置上,如果放在同一个位置上,那么一定相等,但是完全可能将内容相同的多个字符串的拷贝放置在不同的位置上面去
如:if(greeting.substring(0,3) == "Hel");//可能是错误的
如果虚拟机始终将相同的字符串共享,那么就可以使用 == 运算符来检测是不是相等,但是实际上只有字符串常量是共享的,而 + 和 substring等操作产生的结果不是共享的
(9)空串和Null串
空串""是长度为0的字符串,它是一个Java对象,有自己的长度(0)和内容(空)可以调用下面的代码检查一个字符串是不是为空
if(str.length() = 0)或if(str.equals(""))
String变量还可以存放一个特殊的值,名为null,这表示没有任何对象与该变量关联,要检查一个变量是不是为null,使用下面的代码
if(str == null)
有时要检查一个字符串既不是null也不为空串,也不是空串,这种情况需要使用下面的代码
if(str!=null&&str.length()!=0)
首先需要检查str不为空,因为在一个null值上面使用方法会出现错误
(10)码点与代码单元
Java字符串由char序列组成,char数据类型是一个采用UTF-16编码表示Unicode码点的代码单元,大多数常用的Unicode字符使用一个代码单元就可以,而辅助字符需要使用一对代码单元
leng方法将返回采用UTF-16编码表示的给予字符串所需要的代码单元数量
int n = greeting.length();
想要得到实际的长度,也就是码点的数量,可以调用
int cpCount = greeting.codePointCount(0.greeting.length());
返回位置的代码单元
char first = greeting.charAt(0);
想要得到第i个码点
int index = greeting.offsetByCodePoint(0,i);
int cp = greeting.codePonitAt(index);
(11)构建字符串
有时候,我们需要由短的字符串构建成字符串,就像是按键或是来自文件中的单词,采用字符串连接的方式达到这个目的的效率比较低,每一个构建都会创建一个新的String对象,又耗时又浪费空间,此时使用StringBuilder类就可以避免这个问题的发生
首先先构建一个空的字符串构建器
StringBuilder builder = new StringBuilder();
每次要添加一部分内容的时候,就调用append()
builder.append(ch);
在需要构建字符串的时候就调用toString()方法,这样就可以得到一个String对象
String completedString = builder.toString();
注意:还有一个类StringBuffer,这个类效率低下,但是它允许采用多线程的方式来添加字符串或是删除字符串
(12)输入和输出
对于输出来说,我们只要调用System.out.println()方法就可以了,但是输入的话 要读取”标准输入流“System.in就没有那么简单了,想要在控制台进行输入,那么我们就需要构建一个Scanner对象并和”标准输入流“System.in关联
Scanner in = new Scanner(System.in);
现在就可以使用Scanner类的各种方法来实现输入操作了
String name = in.nextLine();//输入一行
String firstName = in.next();//读取一个单词
int age = int.nextInt();//读取一个整数
(13)格式化输出
在Java中也可以使用C语言的printf方法来格式化输出
例如 System.out.printf("%8.2",x);//表示可以用8个字符的宽度和小数点后两个字符的精度去打印x此时的8个字符包含小数点和小数点后面的数
在printf中,可以使用多个参数,每一个以%字符开始的格式说明符都用相应的参数替换,格式说明符尾部的转换符将指示被格式化的数值类型:如 f表示浮点数,s表示字符串
System.out.printf("Hello,%s.Next Year,you'll be %d",name,age);
此外还可以控制格式化输出的各种标志
如System.out.printf("%,.2f",10000.0/3.0);//逗号标志增加了分组的分隔符,也就是打印出 3,333.33
还有一些需要用到时再来查找
使用s转换符可以格式化任意对象,它可以将对象转换为字符串
可以使用静态的String.format()方法来创建一个格式化的字符串,而不是打印输出
String message = String.format("hello,%s.Next year ,you'll be %d",name,age);
使用printf来格式化时间(格式化包含两个字母,以t开始,以自己需要的格式对应的字母结束)
System.out.printf("%tc",new Date());
将打印出 Mon Feb 09 18 : 05 :19 PST 2015这种格式,需要什么类型,需要自己去查找
但是从上面的格式来看,有一些格式只给出了指定日期的部分信息,例如只有月份或是年份,如果需要多次对日期进行操作才能实现对每一部分进行格式化,那么就太过笨拙了,由此,可以采用一个格式化的字符串指出要被格式化的参数索引,(索引必须紧跟在%后面,并以$终止)
System.out.printf("%1%$s, %2$tB,%2$te,%2$tY","Due date",new Date());
参数索引从1开始,%1$表示对第一个参数进行格式化(t是转换符,只有加t才可以转换为其他格式)
(14)文件的输入和输出
要想对文件进行读取,那么就需要一个用File对象构造一个Scanner对象
Scanner in = new Scanner(Path.get("myfile.txt"),"UTF-8");
如果文件名包含一个反斜杠符号,那么就要记住每个反斜杠之前需要再添加一个额外的反斜杠
"c:\\mydirectory\\myfile.txt"
在这边指定了UTF-8的字符编码,要读取一个文本文件时最好要知道它的字符编码,如果忽视字符编码,那么就会运行这个Java程序的机器的”默认编码“,这不是一个好的主意,因为在不同的机器上面运行这个程序会有不同的结果
现在就可以使用之前的Scanner的个中方法类来读取了
如果想要写入文件,那么就需要构造一个PrintWriter对象,在构造器中只要提供文件名就可以
PrintWriter out = new PrintWriter("myfile.txt","UTF-8");//如果文件不在那么就可以创建该文件,可以像输出到System.out一样使用print和printf
也可以构建一个带有字符串参数的Scanner,但是此时这个Scanner会把它解释为数据而不是文件名
正常情况下,定位文件比较烦恼,我们可以使用绝对路径,比如:"c:\\mydirectory\\myfile.txt"或是"/home/me/mydirectory/myfile.txt"
从上面来看,访问文件和使用System.out和System.in一样容易,但是如果用一个不存在的文件来构建一个Scanner或是用一个不能创建的文件名来构造一个PrintWriter,那么就会发生异常,这些异常很严重,所以我们应该告诉编译器:已经知道可能会出现”输入/输出异常“,这就需要在main方法中去用throws子句标记
(15)控制流程
和其他语言一样,Java使用条件语句和循环结构来确定控制流程
块(复合语句):指的是由一对大块号跨起来的Java语句,它确定了变量的作用,一个块可以放在另一个块中,但是不能在嵌套的两个块中声明相同的变量名,有的话会无法通过编译
条件语句:if(condition) statement
条件必须要用()跨起来
如果想要当某个条件为真时执行多条语句,那么就应该使用块语句
if(3>2) {
}
更一般的语句是:
if(){
}else{
}
else部分是可以选择的,else子句与最邻近的if构成一组
当有两个if放在一起的时候,最好使用一对括号这样会使得逻辑更加清晰
if(x<=0) {
if(x==0) sign =0;else sign = - 1;
}
1.循环语句
while(condition) statement
当条件为准备的时候就执行一个任务,false的时候就一次也不执行
对于循环多少次数,我们可以添加一个变量,然后当作是计数器,并在循环体中更新累计的数量
double balance = 0;
while(balance balance += payment; } 上面的循环体会先检查条件,如果不符合那么就连一次执行的代码都不执行,如果想要至少执行一次代码,那么就可以将条件放在后面 do{ }while(input.equal("N"));//此时只要用户回答N,那么循环就会继续执行下去 2.确定循环 for循环语句也是支持迭代的一种通用的结构,利用每次迭代之后更新的计数器或是类似的变量来控制迭代的次数 for(int i = 1;i<=10;i++){ System.out.peintln(i); } 上面的第一步是用来对计数器进行初始化,第二步是用来每次新循环执行前要检测的循环条件,第三步是要来指示如何更新计数器 注意:在循环中,检测两个浮点数是不是相等需要格外小心,因为在四舍五入的情况下,可能永远得不到精确值 在第一步中声明一个变量后,这个变量只能适合于for循环的整个循环体,如果想要在循环体之外使用这个变量,那么就需要确保这个变量是在外面声明定义的 3.多种选择语句switch语句 在处理多个语句的时候,使用if/else就会太麻烦了,此时就可以适应switch语句 Scanner in = new Scanner(System.in); System.out.print("dddd"); int choice = in.nextInt(); switch(choice) { case 1: break; case 2: break; case 3: break; default : break; } 从相比配的case开始执行,到break结束,而如果在case分支下面没有添加break语句,那么就会执行下一个case语句 ,这是相当危险的,编写时需要时时刻刻注意 case 标签可以是(1)char,byte,short,int(2)枚举常量(3)从Java7后,标签还可以是字符串常量 当在switch语句中使用枚举常量的时候,不必在每个标签中去指明枚举名 Size z = ..; switch(sz) { case SMALL: break; } 4.中断控制流程语句 尽管Java的设计者将goto作为保留字,但是实际上并没有打算在语言中去使用它,但是偶尔跳出循环是有意义的,所以增加了一个带标签的break 不带标签的break会立刻跳出本个循环 while(years<100) { if(balance>=goal) break; year++; } 提供了一种带标签的break语句,用于跳出多重嵌套的循环语句,在各层嵌套很深的循环语句中可能会发生一些不可预料的事情,此时就可能希望跳出嵌套的整个循环语句 标签必须放在希望跳出的最外层循环之前,并且必须紧紧跟着一个冒号、 read_data: while() { for(){ if(){ break read_data; } } } 此时如果代码输入有误,那么就可以通过执行带有标签的break跳转到带标签的语句块的末尾,对于任何使用了break语句的代码,都需要检测循环是不是正常结束,还是有由break跳出的 事实上,可以将标签放在任何语句中,甚至放在if语句和块语句中 continue语句 这个语句它一样可以中断正常的控制流程,continue语句将控制权转移到最内层循环的首部 while(sum System.out.print(""); n = in.nextInt(); if(n<0) continue; sum += n; } 此时如果n<0那么continue语句就会跳过剩下的部分,继续执行while语句的 也有一种带标签的continue语句,它可以使得跳转到与标签相比配的首部 (15)大数值 如果基本的整数和浮点数都不能满足需求,那么我们就可以使用java.math包中的两个类:BigInteger(任意精度的整数运算)和BigDecimal(任意精度的浮点运算),这两个类可以处理任何长度的数字序列得数值 BigInteger a = BigInteger.valueOf(100);//利用这个方法可以把普通数值变成大数值 可惜的是现在不能使用 + 和*这些运算符,应该换成add和multiple方法 BigInteger c = a.add(b); (16)数组 数组是一种数据结构,用来存储同一类型值得集合,通过一个整形下标就可以访问数组中得每一个值,如a是一个数组,那么a[i]就是下标为i的整数 在声明数组类型时,需要指出数组类型(数组元素类型然后紧紧加[])和数组的变量名 int[] a; 上面此时只声明了变量a,并没有初始化为一个真正的数组,应该使用new运算符来创建数组 int[] a = new int[100];//创建了一个可以存储100个整数的数组 数组的下标是从0开始的如上面的数组的下标是从0到99 创建一个数字数组,那么全部的元素就会初始化为0,boolean数组会初始化为false,对象数组会初始化为null(这表明这些元素还没有存放任何对象) 想要获得数组元素的个数,可以使用arrray.length属性,记住数组没有长度的方法 一旦创建了数组,那么就不能去改变它的大小,如果想要在运行过程中去扩展数组的大小,那么就需要使用数组列表(array list) 1.for each循环 Java中有一种可以用来一次处理数组中的每个元素,不必去为指定下标值而分心 for(variable : collection) statement 定义一个变量用于暂存集合中的每一个元素,并执行相应的语句 collection这一个集合表达式必须是一个数组或是一个实现了Iterable接口的类对象 for(int element : a) { System.out.println(element); } 打印数组的每一个元素(这样更加整洁也更加不容易出错,也不用担心下标值和终止值) 注意:如果想打印出数组中的全部值,那么就可以利用Array类的toString()方法,它将会返回一个包含数组元素的字符串,这些元素被放在括号里面 如Arrays.toString(a); 打印出[2,3,45,3,]这种情况 2.数组初始化和匿名数组 在Java中,他们提供了一种创建数组对象并同时赋予初始值的简写书写形式 int[] small = {2,2,3,1,4};//使用这种形式不用用new 初始化一个匿名数组 new int[]{13,24,24},使用这种方法可以不用在创建新变量的情况下重新初始化一个数组 small = new int[]{17,39,49,20}; 注解:在Java中,允许数组的长度为0,在编写一个结果为数组的方法时,如果刚好结果为空,那么这种形式就刚好有用了 ,数组长度为0和null是不一样的 3.数组拷贝 在Java中,允许将一个数组变量拷贝给另一个数组变量,这时两个变量将同时引用同一个数组 int[] luck = small; luck[2] = 12;//此时的small[2]也会是12 如果想要把数组的全部值都拷贝到一个新的数组里面,那么我们就可以使用Arrays.copyOf int[] copied = Arrays.copyOf(luck,luck.length);//第二个参数是数组的长度,我们经常用它来扩展数组的长度 4.命令行参数 我们都指定main()接收的是一个字符串数组,也就是命令行参数 如果使用下面的形式运行这个程序 java Message(类名) -g cruel world args[0] "-g" args[1] "cruel" args[2] "world" 也就是程序名没有放在args数组中 5.数组排序 如果想要对数值数组进行排序,那么我们就可以使用Arrays.sort(),这个方法使用了优化的快速排列算法 对于一个抽奖的程序的话,我们应该先准备一个数组将1到n的数放进去, int[] numbers = new int[n]; for(int i=0;i number[i] = i+1; } 然后再准备第二个数组来存放抽取出来的数值 int[] result = new int[k]; 现在我们就可以来抽取k个数值了,Math.random()将返回一个0到1之间(包含0,不包含1)的随机浮点数,然后再用n去乘于这个浮点数,那么就会得到0到n-1之间的一个数 int r = (int) (Math.random()*n); 但是现在还是不能保证不会再次抽到那个数,所以我们可以选择将数组的最后一个数值改写为number[r],然后将n减一 number[r] = number[n-1]; n--; 抽取值后,我们就可以使用sort()来进行排序,这样会使得输出的效果更加明显 Arrays.sort(result); for(int r:result) { System.out.orintln(r); } 6.多维数组 多维数值将使用多个下标来访问数组元素,它适合于表格或更加复杂的排列形式 比如这边来计算一个数值表,用来显示在不同利润下投资10000元,利息每年都拿到,然后又被投资 我们这边可以使用一个二维数组来存储这些信息,这个数组先命名为balance 声明一个二维数组 double[][] balances; 在调用new对对多维数组进行初始化之前不能使用它,可以先这样初始化 balancs = new double[n][d]; 如果知道了数组元素,那么就可以直接使用简化的书写形式 int[][] magicAquard = { {13,24,42}, {37,29,39}, {29,78,89} } 一旦数组已经被初始化了,那么我们就可以利用两个方括号来访问每一个元素了,如balance[i][j]; 在这里我们使用一个一维数组来存放利润,一个二维数组来存放余额,一维是年度,一维表示利润 最开始用初始余额来初始化这个数组的第一行 for(int j=0;j balance[0][j] = 10000; } 然后就可以按照下面来计算其他行 for(int i =1;i for(int j =0;j double oldbalance = balance[i-1][j]; double interest = ....;//得到的利息 balance[i][j] = oldbalance + interest; } } for each循环语句不能自动处理二维数组,它是按照行,也是一维数组来处理的,要访问二维数组的数据,需要使用两个for for(double[] row:a) for(double d:row) { } 想要快速地打印一个二维数组,那么可以调用System.out.println(Arrays.deepToString(a)); 输出格式为 : [ [16,28,29],[381,291], [23,21] ] 7.不规则数组 从上面来看的话,Java的数组和其他数组好像没有太大的区别,但实际上是有区别的,Java实际上是没有多维数组的,只有一维数组,多维数组被解释为“数组的数组” 如前面的balances数组实际上是一个包含10个元素的数组,而每个元素又是一个由6个浮点数组成的数组 表达式balance[i]表示的是引用第i个数组 由于可以单独存取数组的某一行,所以来让两行交换 double[] temp = balance[i]; balance[i] = balance[i+1]; balance[i+1] = temp;