如何从另一个类中定义的类创建数组

Posted

技术标签:

【中文标题】如何从另一个类中定义的类创建数组【英文标题】:How to make an array from a class defined inside another class 【发布时间】:2016-06-27 02:53:46 【问题描述】:

我是一名 Java 程序员新手,试图使用在不同文件中定义的类。所以,我写了这两个 .java 文件:

首先是 MyLibrary.java:

package mymainprogram;

public class MyLibrary 
    public class MyRecord 
        int number;
        char letter;
    

    public static int TriplePlusThree(int input_number)             
        return ((input_number*3) + 3);
    

然后,MyMainProgram.java:

package mymainprogram;

import java.util.Scanner;

public class MyMainProgram 
    public static void main(String[] args) 
        Scanner keyread = new Scanner(System.in);

        System.out.print("Enter Number to Process: ");
        int num = keyread.nextInt();  
        int result = MyLibrary.TriplePlusThree(num);
        System.out.println("3x + 3 = "+result);

        String letters = "ABCDEFGHIJ";
        MyLibrary.MyRecord[] TenRecs = new MyLibrary.MyRecord[10];

        for (int i = 0; i < 10; i++) 
            TenRecs[i].number = i;      //NullPointerException here
            TenRecs[i].letter = letters.charAt(i);           
        
    

让该方法正常工作没有问题;现在我的目标是创建一个数组,其中数组的每个成员都有一个整数和字符。 (注意:我不是在寻找更好的方法来实现这个目标;我只是在使用这个简单的例子来尝试让它工作)。

当我尝试运行我的程序时,我得到了:

java.lang.NullPointerException

我研究了这个,发现this page,上面写着:

如果我们在创建对象之前尝试访问它们,就会发生运行时错误。例如,以下语句在运行时抛出 NullPointerException,这表明 [this array] 尚未指向 [an] 对象。对象必须使用类的构造函数进行实例化,并且它们的引用应按以下方式分配给数组元素。

studentArray[0] = new Student();

所以,我尝试在我的主程序中这样做:

MyRecordArray[0] = new MyLibrary.MyRecord();

但这给出了这个错误:

需要包含 MyLibrary.MyRecord 的封闭实例

那个错误信息把我带到了this Stack Exchange question,上面写着:

你必须创建一个 X 类(外部类)的对象,然后使用 objX.new InnerClass() 语法来创建一个 Y 类的对象。

X x   = new X();
X.Y y = x.new Y();

所以,根据那个答案,我在我的程序中添加了这两行:

MyLibrary mylibrary         = new MyLibrary();
MyLibrary.MyRecord myrecord = mylibrary.new MyRecord();

那些行没有给出任何警告或编译错误,所以我觉得我更近了一步,但我仍在试图弄清楚如何制作一个数组。我知道如果我想创建一个整数数组,我会这样做:

int[] TenInts = new int[10];

所以,我尝试过类似的方法:

myrecord[] TenRecs = new myrecord[10];
MyRecord[] TenRecs = new MyRecord[10];

但是没有任何效果,我觉得我现在正在抓住稻草。我觉得正确的眼睛可以很快解决这个问题。

【问题讨论】:

【参考方案1】:

您需要将内部类声明为静态。

您可以修改如下代码以满足您的要求:

这是 MyLibrary 的代码

public class MyLibrary 

    public static class MyRecord
        int number;
        char letter;

        public MyRecord()
            number = 0;
            letter = '\0';
        

        public MyRecord(int number, char letter)
            this.number = number;
            this.letter = letter;
        
    

    public static int TriplePlusThree(int input_number) 
        return (input_number * 3 + 3);
    

这是 MyMainProgram 的代码

import java.util.Scanner;

public class MyMainProgram 

    public static void main(String[] args)
        Scanner in = new Scanner(System.in);
        System.out.println("Enter number to process");
        int num = in.nextInt();
        System.out.println("3x + 3 = " + MyLibrary.TriplePlusThree(num));

        String letters = "ABCDEFGHIJ";
        MyLibrary.MyRecord[] TenRecords = new MyLibrary.MyRecord[2];

        for (int i=0; i<TenRecords.length; i++)
            TenRecords[i] = new MyLibrary.MyRecord();
            TenRecords[i].number = i;
            TenRecords[i].letter = letters.charAt(i); 
        

        // Printing class records
        for (int i=0; i<TenRecords.length; i++)
            System.out.println("Printing records of record " + i + " : ");
            System.out.println("Number : " + TenRecords[i].number);
            System.out.println("Letter : " + TenRecords[i].letter);
        
        in.close();
    

可以如下创建内部类的实例:

TenRecords[i] = new MyLibrary.MyRecord();

希望这会有所帮助。

【讨论】:

【参考方案2】:

嵌套类MyRecord 包含对外部类MyLibrary 的隐藏引用,因此必须与MyLibrary 的实例相关联。这样MyRecord 可以访问MyLibrary 的私有成员。

MyLibrary.MyRecord myrecord = mylibrary.new MyRecord();

哇,这是一个有趣的语法。在我所有的 Java 编程生涯中,我从未使用过这样的结构。通常,您会在外部类 (MyLibrary) 中创建内部类 (MyRecord) 的对象。另一个常见的事情是将内部类声明为static,这样就不需要外部类的实例了。


MyRecord[] TenRecs = new MyRecord[10];

这将创建一个所有元素都为 NULL 的数组。您必须初始化它们中的每一个(例如使用循环)。

【讨论】:

我承认,这是一个有趣的语法。我只是想遵循另一个答案的语法,该答案获得了 50 个赞。【参考方案3】:

如果您初始化 MyRecord[10] 数组有空对象。您仍然需要将数组中的每个元素初始化为一个新的MyRecord 对象。否则你会得到NPE

一种方法是:List&lt;MyRecord&gt; TenRecs = new ArrayList&lt;MyRecord&gt;(); TenRecs.add( new MyRecord() );

for ( int i = 0; i &lt; 10; i++ ) TenRecs[i] = new MyRecord();

如果你添加一个导入语句:import mymainpackage.MyLibrary.MyRecord;你不需要做mylibrary.new MyRecord();只需做new MyRecord();

【讨论】:

【参考方案4】:

您必须在初始化之前在数组中创建每个对象。参考this link。

像这样创建每个对象。

MyLibrary outer = new MyLibrary();
TenRecs[i] = outer.new MyRecord();

完整代码:

MyLibrary.MyRecord[] TenRecs = new MyLibrary.MyRecord[10];

    for (int i = 0; i < 10; i++) 
        MyLibrary outer = new MyLibrary();
        TenRecs[i] = outer.new MyRecord();
        TenRecs[i].number = i; 
        TenRecs[i].letter = letters.charAt(i);  
    

【讨论】:

【参考方案5】:

有几点需要注意。 一、实例内部类和静态内部类的区别。

一个实例内部类,声明时没有static 修饰符,

public class OutterClass 
    public class InstanceInnerClass 

应该这样创建:

OutterClass outter = new OutterClass();
InstanceInnerClass iInner = outter.new InstanceInnerClass();

虽然是静态内部类,使用static 修饰符声明,

public class OutterClass 
    public static class StaticInnerClass 

应该这样创建:

StaticInnerClass sInner = new OutterClass.StaticInnerClass();

其次,您在填充之前访问了一个数组条目

MyLibrary library = new MyLibrary();
MyLibrary.MyRecord[] TenRecs = new MyLibrary.MyRecord[10];
for (int i = 0; i < 10; i++) 
    // Create new instance
    TenRecs[i] = library.new MyRecord();
    TenRecs[i].number = i;
    TenRecs[i].letter = letters.charAt(i);

【讨论】:

以上是关于如何从另一个类中定义的类创建数组的主要内容,如果未能解决你的问题,请参考以下文章

从另一个视图控制器中的类中快速绘制形状(以编程方式)

如何在 Ocaml 中使用类中定义的类型作为 val?

我想从另一个反应原生的一个类中更改一个静态数组

JavaFX 使用 Platform.runLater 从另一个线程更新 TextArea

从另一个类中的 UITextField 访问文本

如何在继承 SKSpritenode 的类中拥有图像