正如你在上一课中所了解到的,对象将其状态存储在字段中。html
int cadence = 0; int speed = 0; int gear = 1;
“什么是对象?”讨论向你介绍了字段,但你可能还有一些问题,例如:命名字段的规则和约定是什么?除了int
以外,还有哪些其余数据类型?在声明字段时是否必须初始化字段?若是未明确初始化字段,是否为字段分配了默认值?咱们将在本课中探讨这些问题的答案,但在咱们开始以前,你必须首先了解一些技术差别。在Java编程语言中,使用术语“字段”和“变量”,这是新开发人员之间混淆的常见缘由,由于二者每每都是指同一件事。java
Java编程语言定义了如下几种变量:编程
static
关键字的状况下声明的字段,非静态字段也称为实例变量,由于它们的值对于类的每一个实例都是惟一的(换句话说,对于每一个对象),一辆自行车的当前速度独立于另外一辆自行车的当前速度。static
修饰符声明的任何字段,这告诉编译器这个变量只有一个副本存在,不管该类被实例化多少次,定义特定类型自行车档位数的字段能够标记为静态,由于从概念上讲,相同数量的档位将适用于全部实例,代码static int numGears = 6
会建立这样一个静态字段。此外,能够添加关键字final
以指示档位的数量永远不会改变。int count = 0;
)。没有特殊关键字将变量指定为本地变量,该决定彻底来自声明变量的位置 - 它位于方法的开括号和右括号之间。所以,局部变量仅对声明它们的方法可见,他们没法从类的其余其余访问。Bicycle
类和“Hello World”应用程序的main
方法中看到了参数示例,回想一下main
方法的签名是public static void main (String [] args)
,这里,args
变量是此方法的参数。要记住的重要一点是参数老是被归类为“变量”而不是“字段”,这也适用于其余参数接受构造(例如构造函数和异常处理程序),你将在本教程后面学习。每种编程语言都有本身的规则和约定,适用于你可使用的各类名称,Java编程语言也不例外,命名变量的规则和约定可概括以下:segmentfault
Unicode
字母和数字序列,以字母开、美圆符号“$
”或下划线字符“_
”开头,可是,惯例是始终用字母开始变量名,而不是“$
”或“_
”,此外,按照惯例,美圆符号字符根本不会被使用。你可能会发现某些状况,其中自动生成的名称将包含美圆符号,但你的变量名称应始终避免使用它,对于下划线字符存在相似的约定;虽然用“_
”开始变量的名称在技术上是合法的,但不鼓励这种作法,不容许有空格。cadence
,speed
和gear
的字段比缩写版本(如s
,c
和g
)更直观,另请注意,你选择的名称不得是关键字或保留字。gearRatio
和currentGear
是此约定的主要示例,若是你的变量存储一个常量值,例如static final int NUM_GEARS = 6;
,约定略有变化,大写每一个字母并用后下划线分隔后续单词,按照惯例,下划线字符从未在别处使用过。Java编程语言是静态类型的,这意味着必须首先声明全部变量才能使用它们,这包括声明变量的类型和名称,如你所见:api
int gear = 1;
这样作会告诉程序一个名为“gear”的字段存在,保存数字数据,初始值为“1”,变量的数据类型肯定它可能包含的值,以及可能对其执行的操做。除了int
以外,Java编程语言还支持其余七种原始数据类型,基本类型由语言预约义,并由保留关键字命名,原始值不与其余原始值共享状态,Java编程语言支持的八种原始数据类型是:数组
-128
,最大值为127
(含),字节数据类型可用于在大数组中保存内存,其中节省的内存实际上很重要。它们也能够用于代替int
,其限制有助于澄清你的代码,变量范围有限的事实能够做为一种文档形式。short
数据类型是16位带符号的二进制补码整数,它的最小值为-32,768,最大值为32,767(含)。与字节同样,适用相同的准则:在内存节省实际上很重要的状况下,你可使用short
来节省大数组中的内存。int
数据类型是32位带符号的二进制补码整数,其最小值为-2^31,最大值为2^31-1,在Java SE 8及更高版本中,你可使用int
数据类型来表示无符号的32位整数,其最小值为0,最大值为2^32-1,使用Integer
类将int
数据类型用做无符号整数,有关详细信息,请参阅“Number类”一节。已经将诸如compareUnsigned
、divideUnsigned
等静态方法添加到Integer类中,以支持无符号整数的算术运算。long
数据类型是64位二进制补码整数,带符号的long
的最小值为-2^63,最大值为2^63-1,在Java SE 8及更高版本中,你可使用long
数据类型来表示无符号的64位长,其最小值为0,最大值为2^64-1,当须要比int
提供的值更宽的值时,请使用此数据类型,Long类还包含compareUnsigned
、divideUnsigned
等方法,以支持无符号long
的算术运算。byte
和short
的建议同样,若是须要在大型浮点数数组中保存内存,请使用float
(而不是double
),毫不应将此数据类型用于精确值,例如货币,为此,你须要使用java.math.BigDecimal类,Numbers和Strings涵盖了Java平台提供的BigDecimal
和其余有用的类。double
数据类型是双精度64位IEEE 754浮点,它的值范围超出了本讨论的范围,但在Java语言规范的浮点类型、格式和值部分中指定,对于十进制值,此数据类型一般是默认选择,如上所述,此数据类型不该用于精确值,例如货币。true
和false
,将此数据类型用于跟踪真/假条件的简单标志,此数据类型表示一位信息,但其“大小”不是精肯定义的内容。char
数据类型是单个16位Unicode字符,它的最小值为'\u0000'
(或0),最大值为'\uffff'
(或65,535(含))。除了上面列出的八种原始数据类型以外,Java编程语言还经过java.lang.String类为字符串提供特殊支持,将字符串括在双引号内将自动建立一个新的String
对象,例如,String s =“this is a string”;
。字符串对象是不可变的,这意味着一旦建立,它们的值就不能更改,String
类在技术上不是原始数据类型,但考虑到语言给予它的特殊支持,你可能倾向于认为它是这样的,你将在简单的数据对象中了解有关String
类的更多信息。oracle
声明字段时并不老是须要分配值,声明但未初始化的字段将由编译器设置为合理的默认值。通常来讲,此默认值将为零或null,具体取决于数据类型,然而,依赖于这样的默认值一般被认为是糟糕的编程风格。编程语言
下表总结了上述数据类型的默认值。编辑器
数据类型 | 默认值(对于字段) |
---|---|
byte |
0 |
short |
0 |
int |
0 |
long |
0L |
float |
0.0f |
double |
0.0d |
char |
'\u0000' |
String (或任何对象) |
null |
boolean |
false |
局部变量略有不一样;编译器永远不会为未初始化的局部变量分配默认值,若是没法初始化声明它的局部变量,请确保在尝试使用它以前为其赋值,访问未初始化的局部变量将致使编译时错误。ide
你可能已经注意到在初始化基本类型的变量时不使用new
关键字,原始类型是语言中内置的特殊数据类型,它们不是从类建立的对象。字面值是固定值的源代码表示,字面值直接在代码中表示,无需计算,以下所示,能够将字面值分配给基本类型的变量:
boolean result = true; char capitalC = 'C'; byte b = 100; short s = 10000; int i = 100000;
若是整数字面值以字母L
或l
结尾,则其长度为long
,不然它是int
类型,建议你使用大写字母L
,由于小写字母l
很难与数字1
区分开来。
能够从int
字面值建立整数类型byte
、short
、int
和long
的值,能够从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位浮点数)和D
或d
(64位双精度数,这是默认值,按惯例省略)表示。
double d1 = 123.4; // same value as d1, but in scientific notation double d2 = 1.234e2; float f1 = 123.4f;
类型char
和String
的字面值能够包含任何Unicode(UTF-16)字符,若是你的编辑器和文件系统容许,你能够直接在代码中使用这些字符,若是没有,你可使用“Unicode转义”,例如'\u0108'
(带有circumflex的大写字母C
),或"S\u00ED Se\u00F1or"
(SíSeñor,西班牙语)。始终对char
字面值使用“单引号”,对字符串字面值使用“双引号”,Unicode转义序列能够在程序的其余地方使用(例如在字段名中),而不只仅是在char
或String
字面值中。
Java编程语言还支持char
和String
字面值的一些特殊转义序列:\b
(退格)、\t
(制表符)、\n
(换行)、\f
(换页)、\r
(回车)、 \"
(双引号)、\'
(单引号)和\\
(反斜杠)。
还有一个特殊的null
字面值,能够用做任何引用类型的值,null
能够分配给任何变量,但基本类型的变量除外。除了测试它的存在以外,你几乎没法使用null
值,所以,null
一般在程序中用做标记,以指示某些对象不可用。
最后,还有一种特殊的字面值称为类字面值,经过获取类型名称并附加“.class”造成,例如,String.class
,这指的是表示类型自己的对象(类型为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;
你只能在数字之间放置下划线;你不能在如下地方放置下划线:
F
或L
后缀以前如下示例演示了数字字面值中有效和无效的下划线放置:
// Invalid: cannot put underscores // adjacent to a decimal point float pi1 = 3_.1415F; // Invalid: cannot put underscores // adjacent to a decimal point float pi2 = 3._1415F; // Invalid: cannot put underscores // prior to an L suffix long socialSecurityNumber1 = 999_99_9999_L; // OK (decimal literal) int x1 = 5_2; // Invalid: cannot put underscores // At the end of a literal int x2 = 52_; // OK (decimal literal) int x3 = 5_______2; // Invalid: cannot put underscores // in the 0x radix prefix int x4 = 0_x52; // Invalid: cannot put underscores // at the beginning of a number int x5 = 0x_52; // OK (hexadecimal literal) int x6 = 0x5_2; // Invalid: cannot put underscores // at the end of a number int x7 = 0x52_;
数组是一个容器对象,它包含固定数量的单个类型的值,建立数组时,将创建数组的长度,建立后,其长度是固定的。你已经在“Hello World!”应用程序的main
方法中看到了一个数组示例,本节更详细地讨论了数组。
10个元素的数组。
数组中的每一个项称为元素,每一个元素都由其数字索引访问,如上图所示,编号从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
在实际编程状况下,你可能会使用其中一个受支持的循环结构来遍历数组的每一个元素,而不是像前面的示例中那样单独编写每一行,可是,该示例清楚地说明了数组语法,你将在控制流部分中了解各类循环结构(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 [][] names
,所以,每一个元素必须由相应数量的索引值访问。
在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][10] + names[1][11]); } }
该程序的输出是:
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
元素数组,拼写单词“decaffeinated”,它使用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
示例使用System
类的arraycopy
方法,而不是手动迭代源数组的元素并将每一个元素放入目标数组中。这是在幕后执行的,使开发人员只使用一行代码来调用该方法。
为方便起见,Java SE提供了几种在java.util.Arrays类中执行数组操做(常见任务,如复制、排序和搜索数组)的方法。例如,能够修改前面的示例以使用java.util.Arrays
类的copyOfRange
方法,如ArrayCopyOfDemo
示例中所示:
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
类中的方法提供的一些其余有用的操做是:
binarySearch
方法)。equals
方法)。fill
方法)。sort
方法串行完成,也可使用Java SE 8中引入的parallelSort
方法并行完成,在多处理器系统上并行排序大型数组比串行数组排序更快。Java编程语言使用“字段”和“变量”做为其术语的一部分,实例变量(非静态字段)对于类的每一个实例都是惟一的,类变量(静态字段)是使用static
修饰符声明的字段,不管类被实例化多少次,都只有一个类变量的副本。局部变量在方法中存储临时状态,参数是为方法提供额外信息的变量,局部变量和参数老是被归类为“变量”(而不是“字段”),在命名字段或变量时,你应该(或必须)遵循规则和约定。
八种原始数据类型是:byte
、short
、int
、long
、float
、double
、boolean
和char
,java.lang.String
类表示字符串。编译器将为上述类型的字段分配合理的默认值,对于局部变量,永远不会分配默认值。字面值是固定值的源代码表示,数组是一个容器对象,它包含固定数量的单个类型的值,建立数组时,将创建数组的长度,建立后,其长度是固定的。