原文地址:docs.oracle.com/javase/tuto…html
正如咱们上一节中所学,对象将它的状态存储在"字段(fields)"中java
int cadence = 0;
int speed = 0;
int gear = 1;
复制代码
"何为对象?"中向您介绍了“字段(fields)”,可是您可能会存在一些疑问,例如:命名"字段(fields)"的规则和约定是什么?除了int,还有一些什么数据类型?字段声明时必须初始化吗?若是没有显示初始化,它们具备默认的值吗?本节课咱们将探索这些问题的答案,可是在这以前,下面是您必须首先注意的一些技术区别。在Java编程语言中,术语“字段(fields)”和“变量(Variables)”都被采用,对于新开发人员来讲,这是一个常见的困惑源,它们一般指代的彷佛是同一个事物。git
Java编程语言定义了如下几种变量:编程
实例变量(非静态字段):技术上来讲,对象将各自的状态存储在“非静态字段”中,也就是说,声明字段时没有指定static关键字。非静态字段也称为实例变量,由于他们的值在每一个类的实例中(或者说:在每一个对象中)都是不同的。一辆自行车的当前速度与另外一辆自行车的当前速度无关。api
类变量(静态字段):使用静态修饰符(static)声明的任何字段称为类变量;这告诉编译器,无论这个类实例化了多少次,该变量都仅存在一个副本。对于特定类型自行车齿轮数的字段能够声明为static,这将赋予全部实例相同的齿轮数。代码段:static int numGears = 6;将建立一个静态字段,此外,能够添加关键字final来表示齿轮的数量永远不会改变。数组
局部变量:与对象将状态存储在字段中类似,方法常常将其暂时的状态存在局部变量中。声明局部变量的语法相似于声明字段(int count = 0;)。没有特殊的关键字指定其为局部变量;这彻底取决于变量声明的位置——方法的开括号和闭括号之间;所以,局部变量只对声明它们的方法可见;其余类没法访问它们。bash
参数: 在自行车类和“Hello world!”应用中您已经看到过参数的示例。回想一下main方法:public static void main(String[] args),这里,args是这个方法的参数。重要的是要记住参数老是被分类为“变量”而不是“字段”。这也适用于其余接受参数的构造方法(如构造函数和异常处理器),您将在本教程的后面学习这些并发
话虽如此,若是咱们谈论的是“通常的字段”(不包括局部变量和参数),咱们能够简单地说“字段”。若是讨论适用于“以上全部”,咱们能够简单地说“变量”。若是上下文须要区别,咱们将使用特定的术语(静态字段、局部变量等)。你可能会常常看到"成员"这个术语。字段、方法和嵌套类型统称为其成员。oracle
每种编程语言对于容许使用的命名方式都有本身的一套规则和约定,Java编程语言也不例外,变量命名的规则和约定能够总结以下:编程语言
变量名区分大小写。变量的名称能够是任何合法的标识符——不限长度的Unicode字母和数字序列,以字母,“$”符,或下划线“_”开头。然而,习惯上,变量名老是以字母开头,而不是“$”或“_”。此外,根据惯例,美圆符号字符从未使用过。您可能会发如今某些状况下,自动生成的名称将包含美圆符号,可是变量命名时应该避免使用。下划线字符也有相似的约定;虽然从技术上讲,以“_”做为变量名的开头是合法的,可是不鼓励这样作。空格是不被容许使用的。
后续字符能够是字母、数字、美圆符号或下划线字符。当为变量选择名称时,使用完整的单词而不是模糊的缩写。这样作将使您的代码更容易阅读和理解。在许多状况下,它还会使您的代码更直观;例如,名为cadence、speed和gear的字段比缩写版本(如s、c和g)更直观。还要记住,您选择的名称不能是关键字或保留字
若是您选择的名称只包含一个单词,请将该单词所有用小写字母拼写。若是由一个以上的单词组成,则将后面每一个单词的第一个字母大写。如:gearRatio、currentGear。对于static final int NUM_GEARS = 6,约定有少量变化,将每一个字母大写,而后用下划线分隔后面的单词。按照惯例,下划线字符永远不会在其余地方使用
Java编程语言是静态类型语言,这意味着全部的变量在使用前必须先声明。包括声明变量的类型和名称,正如你已经见过的:
int gear = 1;
复制代码
这样作会告诉程序存在一个名为“gear”的字段,该字段保存数值数据,初始值为“1”。 变量的数据类型决定了它可能包含的值,以及可能对其执行的操做。除了int,Java程序语言还支持其余7种基本数据类型。基本类型由语言预约义,并由保留关键字命名。不一样基本数据类型之间的值并不共享。Java支持的8种基本数据类型分别为:
byte:byte数据类型是8-bit补码表示的有符号整数。最小值为-128,最大值为127(含)。byte数据类型在大数组中节省内存时显得十分有用,在大数组中,内存的节省实际上很是重要。范围限制有助于阐明代码时能够用其代替int;变量的范围有限这一事实能够做为文档的一种形式。
short:short数据类型是16-bit补码表示的有符号整数。最小值为-32768,最大值为32767(含)。与byte同样,一样的指导原则也适用:在实际须要节省内存的状况下,您可使用short来在大数组中节省内存。
int:默认状况下,int数据类型是一个32-bit补码表示的有符号整数,最小值为-2^31,最大值为2^31-1。在Java SE 8及更高版本中,可使用int数据类型表示范围为0到2^32-1的无符号32-bit整数。使用Integer类将int数据类型用做无符号整数,更多信息见The Number Classes一节,在Integer类中添加了compareUnsigned、divideUnsigned等静态方法来支持无符号整数的算术运算。
long:long数据类型是一个64-bit补码表示的有符号整数,最小值为-2^64,最大值为2^64-1。在Java SE 8及更高版本中,您可使用long数据类型来表示范围为0到2^64-1的无符号64-bit整数。当您须要比int提供的值范围更大的值时,可使用这种数据类型。Long类还包含compareUnsigned、divideUnsigned等方法来支持无符号long的算术操做
float:float数据类型是一个单精度的32位IEEE 754浮点数,它的取值区间超出了咱们的讨论范围,可是在Floating-Point Types, Formats, and Values一节中有详细说明。与byte和short的建议同样,若是须要在浮点数的大数组中节省内存,请使用float(而不是double)。这种数据类型不该该用于存储精确的值,好比货币。为此,您须要使用java.math.BigDecimal类。Numbers and Strings中涵盖了BigDecimal和其它Java平台提供的有用的类。
double:double数据类型是一个双精度的64位IEEE 754浮点数,它的取值区间超出了咱们的讨论范围,可是在Floating-Point Types, Formats, and Values一节中有详细说明。对于包含小数的值,这种数据类型一般是默认选择。如上所述,这种数据类型永远不该该用于精确的值,好比货币。
boolean:boolean数据类型只有两个可能的值:true和false。使用此数据类型存储"真/假"条件。这个数据类型表示1-bit的信息,可是它实际占用内存的“大小”并非精肯定义的。
char: char数据类型是一个16位Unicode字符。 最小值为 '\u0000' (0),最大值为 '\uffff' (65535)
除了上面列出的八种基本数据类型以外,Java编程语言还经过Java .lang.String提供了对字符串的特殊支持。将字符串括在双引号内将自动建立一个新的字符串对象;例如: String s = "this is a string";String对象是不可变的,这意味着一旦建立,它们的值就不能更改。String类在技术上不是原始数据类型,可是考虑到该语言对它的特殊支持,您可能会这样认为。您将在Numbers and Strings中了解关于String类的更多信息
声明字段时并不老是须要赋值,编译器将为已经声明但未初始化的字段设置合理的默认值。通常来讲,根据数据类型的不一样,这个默认值将是零或null。然而,依赖这些默认值一般被认为是糟糕的编程风格
下表总结了上述数据类型的默认值:
局部变量略有不一样;编译器从不将默认值分配给未初始化的局部变量。若是没法在声明局部变量的地方初始化该变量,请确保在尝试使用它以前为其赋值。访问未初始化的局部变量将致使编译时错误。
您可能已经注意到,在初始化基本类型的变量时不使用new关键字。基本类型是构建在语言中的特殊数据类型;它们不是经过类建立的对象。字面量是值的源代码表示,直接在代码中表示,不须要计算。以下所示,能够将字面量赋值给基本类型的变量:
boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;
复制代码
若是以字母L或l结尾,整数字面量的类型为long;不然它是int类型的。建议使用大写字母L,由于小写字母l很难与数字1区分.整数类型byte、short、int和long的值能够从int字面量建立。long类型的值超出int的范围,能够从long字面量建立。整数字面值能够由这些数字系统表示:
对于通常编程,十进制系统多是您将使用的惟一数字系统。可是,若是须要使用另外一个数字系统,下面的示例显示了正确的语法。前缀0x表示十六进制,0b表示二进制:
// The number 26, in decimal
int decVal = 26;
// The number 26, in hexadecimal
int hexVal = 0x1a;
// The number 26, in binary
int binVal = 0b11010;
复制代码
若是以字母F或f结尾,浮点字面量的类型为float;不然,它的类型是double,而且能够选择以字母D或d结尾。浮点类型(float和double)也可使用E或e(用于科学表示法)、F或f(32位float字面量)和D或d(64位double字面量;这是默认值,按惯例可省略)来表示。
double d1 = 123.4;
// same value as d1, but in scientific notation
double d2 = 1.234e2;
float f1 = 123.4f;
复制代码
字符和字符串类型的字面量能够包含任何Unicode (UTF-16)字符。若是编辑器和文件系统容许,能够在代码中直接使用这些字符。若是不容许,您可使用“Unicode转义”,好比“\u0108”(大写的C)或"S\u00ED Se\u00F1or"(西班牙语中的Sí Señor)。对于char字面量,请始终使用'单引号';对于String字面量,请使用“双引号”。Unicode转义序列能够在程序的其余地方使用(例如在字段名中),而不只仅是在字符或字符串字面量中。Java编程语言还支持一些用于字符和字符串字面量的特殊转义序列:\b(退格)、\t(制表符)、\n(换行)、\f(表格换行)、\r(回车)、\"(双引号)、\'(单引号)和\\(反斜杠)
还有一个特殊的null字面量,能够用做任何引用类型的值。除基本类型的变量外,能够将null赋给任何变量。除了测试null值的存在性以外,您对null值几乎无能为力。所以,在程序中常用null做为标记来指示某些对象不可用。
最后,还有一种特殊的字面量,叫作类字面量,它是由一个类型名加上“.class”组成的;例如String.class。这表示对象自己的类型(类的类型)。
在Java SE 7和更高版本中,任何下划线字符(_)均可以出如今数字字面量中数字之间的任何位置。这个特性支持您将数字字面量进行分隔,以提升代码的可读性。 例如,若是您的代码包含不少位数字,您可使用下划线将数字分红三组,相似于使用逗号或空格等标点符号做为分隔符。 下面的示例展现了在数字字面量中使用下划线的方法:
long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi = 3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;
复制代码
只能在数字之间放置下划线;不能在如下位置放置下划线:
下面的例子演示了数字字面量中有效和无效的下划线位置:
// Invalid: cannot put underscores
// 小数点相邻位置
float pi1 = 3_.1415F;
// Invalid: cannot put underscores
// 小数点相邻位置
float pi2 = 3._1415F;
// Invalid: cannot put underscores
// 在L后缀以前
long socialSecurityNumber1 = 999_99_9999_L;
// OK (decimal literal)
int x1 = 5_2;
// Invalid: cannot put underscores
// 字面量的开头或结尾
int x2 = 52_;
// OK (decimal literal)
int x3 = 5_______2;
// Invalid: cannot put underscores
// 在0x前缀中
int x4 = 0_x52;
// Invalid: cannot put underscores
// 在数字的开头
int x5 = 0x_52;
// OK (hexadecimal literal)
int x6 = 0x5_2;
// Invalid: cannot put underscores
// 数字的结尾
int x7 = 0x52_;
复制代码
数组是一个容器对象,它存储固定数量的单一类型值。数组的长度是在建立数组时肯定的。建立以后,它的长度就是固定的。您已经在“Hello World!”应用程序的主方法中看到了一个数组示例(main(String[] args))。本节更详细地讨论数组:
数组中的每一项都称为一个元素,每一个元素都由其数值索引访问。如上图所示,编号从0开始。例如,第9个元素将在索引8处访问。
下面的程序ArrayDemo建立一个整数数组,在数组中放入一些值,并将每一个值打印到标准输出:
class ArrayDemo {
public static void main(String[] args) {
// declares an array of integers
int[] anArray;
// allocates memory for 10 integers
anArray = new int[10];
// initialize first element
anArray[0] = 100;
// initialize second element
anArray[1] = 200;
// and so forth
anArray[2] = 300;
anArray[3] = 400;
anArray[4] = 500;
anArray[5] = 600;
anArray[6] = 700;
anArray[7] = 800;
anArray[8] = 900;
anArray[9] = 1000;
System.out.println("Element at index 0: "
+ anArray[0]);
System.out.println("Element at index 1: "
+ anArray[1]);
System.out.println("Element at index 2: "
+ anArray[2]);
System.out.println("Element at index 3: "
+ anArray[3]);
System.out.println("Element at index 4: "
+ anArray[4]);
System.out.println("Element at index 5: "
+ anArray[5]);
System.out.println("Element at index 6: "
+ anArray[6]);
System.out.println("Element at index 7: "
+ anArray[7]);
System.out.println("Element at index 8: "
+ anArray[8]);
System.out.println("Element at index 9: "
+ anArray[9]);
}
}
复制代码
程序输出:
Element at index 0: 100
Element at index 1: 200
Element at index 2: 300
Element at index 3: 400
Element at index 4: 500
Element at index 5: 600
Element at index 6: 700
Element at index 7: 800
Element at index 8: 900
Element at index 9: 1000
复制代码
在实际的编程环境中,您可能会使用受支持的循环结构来遍历数组的每一个元素,而不是像前面的示例那样单独地编写每一行。然而,这个例子清楚地说明了数组语法。在 "控制流(Control Flow)"一节中您将了解各类循环结构(for、while和do-while)。
前面的程序使用如下代码行声明一个数组(名为anArray):
// declares an array of integers
int[] anArray;
复制代码
与其余类型变量的声明同样,数组声明有两个组件:数组的类型和数组的名称。数组的类型被写成type[],其中type是所包含元素的数据类型;[]是一些特殊的符号,表示这个变量包含一个数组。数组的大小不是其类型的一部分(这就是为何[]是空的)。数组的名称能够是任何您想要的名称,只要它遵循前面在命名部分中讨论的规则和约定便可。与其余类型的变量同样,声明实际上并不建立数组;它只是告诉编译器该变量将保存指定类型的数组。
相似地,您能够声明其余类型的数组:
byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;
复制代码
你也能够把括号放在数组的名字后面:
// this form is discouraged
float anArrayOfFloats[];
复制代码
然而,惯例不鼓励这种形式;方括号标识数组类型,并应与类型指定一块儿出现。
建立数组的一种方法是使用new操做符。下面ArrayDemo程序中的语句申请一个足够容纳10个整数的数组,并将数组分配给anArray变量:
// create an array of integers
anArray = new int[10];
复制代码
若是缺乏该语句,编译器将打印以下错误,编译失败:
ArrayDemo.java:4: Variable anArray may not have been initialized.
复制代码
接下来的几行代码为数组的每一个元素赋值:
anArray[0] = 100; // initialize first element
anArray[1] = 200; // initialize second element
anArray[2] = 300; // and so forth
复制代码
每一个数组元素都由其数值索引访问:
System.out.println("Element 1 at index 0: " + anArray[0]);
System.out.println("Element 2 at index 1: " + anArray[1]);
System.out.println("Element 3 at index 2: " + anArray[2]);
复制代码
或者,您可使用快捷语法建立和初始化数组:
int[] anArray = {
100, 200, 300,
400, 500, 600,
700, 800, 900, 1000
};
复制代码
数组的长度由大括号中逗号分隔的值的数量决定。
您还可使用两个或多个括号(如String[][]名称)声明数组的数组(也称为多维数组)。所以,每一个元素必须由相应数量的索引值访问。
在Java编程语言中,多维数组是一个数组,其组件自己就是数组。这与C或Fortran中的数组不一样。其结果是容许行长度变化,以下面的MultiDimArrayDemo程序所示:
class MultiDimArrayDemo {
public static void main(String[] args) {
String[][] names = {
{"Mr. ", "Mrs. ", "Ms. "},
{"Smith", "Jones"}
};
// Mr. Smith
System.out.println(names[0][0] + names[1][0]);
// Ms. Jones
System.out.println(names[0][2] + names[1][1]);
}
}
复制代码
程序输出为:
Mr. Smith
Ms. Jones
复制代码
最后,您可使用内置的length属性来肯定任何数组的大小。如下代码将数组的大小打印到标准输出:
System.out.println(anArray.length);
复制代码
System类有一个arraycopy方法,您可使用它来有效地将数据从一个数组复制到另外一个数组:
public static void arraycopy(Object src, int srcPos,
Object dest, int destPos, int length)
复制代码
这两个Object参数指定源数组和要目的数组,三个int参数指定源数组中的起始位置、目标数组中的起始位置和要复制的数组元素的数量。
下面的程序ArrayCopyDemo声明了一个char元素数组,存储单词“decaffeated”。它使用System.arraycopy方法将源数组的子串复制到第二个数组中:
class ArrayCopyDemo {
public static void main(String[] args) {
char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd' };
char[] copyTo = new char[7];
System.arraycopy(copyFrom, 2, copyTo, 0, 7);
System.out.println(new String(copyTo));
}
}
复制代码
这个程序的输出是:
caffein
复制代码
数组是编程中使用的一个强大而有用的概念。Java SE提供了一些方法来执行与数组相关的一些最多见的操做。例如,ArrayCopyDemo示例使用系统类的arraycopy方法,而不是手动遍历源数组的元素并将每一个元素放入目标数组。这是在后台执行的,容许开发人员只使用一行代码来调用方法。
为了方便起见,Java SE在java.util.Arrays 类中提供了几种执行数组操做的方法(常见的任务:如复制、排序和搜索)。例如,能够修改前面的示例,使用java.util.Arrays类的copyOfRange方法。正如您在ArrayCopyOfDemo示例中所看到的。不一样之处在于,使用copyOfRange方法不须要在调用该方法以前建立目标数组,由于该方法返回目标数组。
class ArrayCopyOfDemo {
public static void main(String[] args) {
char[] copyFrom = {'d', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd'};
char[] copyTo = java.util.Arrays.copyOfRange(copyFrom, 2, 9);
System.out.println(new String(copyTo));
}
}
复制代码
正如您所看到的,尽管这个程序的代码更少,可是输出倒是相同的(caffein)。注意,copyOfRange方法的第二个参数是要复制的范围的初始索引,而第三个参数是要复制的范围的最终索引。在本例中,要复制的范围不包括索引9处的数组元素('a')。
下面例举java.util.Arrays类中提供的一些其余有用的方法: