资讯专栏INFORMATION COLUMN

Java™ 教程(变量)

elina / 3020人阅读

变量

正如你在上一课中所了解到的,对象将其状态存储在字段中。

int cadence = 0;
int speed = 0;
int gear = 1;

“什么是对象?”讨论向你介绍了字段,但你可能还有一些问题,例如:命名字段的规则和约定是什么?除了int之外,还有哪些其他数据类型?在声明字段时是否必须初始化字段?如果未明确初始化字段,是否为字段分配了默认值?我们将在本课中探讨这些问题的答案,但在我们开始之前,你必须首先了解一些技术差异。在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编程语言也不例外,命名变量的规则和约定可归纳如下:

变量名称区分大小写,变量的名称可以是任何合法标识符 - 一个无限长度的Unicode字母和数字序列,以字母开、美元符号“$”或下划线字符“_”开头,但是,惯例是始终用字母开始变量名,而不是“$”或“_”,此外,按照惯例,美元符号字符根本不会被使用。你可能会发现某些情况,其中自动生成的名称将包含美元符号,但你的变量名称应始终避免使用它,对于下划线字符存在类似的约定;虽然用“_”开始变量的名称在技术上是合法的,但不鼓励这种做法,不允许有空格。

后续字符可以是字母,数字,美元符号或下划线字符,约定(和通用场景)也适用于此规则,为变量选择名称时,请使用完整单词而不是隐藏缩写,这样做可以使你的代码更易于阅读和理解。在许多情况下,它还会使你的代码自我记录,例如,名为cadencespeedgear的字段比缩写版本(如scg)更直观,另请注意,你选择的名称不得是关键字或保留字。

如果你选择的名称只包含一个单词,则拼写全部小写字母,如果它由多个单词组成,则将每个后续单词的首字母大写,名称gearRatiocurrentGear是此约定的主要示例,如果你的变量存储一个常量值,例如static final int NUM_GEARS = 6;,约定略有变化,大写每个字母并用后下划线分隔后续单词,按照惯例,下划线字符从未在别处使用过。

原始数据类型

Java编程语言是静态类型的,这意味着必须首先声明所有变量才能使用它们,这包括声明变量的类型和名称,如你所见:

int gear = 1;

这样做会告诉程序一个名为“gear”的字段存在,保存数字数据,初始值为“1”,变量的数据类型确定它可能包含的值,以及可能对其执行的操作。除了int之外,Java编程语言还支持其他七种原始数据类型,基本类型由语言预定义,并由保留关键字命名,原始值不与其他原始值共享状态,Java编程语言支持的八种原始数据类型是:

byte:字节数据类型是8位带符号的二进制补码整数,它的最小值为-128,最大值为127(含),字节数据类型可用于在大数组中保存内存,其中节省的内存实际上很重要。它们也可以用于代替int,其限制有助于澄清你的代码,变量范围有限的事实可以作为一种文档形式。

shortshort数据类型是16位带符号的二进制补码整数,它的最小值为-32,768,最大值为32,767(含)。与字节一样,适用相同的准则:在内存节省实际上很重要的情况下,你可以使用short来节省大数组中的内存。

int:默认情况下,int数据类型是32位带符号的二进制补码整数,其最小值为-2^31,最大值为2^31-1,在Java SE 8及更高版本中,你可以使用int数据类型来表示无符号的32位整数,其最小值为0,最大值为2^32-1,使用Integer类将int数据类型用作无符号整数,有关详细信息,请参阅“Number类”一节。已经将诸如compareUnsigneddivideUnsigned等静态方法添加到Integer类中,以支持无符号整数的算术运算。

longlong数据类型是64位二进制补码整数,带符号的long的最小值为-2^63,最大值为2^63-1,在Java SE 8及更高版本中,你可以使用long数据类型来表示无符号的64位长,其最小值为0,最大值为2^64-1,当需要比int提供的值更宽的值时,请使用此数据类型,Long类还包含compareUnsigneddivideUnsigned等方法,以支持无符号long的算术运算。

float:浮点数据类型是单精度32位IEEE 754浮点,它的值范围超出了本讨论的范围,但在Java语言规范的浮点类型、格式和值部分中指定。与byteshort的建议一样,如果需要在大型浮点数数组中保存内存,请使用float(而不是double),绝不应将此数据类型用于精确值,例如货币,为此,你需要使用java.math.BigDecimal类,Numbers和Strings涵盖了Java平台提供的BigDecimal和其他有用的类。

doubledouble数据类型是双精度64位IEEE 754浮点,它的值范围超出了本讨论的范围,但在Java语言规范的浮点类型、格式和值部分中指定,对于十进制值,此数据类型通常是默认选择,如上所述,此数据类型不应用于精确值,例如货币。

boolean:布尔数据类型只有两个可能的值:truefalse,将此数据类型用于跟踪真/假条件的简单标志,此数据类型表示一位信息,但其“大小”不是精确定义的内容。

charchar数据类型是单个16位Unicode字符,它的最小值为"u0000"(或0),最大值为"uffff"(或65,535(含))。

除了上面列出的八种原始数据类型之外,Java编程语言还通过java.lang.String类为字符串提供特殊支持,将字符串括在双引号内将自动创建一个新的String对象,例如,String s =“this is a string”;。字符串对象是不可变的,这意味着一旦创建,它们的值就不能更改,String类在技术上不是原始数据类型,但考虑到语言给予它的特殊支持,你可能倾向于认为它是这样的,你将在简单的数据对象中了解有关String类的更多信息。

默认值

声明字段时并不总是需要分配值,声明但未初始化的字段将由编译器设置为合理的默认值。一般来说,此默认值将为零或null,具体取决于数据类型,然而,依赖于这样的默认值通常被认为是糟糕的编程风格。

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

数据类型 默认值(对于字段)
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char "u0000"
String(或任何对象) null
boolean false

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

字面值

你可能已经注意到在初始化基本类型的变量时不使用new关键字,原始类型是语言中内置的特殊数据类型,它们不是从类创建的对象。字面值是固定值的源代码表示,字面值直接在代码中表示,无需计算,如下所示,可以将字面值分配给基本类型的变量:

boolean result = true;
char capitalC = "C";
byte b = 100;
short s = 10000;
int i = 100000;
整数字面值

如果整数字面值以字母Ll结尾,则其长度为long,否则它是int类型,建议你使用大写字母L,因为小写字母l很难与数字1区分开来。

可以从int字面值创建整数类型byteshortintlong的值,可以从long字面值创建超出int范围的long类型的值,整数字面值可以用这些数字系统表示:

十进制:基数10,其数字由数字0到9组成,这是你每天使用的数字系统。

十六进制:基数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;
浮点字面值

如果浮点字面值以字母Ff结尾,则浮点字面值为float类型,否则它的类型是double的,它可以选择以字母Dd结尾。

浮点类型(floatdouble)也可以用Ee(科学计数法),Ff(32位浮点数)和Dd(64位双精度数,这是默认值,按惯例省略)表示。

double d1 = 123.4;
// same value as d1, but in scientific notation
double d2 = 1.234e2;
float f1  = 123.4f;
字符和字符串字面值

类型charString的字面值可以包含任何Unicode(UTF-16)字符,如果你的编辑器和文件系统允许,你可以直接在代码中使用这些字符,如果没有,你可以使用“Unicode转义”,例如"u0108"(带有circumflex的大写字母C),或"Su00ED Seu00F1or"(SíSeñor,西班牙语)。始终对char字面值使用“单引号”,对字符串字面值使用“双引号”,Unicode转义序列可以在程序的其他地方使用(例如在字段名中),而不仅仅是在charString字面值中。

Java编程语言还支持charString字面值的一些特殊转义序列:(退格)、 (制表符)、 (换行)、f(换页)、 (回车)、 "(双引号)、"(单引号)和(反斜杠)。

还有一个特殊的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;

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

在数字的开头或结尾

与浮点字面值中的小数点相邻

FL后缀之前

在预期有一串数字的位置

以下示例演示了数字字面值中有效和无效的下划线放置:

// 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

在实际编程情况下,你可能会使用其中一个受支持的循环结构来遍历数组的每个元素,而不是像前面的示例中那样多带带编写每一行,但是,该示例清楚地说明了数组语法,你将在控制流部分中了解各种循环结构(forwhiledo-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编程语言中,多维数组是一个数组,其组件本身就是数组,这与CFortran中的数组不同,这样做的结果是允许行的长度不同,如下面的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修饰符声明的字段,无论类被实例化多少次,都只有一个类变量的副本。局部变量在方法中存储临时状态,参数是为方法提供额外信息的变量,局部变量和参数总是被归类为“变量”(而不是“字段”),在命名字段或变量时,你应该(或必须)遵循规则和约定。

八种原始数据类型是:byteshortintlongfloatdoublebooleancharjava.lang.String类表示字符串。编译器将为上述类型的字段分配合理的默认值,对于局部变量,永远不会分配默认值。字面值是固定值的源代码表示,数组是一个容器对象,它包含固定数量的单个类型的值,创建数组时,将建立数组的长度,创建后,其长度是固定的。

上一篇:面向对象编程概念 下一篇:运算符

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76441.html

相关文章

  • 阿里 Java 手册系列教程:为啥强制子类、父类变量名不同?

    摘要:所以看出和两个的对应指针数一样,一个为一个为这就引出了变量的知识点,如手工画的图二为啥强制子类父类变量名不同阿里巴巴手册是这样写的强制避免在子父类的成员变量之间或者不同代码块的局部变量之间采用完全相同的命名方式,那会导致代码可读性降低。 摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 父子...

    XGBCCC 评论0 收藏0
  • Windows环境下JDK安装与环境变量配置详细的图文教程

    摘要:原文作者博文出处本节内容安装与环境变量配置以下是详细步骤一准备工具可以到官网下载系统我这里是系统可以根据系统的版本下载相对应的。配置系统环境配置环境变量右击我的电脑高级环境变量。根据自己的安装路径填写环境变量。 原文作者:souvc博文出处:http://www.cnblogs.com/liuhon... 本节内容:JDK安装与环境变量配置 以下是详细步骤 一、准备工具: 1.JDK ...

    Yangyang 评论0 收藏0
  • 【精致Java教程】03:安装JDK和配置Java环境变量

    摘要:运行环境,它是程序运行的所必需的环境集合。安装下一步下一步即可,要记得安装路径。配置环境变量安装完以后需要对系统的环境变量进行配置才能开发。之所以不能运行是因为装类之后还得配置环境变量。 在了解了Java历史、特性、作用和跨平台原理之后,我们可以开始为Java开发做准备工作了,只是在此之前我们还需要了解Java的两大基础概念JDK(Java Development kit)和JRE(J...

    CoyPan 评论0 收藏0
  • Java教程(PATH和CLASSPATH)

    PATH和CLASSPATH 本节介绍如何在Microsoft Windows,Solaris和Linux上使用PATH和CLASSPATH环境变量,有关最新信息,请参阅安装Java Development Kit(JDK)软件包中随附的安装说明。 安装软件后,JDK目录将具有如下所示的结构。 showImg(https://segmentfault.com/img/bVbqpb7?w=282&h...

    Ku_Andrew 评论0 收藏0
  • Java 8 并发教程:原子变量和 ConcurrentMa

    摘要:并发教程原子变量和原文译者飞龙协议欢迎阅读我的多线程编程系列教程的第三部分。如果你能够在多线程中同时且安全地执行某个操作,而不需要关键字或上一章中的锁,那么这个操作就是原子的。当多线程的更新比读取更频繁时,这个类通常比原子数值类性能更好。 Java 8 并发教程:原子变量和 ConcurrentMap 原文:Java 8 Concurrency Tutorial: Synchroni...

    bitkylin 评论0 收藏0
  • Java教程(原子变量

    原子变量 java.util.concurrent.atomic包定义了支持单个变量的原子操作的类,所有类都有get和set方法,类似于对volatile变量的读写操作,也就是说,set与在同一个变量上任何后续的get具有先发生关系,compareAndSet原子方法也具有这些内存一致性特性,适用于整数原子变量的简单原子算法也是如此。 要查看如何使用此包,让我们返回我们最初用于演示线程干扰的Cou...

    bang590 评论0 收藏0

发表评论

0条评论

elina

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<