【问题标题】:Java: Generic Static Multidimensional ArraysJava:通用静态多维数组
【发布时间】:2011-10-28 02:19:42
【问题描述】:

如果可能的话,如何在 Java 中创建一个 static 多维数组,每个维度具有不同的原始数据类型?

我所说的静态,是指不像 ArrayList 那样动态的原始数组。

【问题讨论】:

  • Object[] arr = {new Integer[]{}, new String[]{}, new Double[]{}};
  • @BheshGurung 是的,我想通了。这是相当明显的。 ;)
  • 是的,我看到我打字太慢了。

标签: java arrays generics multidimensional-array static-array


【解决方案1】:

你不能。

根据定义,多维数组是由数组的数组组成的数组......因此,除了最后一个维度之外,这些维度中的任何一个都无法成为数组以外的任何维度。至少,无论如何,按照传统定义。但是,如果您所说的“多维数组”是其他意思,您需要告诉我们它是什么。

至于“静态”,它在编程中是一个重度重载的词,我能想到的每种语言都用它来表示稍微不同的东西。在 Java 中,static 表示“属于一个类,而不是该类的实例”。同样,如果您在这里所说的“静态”指的是其他意思,您需要告诉我们那是什么。

编辑:正如最初发布的那样,问题不包括“原始”一词。这有点改变。事实上,我同意从方便的角度来看,如果 Java 允许使用 char 甚至是 enum 而不仅仅是 int 来索引数组,那将是一件好事。但事实并非如此。

【讨论】:

  • 静态数组是指不像 ArrayList 那样动态的数组。我会在我的问题中添加它。
  • 很抱歉没有包含“原始”一词。
  • primitivestatic 我猜他的意思是 unchangeable in size
【解决方案2】:

数组中的维度总是来自 int 类型。想想吧!

int a = 4;
int b = 5;

Shoe shoe = new Shoe (Color.RED, 42, "Leather");
Hat hat = new Hat (17, Color.Black);

Foo foo = foos[a][b];
Zilch pop = bars[shoe][hat]; // no go

如果你有一个 Foos 的多维数组,第一维是 Foo,第二维是 Foos 数组,第三维是 Foo 数组。唯一的变量类型是底部的那个。

问题更新后编辑:

数组不称为静态或原始数组。它们的大小在初始化时是固定的,它们与原语的共同点是,它们是内置的,在某些情况下被威胁为特殊。它们是 - 与所谓的原始类型相反,它们不是原始类型(例如,它们有专门为它们自己的运算符,如* / -)但同时它们是对象,但未在库中声明。

打电话给他们build in-types

使用 Bhesh Gurung 的把戏:

Object[] arr = {new Integer[]{}, new String[]{}, new Double[]{}}; 

是在自找麻烦,而且它不是由每个维度的不同数据类型组成的。让我们从尺寸开始:

// One-dimensional object:
JPanel [] panels = new JPanel [3]; 
// Two-dimensional object:
JPanel [][] panels = new JPanel [3][10]; 

底层有 JPanel,下一个维度有一个 JPanel 数组。您可以添加更多维度,并且总是会得到一个额外的 (Array of ...)。

您不能在数组中混合不同的数据类型,例如 int 和 char,或 JPanel 和 JFrame,或 int 和 JButton。仅当您抽象出差异,并将 JComponent 用于 JPanel 和 JFrame 作为公共父级时,但这不适用于内置类型 int、char、boolean 等,因为它们不是对象。

但是你不能用自动装箱,用Integer代替int,用Character代替char,然后用Object作为公共父类吗?是的,你可以,但是你不再使用原语,你在乞求麻烦。

Dan 在谈论不同的事情——在多维数组中使用不同的类型进行索引:

byte  b = 120;
short s = 1000;
String o [][] = new String[b][s];
b = 7;
s = 9;  
o[b][s] = "foobar";
String foo = o[b][s];

使用 bytes 或 short 没有问题,但不能通过将 Array 声明为 byte 或 short 来限制其大小。在大多数情况下,内置整数类型的边界不适合数据类型(想想每年 365 天),特别是因为所有类型都可能变为负数,所以边界检查是必要的,但不能仅限于编译时间。

但现在麻烦了:
我们可以从一开始就将数组声明为二维:

Object[][] ar2 = {
    new Integer [] {4, 5, 6}, 
    new String [] {"me", "and", "you"}, 
    new Character [] {'x', 'y', 'z'}};

这很好用,并且无需强制转换即可立即访问内部数组。但是只有编译器知道,元素是 Object 数组——底层类型被抽象掉了,所以我们可以这样写:

ar2[1][1] = 17; // expected: String
ar2[2][0] = "double you"; // expected: Char

这将完美地编译,但你是在自找麻烦并免费获得一个运行时异常。

这是一个整体的来源:

public class ArrOfMixedArr
{
    public static void main (String args[])
    {
        Object[] arr = {
            new Integer [] {1, 2, 3}, 
            new String [] {"you", "and", "me"}, 
            new Character [] {'a', 'b', 'c'}};
        show (arr);
        
        byte b = 7;
        short s = 9;
        String o [][] = new String[200][1000];
        o[b][s] = "foobar";
        String foo = o[b][s];
        
        Object[][] ar2 = {
            new Integer [] {4, 5, 6}, 
            new String [] {"me", "and", "you"}, 
            new Character [] {'x', 'y', 'z'}};
        show (ar2);

        // exeptions:
        ar2[1][1] = 17; // expected: String
        ar2[2][0] = "double you"; // expected: Char
    }

    public static void show (Object[] arr)
    {
        for (Object o : arr) 
        {
            if (o instanceof Object[])
                show ((Object[]) o);
            else 
                System.out.print (o.toString () + "\t");
        }
        System.out.println ();
    }
}

现在有什么解决办法? 如果您的 (int, byte, char, String, JPanel, ...) 的基本类型数组长度相等,那么您就有了类似于隐藏对象、数据库行的东西。改用类:

class Shoe {
    byte size;
    String manufactor;
    java.math.BigDecimal price;
    java.awt.Color color;
}

Shoe [] shoes = new Shoe [7];

如果你没有相同大小的不同类型,它们可能是不相关的,不应该放在一个公共容器中。

【讨论】:

    【解决方案3】:

    经过一些测试,我有一个简单的解决方案:

    Object [][] array = new Object [10][2];
    array[0][0] = 2;
    array[0][1] = false;
    

    【讨论】:

    • 从这样的数组中提取值的最佳方法是什么?在 C# 中,它的 Convert.ToInt32 等,不确定 java
    • 在一个数组中组合不同的类型是不好的做法,应该避免。您需要知道数组中的哪些元素属于哪种类型,某些东西,编译器无法保证,所以这是规避类型系统,也就是自找麻烦,您必须使用额外的技术来记住类型/职位。在位置 array[1][0],你会再次有一个 int,在 (1,1) 处有一个布尔值吗?
    【解决方案4】:

    好吧,你可以定义一个数组数组......一个对象数组(嵌套的级别与维度一样多),并在底层用不同的类型填充每个数组。 .. 然后,当您需要提取一个值时,将其转换为适当的类型。为有价值的东西付出太多的工作,真的。 Java 不适合这种事情,因为它是一种静态类型的语言。

    也许你应该重新考虑一下,为什么需要这样的数据结构。

    【讨论】:

      【解决方案5】:

      使用对象数组可以得到效果:

      final static Object tryit[][] = {
              {'a',4},
              {'b',7},
              {'c',8},
      };
      @Test
      public void accessArray( ) {
          for (int i = 0; i < tryit.length ; i++) {
              char letter = (Character)tryit[i][0];
              int value = (Integer)tryit[i][1];
              System.out.println(letter + " has value " + value);
          }
      }
      

      “@Test”是JUnit注解。

      请注意,如果在数组中输入了错误的数据,这种方法在运行时会出现 NullPointer 和 ClassCast 异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-23
        • 2018-09-03
        • 2013-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-10
        • 2023-04-08
        相关资源
        最近更新 更多