【译】Java8官方教程:语言基础—变量

栏目: Java · 发布时间: 7年前

内容简介:正如我们上一节中所学,对象将它的状态存储在"字段(fields)"中"何为对象?"中向您介绍了“字段(fields)”,但是您可能会存在一些疑问,例如:命名"字段(fields)"的规则和约定是什么?除了int,还有一些什么数据类型?字段声明时必须初始化吗?如果没有显示初始化,它们具有默认的值吗?本节课我们将探索这些问题的答案,但是在这之前,下面是您必须首先注意的一些技术区别。在Java编程语言中,术语“字段(fields)”和“变量(Variables)”都被采用,对于新开发人员来说,这是一个常见的困惑源

正如我们上一节中所学,对象将它的状态存储在"字段(fields)"中

int cadence = 0;
int speed = 0;
int gear = 1;
复制代码

"何为对象?"中向您介绍了“字段(fields)”,但是您可能会存在一些疑问,例如:命名"字段(fields)"的规则和约定是什么?除了int,还有一些什么数据类型?字段声明时必须初始化吗?如果没有显示初始化,它们具有默认的值吗?本节课我们将探索这些问题的答案,但是在这之前,下面是您必须首先注意的一些技术区别。在 Java 编程语言中,术语“字段(fields)”和“变量(Variables)”都被采用,对于新开发人员来说,这是一个常见的困惑源,它们通常指代的似乎是同一个事物。

Java编程语言定义了以下几种变量:

  • 实例变量(非静态字段):技术上来说,对象将各自的状态存储在“非静态字段”中,也就是说,声明字段时没有指定static关键字。非静态字段也称为实例变量,因为他们的值在每个类的实例中(或者说:在每个对象中)都是不一样的。一辆自行车的当前速度与另一辆自行车的当前速度无关。

  • 类变量(静态字段):使用静态修饰符(static)声明的任何字段称为类变量;这告诉编译器,不管这个类实例化了多少次,该变量都仅存在一个副本。对于特定类型自行车齿轮数的字段可以声明为static,这将赋予所有实例相同的齿轮数。代码段:static int numGears = 6;将创建一个静态字段,此外,可以添加关键字final来表示齿轮的数量永远不会改变。

  • 局部变量:与对象将状态存储在字段中相似,方法经常将其暂时的状态存在局部变量中。声明局部变量的语法类似于声明字段(int count = 0;)。没有特殊的关键字指定其为局部变量;这完全取决于变量声明的位置——方法的开括号和闭括号之间;因此,局部变量只对声明它们的方法可见;其他类无法访问它们。

  • 参数: 在自行车类和“Hello world!”应用中您已经看到过参数的示例。回想一下main方法:public static void main(String[] args),这里,args是这个方法的参数。重要的是要记住参数总是被分类为“变量”而不是“字段”。这也适用于其他接受参数的构造方法(如构造函数和异常处理器),您将在本教程的后面学习这些

话虽如此,如果我们谈论的是“一般的字段”(不包括局部变量和参数),我们可以简单地说“字段”。如果讨论适用于“以上所有”,我们可以简单地说“变量”。如果上下文需要区别,我们将使用特定的术语(静态字段、局部变量等)。你可能会经常看到"成员"这个术语。字段、方法和嵌套类型统称为其成员。

命名

每种编程语言对于允许使用的命名方式都有自己的一套规则和约定,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。然而,依赖这些默认值通常被认为是糟糕的编程风格

下表总结了上述数据类型的默认值:

【译】Java8官方教程:语言基础—变量

局部变量略有不同;编译器从不将默认值分配给未初始化的局部变量。如果无法在声明局部变量的地方初始化该变量,请确保在尝试使用它之前为其赋值。访问未初始化的局部变量将导致编译时错误。

字面量(Literals)

您可能已经注意到,在初始化基本类型的变量时不使用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字面量创建。整数字面值可以由这些数字系统表示:

  • 十进制:以10为基数,由数字0到9组成;这是你每天使用的数字系统
  • 16进制:以16为基数,由数字0到9和字母A到F组成
  • 二进制:以2为基数,由数字0和1组成(您可以在Java SE 7和更高版本中创建二进制字面量)

对于一般编程,十进制系统可能是您将使用的唯一数字系统。但是,如果需要使用另一个数字系统,下面的示例显示了正确的语法。前缀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;
复制代码

只能在数字之间放置下划线;不能在以下位置放置下划线:

  • 在数字的开头或结尾
  • 在浮点数的小数点相邻位置
  • 在F或L后缀之前
  • 在需要一串数字的位置(原文:In positions where a string of digits is expected)

下面的例子演示了数字字面量中有效和无效的下划线位置:

// 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))。本节更详细地讨论数组:

【译】Java8官方教程:语言基础—变量

数组中的每一项都称为一个元素,每个元素都由其数值索引访问。如上图所示,编号从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类中提供的一些其他有用的方法:

  • 在数组中搜索特定值,以获得它所在的索引(binarySearch方法)
  • 比较两个数组以确定它们是否相等(equals方法)
  • 在每个索引处放置特定值(fill方法)
  • 按升序排列数组。可以使用sort方法顺序执行,也可以使用Java SE 8中引入的parallelSort方法并发执行。在多处理器系统上对大数组进行并行排序要比顺序数组排序快。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

DOM Scripting

DOM Scripting

Jeremy Keith / friendsofED / 2010-12 / GBP 27.50

There are three main technologies married together to create usable, standards-compliant web designs: XHTML for data structure, Cascading Style Sheets for styling your data, and JavaScript for adding ......一起来看看 《DOM Scripting》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具