当前位置: 主页 > JAVA语言

java数组定义-java字符数组定义

发布时间:2023-02-11 11:26   浏览次数:次   作者:佚名

java数组定义_java字符数组定义_java定义整型数组

在浏览 Stack Overflow 时,我发现了一些类似 Andes 的问题,例如:What is the most elegant way to print a Java array? 访问量220W+。 没想到这么简单的一个问题,却困扰了这么多程序员

我们来回顾一下提问者的问题:

在 Java 中,数组虽然是对象,但是没有显式定义这样的类,所以没有机会重写 toString() 方法。 如果我们尝试直接打印数组,输出不是我们预期的。 那么有没有简单可行的方法呢?

如果你也被这个问题困扰过,或者正在被困扰,请跟我来,我们一起来梳理这个问题,找到最佳答案。 Duang Duang 打怪前进!

01.为什么不能直接打印

我很好奇,是不是,为什么我不能使用System.out.println()等一系列方法来打印数组呢? 我们来看这样一个例子。

String [] cmowers = {"沉默","王二","一枚有趣的程序员"};
System.out.println(cmowers);

程序打印的结果是:

[Ljava.lang.String;@3d075dc0

[Ljava.lang.String; 表示字符串数组的Class名,@后面的hashCode是16进制的hashCode——这种打印结果太“人性化”了,一般人表示看不懂! 为什么会这样显示? 查看 java.lang.Object 类的 toString() 方法。

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

PS:数组虽然没有明确定义为类,但它确实是一个对象,继承了祖先类Object的所有方法。

那为什么数组不定义一个类来表示呢? 像 String 类?

一个合理的解释是Java隐藏了它。 如果有一个Array.java,我们也可以想象它真实的样子,它必须定义一个容器来存放数组的元素,就像String类一样。

public final class String
    implements java.io.SerializableComparable<String>, CharSequence 
{
    /** The value is used for character storage. */
    private final char value[];
}

但真的有必要吗? 为数组定义一个单独的类是不是有点多余?

02.使用流

如果你使用的是JDK8以上的版本,我们可以使用Stream这种时髦又时髦的方式来遍历数组,顺便打印出来。

首先:

Arrays.asList(cmowers).stream().forEach(s -> System.out.println(s));

第二种:

Stream.of(cmowers).forEach(System.out::println);

第三种:

Arrays.stream(cmowers).forEach(System.out::println);

打印结果如下。

沉默
王二
一枚有趣的程序员

没错,这三个方法可以轻松胜任他们的工作,而且显得有点高大上,毕竟用到了Stream和lambda表达式。 但它们并不是我心目中最优雅的方式。

03.使用for循环

当然如果你不喜欢Stream的方式,也可以使用for循环顺便打印数组的变量,甚至for-each。

for(int i = 0; i < cmowers.length; i++){
    System.out.println(cmowers[i]);
}

for (String s : cmowers) {
    System.out.println(s);
}

但是如果你是一个有抱负的程序员java数组定义,你不禁会觉得这个方法有点low。 那么最优雅的方式是什么?

04. 使用 Arrays.toString()

Arrays.toString() 可以将任何类型的数组转换为字符串,包括基本类型数组和引用类型数组。 我们截图感受一下。

java数组定义_java字符数组定义_java定义整型数组

Arrays类不需要我介绍吧? 虽然大家明白我的意思,但我还是忍不住废话:这个类包含各种操作数组的方便方法。 与其将其命名为 Arrays,不如将其命名为 ArrayUtil。

没有什么比使用 Arrays.toString() 方法打印数组更优雅的了,就像蒙娜丽莎的微笑一样。

java定义整型数组_java字符数组定义_java数组定义

你觉得好笑吗? 来吧,好好看看代码示例。

String [] cmowers = {"沉默","王二","一枚有趣的程序员"};
System.out.println(Arrays.toString(cmowers));

程序打印结果:

[沉默, 王二, 一枚有趣的程序员]

哇,打印格式不要太完美,不多也不少! 正是我们所期望的:[] 表示一个数组,点和空格用于分隔元素。

顺便看看toString()方法的源码。

public static String toString(Object[] a) {
    if (a == null)
        return "null";

    int iMax = a.length - 1;
    if (iMax == -1)
        return "[]";

    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; ; i++) {
        b.append(String.valueOf(a[i]));
        if (i == iMax)
            return b.append(']').toString();
        b.append(", ");
    }
}

1)如果数组为null,则返回“null”字符串,很贴心,省去了NullPointerException的麻烦。

2)如果数组长度为0,则返回“[]”字符串。 注意这里没有使用a.length == 0进行空判断,而是使用了a.length - 1 == -1,为后面的for循环中的i == iMax做铺垫,资源获取不到全部。 没有浪费。

3)for循环中的字符串拼接更是巧妙。 for循环的条件不判断i < a.length,而是在循环体中使用i == iMax。 这样做有什么好处?

一般来说java数组定义,这就是普通程序员在拼接字符串时所做的事情。

StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; i < cmowers.length; i++) {
    b.append(cmowers[i]);
    b.append(", ");
}
b.delete(b.length()-2, b.length());
b.append(']');

没错,很乖,但是和toString()方法源码中的写法相比,就显得苍白无力了。 不禁感慨:要想成为优秀的程序员,而不仅仅是普通的程序员,最快的捷径就是学习Java的源代码。

05. 使用 Arrays.deepToString()

如果需要打印多维码数组,Arrays.toString()也无能为力。

String[][] deepArray = new String[][] {{"沉默""王二"}, {"一枚有趣的程序员"}};
System.out.println(Arrays.toString(deepArray));

打印结果如下。

[[Ljava.lang.String;@7ba4f24f, [Ljava.lang.String;@3b9a45b3]

不不不,这不是我们期待的结果,怎么办? 使用专为多维数组设计的 Arrays.deepToString()。

String[][] deepArray = new String[][] {{"沉默""王二"}, {"一枚有趣的程序员"}};
System.out.println(Arrays.deepToString(deepArray));

打印结果如下。

[[沉默, 王二], [一枚有趣的程序员]]

出色的! 至于deepToString()的源码,本文不再分析。 如果您有兴趣,请自己看看。 (想要优秀,一定要看)