如何在 Java 中使用数组

介绍

一个数组(https://en.wikipedia.org/wiki/Array_(data_structure)允许您组合和存储多个元素。使用数组,您可以存储任何类型的数据,即参考或原始类型。但是,所有的数组元素必须是相同的数据类型。

数组在Java中起着基本的作用,因为许多核心数据类型是基于它们的,例如,常用的参考类型String实际上是作为一个数组的char元素实现的,所以即使你可能不知道它,你已经使用了数组。

在本教程中,你将使用一个char数组来安全地存储密码. 这是数组的常见用例。 一个char数组比存储密码的string是一个更好的选择,因为一个string对象是不可变的 - 也就是说,它不能被压缩。 因此,即使你可能不再需要一个密码string对象,你不能简单地去除它。 这意味着对象仍然存在于记忆中,因此,攻击者理论上可以访问这个内存部分并阅读密码。 相比之下,你可以很容易地压缩一个作为一个char数组存储的密码并使其不可用。 因此,攻击者没有机会从检查记忆中学习密码。

前提条件

要遵循本教程,您将需要:

创建 Arrays

要开始使用一个数组,你必须先创建它. 创建一个数组有几种方法,你创建一个方法取决于你是否知道数组将包含哪些元素。

<$>[info] 信息: 要跟进本教程中的示例代码,请在本地系统上运行jshell命令,打开Java Shell工具,然后您可以复制、粘贴或编辑示例,在jshell>提示后添加它们并按ENTER

如果您不知道数组元素,则可以创建一个空数组并定义其大小,如下:

1char[] password = new char[6];

char关键字之后的[]组合将变量密码定义为数组。char关键字意味着变量包含char原始词。

当您运行前一个代码时,您将收到以下输出:

1password ==> char[6] { '\000', '\000', '\000', '\000', '\000', '\000' }

输出证实,在名为密码下创建了一个新的char数组,它可以存储六个元素([6]),这些元素目前是空的(000)。

或者,如果您已经知道数组元素,您可以创建一个名为密码的数组,其中包含char元素,如下:

1char[] password = new char[] {'s', 'e', 'c', 'r', 'e', 't'};

声明的左部分,在等位符号之前,与第一个空数组示例中的声明的左部分相同 - 一个char数组被定义为名为password。声明的第二部分,在等位符号之后,再次以关键字开始;然而,元素的数量没有被明确说明。相反,所有六个元素都列出了。

当你将前面的代码插入到jshell中时,你会得到以下输出:

1[secondary_label Output]
2password ==> char[6] { 's', 'e', 'c', 'r', 'e', 't' }

输出确认密码``char数组已创建并列出其元素。

在后一个示例中,您在创建数组时指定了元素,从而节省了您在为元素编写额外的指示来分配值的机会,这是以这种方式创建数组的好处。

定义和更改数组元素

您不会总是知道数组的元素,所以指定它们以及创建数组可能不是一个选项,无论您是否最初指定数组元素,您可以随时指定或更改它们。

例如,您可以通过引用其索引(即在数组中的位置)来更改密码数组的元素,如下:

1password[0] = 'n';

通过使用密码[0],您指的是密码数组的第一个元素。 数组元素从0开始编号,所以第一个元素将有0的索引,就像在这种情况下一样。

jshell中执行前一个语句后,您将获得类似于以下的输出:

1[secondary_label Output]
2$8 ==> 'n'

临时变量8美元jshell中被内部使用,在您的情况下可能是一个不同的数字。

jshell中,您可以使用一个独特的功能来确认密码数组已按照您的意图改变。当您粘贴数组的名称时,在jshell中,它将打印数组及其元素,而无需其他方法:

1password

您将在jshell中获得以下输出:

1[secondary_label Output]
2password ==> char[6] { 'n', 'e', 'c', 'r', 'e', 't' }

此输出确认您已成功地从s,e,c,r,e,t更改到n,e,c,r,e,t。现在,如果攻击者获得访问您的服务器,他们将获得更改的密码,而不是原始密码。

您将继续在本教程中使用密码数组,因此出于一致性原因,将第一个元素的值恢复到s,再次参考它并在jshell中执行命令:

1password[0] = 's';

这将产生类似于前者与临时变量类似的输出,在这种情况下,25美元,这确认了更改的成功:

1[secondary_label Output]
2$25 ==> 's'

再次,你有原始的密码数组,其中包括元素s,e,c,r,e,t。现在你知道如何创建和更改数组的元素,现在是时候开始阅读和使用它的元素了。

获取 Array 元素

获取特定数组元素时,您将使用其索引工作,例如,要获取密码数组的第二个元素,您可以使用以下代码:

1System.out.println(password[1]);

在此代码中,您使用println()方法来打印密码数组的第二个元素。 (有关System.out.println陈述的更多信息,请参阅我们的教程(How To Write Your First Program in Java)(https://andsky.com/tech/tutorials/how-to-write-your-first-program-in-java#understanding-the-hello-world-program)。

此代码将产生以下输出:

1[secondary_label Output]
2e

输出打印了第二个数组元素e。就像打印它一样,你可以以任何其他方式使用它,其中一个char值是合适的。 <!--- AOT 这里的意思不清楚。

此外,您还可以使用前列循环对所有数组元素进行迭代,正如我们在教程中解释的那样(https://andsky.com/tech/tutorials/how-to-use-loops-in-java)。 循环是控制重复程序流程的结构,而前列循环对于在数组上迭代尤其有用,因为它需要最少的锅板代码。

1for (char c : password) {
2    System.out.print(c);
3}

这个前进循环在密码数组上迭代,并使用一个被称为c的临时char变量。每次迭代,c密码数组的第一个元素移动到最后一个元素。一旦c得到数组元素的值,你可以以任何适当的方式在代码块中使用c

请注意,‘print()’方法打印了没有新行的论点,相反,到目前为止,在教程中,你已经使用了‘println()’方法,每次运行时都会留下一个新行.<!--AOT 我看不到 println() 方法的例子打印了一个新行,前面的例子只打印了一个元素,即e。我建议添加一个示例显示 println()打印了多个数组元素,这样 println() 和 print() 之间的对比就更清晰了。

如果您准确遵循前面的步骤并在jshell中运行此代码,您将获得以下输出:

1[secondary_label Output]
2secret

如果您错过了将第一个数组元素从n返回到s的步骤,您将获得necret

您可以通过将迄今为止所建立的知识结合起来获得数组的所有元素,从此开始,您准备深入到数组的主题,并学习有用的数组方法来执行各种功能。

使用 Arrays 方法

Java 有一个非常有用的Arrays类,位于java.util包中。这个类可以帮助您在与数组工作时,通过为常见用例提供有用的方法。这意味着您不必重新发明轮子,您可以节省自己多余的努力。

平等( )的方法

equals()方法比较两个数组,以确定它们是否等同. 要使两个数组等同,它们必须具有相同的长度、元素和顺序. 继续使用password数组示例,您将创建一个名为password2的第二个数组,其中包含字符n,o,ne:

1char[] password2 = new char[] {'n', 'o', 'n', 'e'};

一旦在jshell中运行此代码,您将收到以下确认:

1[secondary_label Output]
2password2 ==> char[4] { 'n', 'o', 'n', 'e' }

之前的输出确认你有password2数组. 它有四个元素,并且它们也被打印出来。 如果你没有退出以前的jshell会话,你也将有原来的password数组. 如果你退出你的jshell会话,你将不得不使用创建数组中的步骤来重新创建password数组,以便你可以比较两个数组。

现在你可以比较这两个数组,如下:

1System.out.println(Arrays.equals(password, password2));

在上一行中,您正在使用println()方法来打印来自Array.equal()方法的结果,比较passwordpassword2数组。

由于两个数组不同,结果将是错误:

1[secondary_label Output]
2false

输出确认两个数组不等。作为一个练习,创建其他数组并比较它们. 如果两个数组相等,你会得到一个结果。

类型() 方法

「sort()」方法以上升顺序排序一个数组的元素. 使用此方法,您可以按照字母顺序排列「密码」数组中的字符,运行以下操作:

1Arrays.sort(password);

之后,您可以通过在jshell中发出其名称来重新打印数组,以便注意它是如何改变的,如下:

1password;

jshell的输出将是:

1[secondary_label Output]
2password ==> char[6] { 'c', 'e', 'e', 'r', 's', 't' }

这证实了数组仍然有相同的元素,但它们的顺序已经改变了。数组元素已从s,e,c,r,e,tc,e,e,r,s,t重新排序。改变数组的顺序可能不是一个好主意,因为原来的顺序可能很重要。就像密码的情况一样,如果您更改顺序,密码与原来的不同,并且不会起作用。

「BinarySearch()」方法

二进制Search()方法搜索一个数组的元素为一个特定的值。该方法的一个特点是,它需要先排序数组元素;否则,你会得到意想不到的结果。所以,一旦你排序了密码数组,你可以找到一个元素的索引。例如,你可以找出哪个索引字符c密码中,然后打印它,如下:

1System.out.println(Arrays.binarySearch(password, 'c'));

这将产生:

1[secondary_label Output]
20

请记住,现在密码数组被排序,并且看起来像这样:c,e,e,r,s,t。由于数字0被打印,这意味着字符c具有0的索引,因为它是第一个数组元素。

「copyOf()」方法

「copyOf()」方法将给定的数组复制到新数组,当您需要增加或减少数组的大小时。 由于数组的长度无法在创建后更改,您可以使用此方法创建具有所需大小的新数组,其中包含从旧数组复制的内容。

例如,密码数组只能存储六个元素,这不适合当今的安全要求,要增加其大小,您可以使用copyOf()创建一个新的更大的数组,如下:

1password = Arrays.copyOf(password, 10);

在上面的示例中,您将密码的值重新分配给一个新的数组。这个新数组是将旧的密码数组复制到一个长达 10 个元素的新数组的结果。 为了复制它,您使用了Arrays.copyOf()方法,该方法接受两个参数。

当你在jshell中运行前面的代码时,你会得到类似于此的输出:

1[secondary_label Output]
2password ==> char[10] { 'c', 'e', 'e', 'r', 's', 't', '\000', '\000', '\000', '\000' }

前一行显示密码数组现在有10个元素,前六个元素来自原始的密码数组,该数组在字母排序后变成了c,e,e,r,s,t

您也可以通过检查每个数组对象的长度属性来验证新数组有 10 个元素。

1System.out.println(password.length);

在这里,您使用println()方法将password.length作为参数,从jshell的输出将是:

1[secondary_label Output]
210

本节所涵盖的方法是与数组相关的最有用的方法之一,您可以根据 官方数组文件进一步探索数组类中的各种方法。

结论

在本教程中,您使用 Java 数组来组合相关项目,您了解如何创建数组,如何查看它们,以及如何使用其内容,您还了解了与数组工作的最佳实践和有用的方法。

關於Java的更多信息,請參閱我們的 如何在Java中編碼系列。

Published At
Categories with 技术
comments powered by Disqus