Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java不理解我放在这个多维数组中的对象的类?_Java_Arrays_Class_Multidimensional Array - Fatal编程技术网

为什么Java不理解我放在这个多维数组中的对象的类?

为什么Java不理解我放在这个多维数组中的对象的类?,java,arrays,class,multidimensional-array,Java,Arrays,Class,Multidimensional Array,我正在做一个小游戏,但为了举例,我将使用来自假设类学生的对象和来自假设类课本的对象 我有一个多维网格,希望由学生对象或书本对象填充。也许它叫 classroom[][] 有四张桌子: [0][0], [0][1], [1][0], and [1][1]. 我希望能够放置一个学生或一本书,而不是两者都放,并且能够打印 classroom[0][1].someStudentAttribute 如果我知道是个学生或者 classroom[0][1].someBookAttribute

我正在做一个小游戏,但为了举例,我将使用来自假设类学生的对象和来自假设类课本的对象

我有一个多维网格,希望由学生对象或书本对象填充。也许它叫

classroom[][] 
有四张桌子:

[0][0], [0][1], [1][0], and [1][1].
我希望能够放置一个学生或一本书,而不是两者都放,并且能够打印

classroom[0][1].someStudentAttribute 
如果我知道是个学生或者

 classroom[0][1].someBookAttribute 
如果我知道这是一本书

要明确的是,当它是一个学生或一本书时,它将是显而易见的。我不需要一个万无一失的方法来区分,也就是说,我只会在代码中使用.someStudentAttribute,当它肯定是一个学生在那张桌子上时

我在这里的某个地方读到,我可以创建一个多维数组,通过在名称前声明变量类型Object[]]来接受多种类型的对象

Student alice = new Student("alice", 10);
Student bob = new Student("bob", 11);
Student charlie = new Student("charlie", 10);
Book mathBook = new Book("mathematics", 578);

Object[][] classroom = new Object[2][2];
classroom[0][0] = alice;
classroom[0][1] = bob;
classroom[1][0] = charlie;
classroom[1][1] = mathBook;
这将返回正确的类学生

System.out.println(classroom[0][0].getClass());
这也会返回正确的类目

System.out.println(classroom[1][1].getClass()):
但一旦我尝试打印属性,就会出现错误:

System.out.println(classroom[0][0].age);
错误是:

java: cannot find symbol
symbol: variable age
location: java.lang.Object
看起来Java忘记了这一点

classroom[0][0] 
只要我要求属性,它就属于学生类!如果

classroom[0][0] 
表示数组插槽中的对象不是正确的方法,是什么

可能与将变量声明为Object[][]有关,但重点还是要能够将来自不同类的对象放入其中。如果我只是叫它Student[][],我就无法把它放进书中。

对象教室的类类型是object,正如您所称的教室[0][0]。年龄,对象类不知道您在自定义类中定义的属性。您需要将教室[0][0]强制转换为自定义类,如下所示:

if (classroom[0][0] instanceof Student) { // Although it is a bad practice and against OOP
    System.out.println(((Student)classroom[0][0]).age);
}
我建议读一些关于OOP原理的东西,然后设计一个合适的解决方案

编辑:我可能不清楚您必须努力实现什么,但下面是一个示例实现,它可能会给您一些想法。通常避免直接使用on对象访问变量,而是使用getter/setter

查看这个示例实现

public class Classroom {

    enum ClassRoomObjectType {
        STUDENT,BOOK;
    }

    static abstract class ClassRoomObject {
        private String name;
        private int age;
        private ClassRoomObjectType classRoomObjectType;

        protected ClassRoomObject(ClassRoomObjectType classRoomObjectType, String name, int age) {
            this.classRoomObjectType = classRoomObjectType;
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return String.format("Type: %s, Name: %s, Age: %s", classRoomObjectType, name, age);
        }
    }

    static class Student extends ClassRoomObject {

        public Student(String name, int age) {
            super(ClassRoomObjectType.STUDENT, name, age);
        }

    }

    static class Book extends ClassRoomObject {

        public Book(String name, int age) {
            super(ClassRoomObjectType.BOOK, name, age);
        }

    }

    public static void main(String[] args) {
        Student alice = new Student("alice", 10);
        Student bob = new Student("bob", 11);
        Student charlie = new Student("charlie", 10);
        Book mathBook = new Book("mathematics", 578);

        ClassRoomObject[][] classRoomObjects = new ClassRoomObject[2][2];
        classRoomObjects[0][0] = alice;
        classRoomObjects[0][1] = bob;
        classRoomObjects[1][0] = charlie;
        classRoomObjects[1][1] = mathBook;

        for(int i=0;i<2;i++) {
            for(int j=0;j<2;j++) {
                System.out.println(classRoomObjects[i][j]); // This is how you can print the object content by overriding toString method
                System.out.println(classRoomObjects[i][j].getAge()); // This is how you should access the value of an object attribute by using getters and not directly the variable
            }
        }
    }

}
对象教室的类类型为object,正如您所调用的教室[0][0]。年龄,对象类不知道您在自己的自定义类中定义的属性。您需要将教室[0][0]强制转换为自定义类,如下所示:

if (classroom[0][0] instanceof Student) { // Although it is a bad practice and against OOP
    System.out.println(((Student)classroom[0][0]).age);
}
我建议读一些关于OOP原理的东西,然后设计一个合适的解决方案

编辑:我可能不清楚您必须努力实现什么,但下面是一个示例实现,它可能会给您一些想法。通常避免直接使用on对象访问变量,而是使用getter/setter

查看这个示例实现

public class Classroom {

    enum ClassRoomObjectType {
        STUDENT,BOOK;
    }

    static abstract class ClassRoomObject {
        private String name;
        private int age;
        private ClassRoomObjectType classRoomObjectType;

        protected ClassRoomObject(ClassRoomObjectType classRoomObjectType, String name, int age) {
            this.classRoomObjectType = classRoomObjectType;
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return String.format("Type: %s, Name: %s, Age: %s", classRoomObjectType, name, age);
        }
    }

    static class Student extends ClassRoomObject {

        public Student(String name, int age) {
            super(ClassRoomObjectType.STUDENT, name, age);
        }

    }

    static class Book extends ClassRoomObject {

        public Book(String name, int age) {
            super(ClassRoomObjectType.BOOK, name, age);
        }

    }

    public static void main(String[] args) {
        Student alice = new Student("alice", 10);
        Student bob = new Student("bob", 11);
        Student charlie = new Student("charlie", 10);
        Book mathBook = new Book("mathematics", 578);

        ClassRoomObject[][] classRoomObjects = new ClassRoomObject[2][2];
        classRoomObjects[0][0] = alice;
        classRoomObjects[0][1] = bob;
        classRoomObjects[1][0] = charlie;
        classRoomObjects[1][1] = mathBook;

        for(int i=0;i<2;i++) {
            for(int j=0;j<2;j++) {
                System.out.println(classRoomObjects[i][j]); // This is how you can print the object content by overriding toString method
                System.out.println(classRoomObjects[i][j].getAge()); // This is how you should access the value of an object attribute by using getters and not directly the variable
            }
        }
    }

}

Java被称为静态类型语言,与Javascript(动态类型)形成对比。这意味着,在Java中,每个表达式的类型在编译时都应该是已知的。一旦教室被声明为对象[],表达式教室[0][0]就具有类型对象,而此类型没有年龄字段。您需要将表达式显式强制转换为Student,如下所示:

if (classroom[0][0] instanceof Student)
    System.out.println(((Student)classroom[0][0]).age);
或者将教室元素的类型更改为具有年龄属性的类型

如果要将不同类型的对象存储在同一数组中,并且仍然能够访问公共属性而无需显式类型转换,请将公共属性移动到公共超类,例如:

class ClassroomObject {
    // Common stuff
    public int age;
}

class Book extends ClassroomObject {
    // Book-specific stuff
}

class Student extends ClassroomObject {
    // Student-specific stuff
}

ClassroomObject [][] classroom;

Java被称为静态类型语言,与Javascript(动态类型)形成对比。这意味着,在Java中,每个表达式的类型在编译时都应该是已知的。一旦教室被声明为对象[],表达式教室[0][0]就具有类型对象,而此类型没有年龄字段。您需要将表达式显式强制转换为Student,如下所示:

if (classroom[0][0] instanceof Student)
    System.out.println(((Student)classroom[0][0]).age);
或者将教室元素的类型更改为具有年龄属性的类型

如果要将不同类型的对象存储在同一数组中,并且仍然能够访问公共属性而无需显式类型转换,请将公共属性移动到公共超类,例如:

class ClassroomObject {
    // Common stuff
    public int age;
}

class Book extends ClassroomObject {
    // Book-specific stuff
}

class Student extends ClassroomObject {
    // Student-specific stuff
}

ClassroomObject [][] classroom;

就编译器而言,其中所有内容的类型都只是对象。对象没有年龄。如果您知道课堂[1][1]实际上是一本书,那么您必须在代码中表达更多信息;阅读有关铸造的文章。但更广泛的问题似乎是,这并不是如何使用类型化语言。您有一个对象[]。就编译器而言,在每个索引处都有对象。对象肯定没有年龄字段。您是否希望对象student=。。。;要编译的学生年龄?老实说,异类数组很可能不是您想要的。@jonrsharpe我根据错误消息怀疑这一点,但在执行.getClass时被抛出,但仍然收到了正确的类。我的意思是我知道物体是一本书
因为代码实际上是专门将一本书放在教室[1][1],人类读者不应该推断它是一本书。我认为这足以让代码理解一个Book对象被放置在那里。如果没有办法将不同的类对象放入同一个数组中,我将不得不学习更多关于Java的知识,以了解如何做我想做的事情!getClass之所以能够工作,是因为对象确实具有该方法,所以它可以愉快地编译,并且在运行时您确实可以看到相应的类。但是编译器将嵌套数组中的每一项都视为对象,因为这是您告诉它的。数组引用的编译时类型和引用值的运行时类型之间存在差异。就编译器而言,其中的每一项的类型都只是对象。对象没有年龄。如果您知道课堂[1][1]实际上是一本书,那么您必须在代码中表达更多信息;阅读有关铸造的文章。但更广泛的问题似乎是,这并不是如何使用类型化语言。您有一个对象[]。就编译器而言,在每个索引处都有对象。对象肯定没有年龄字段。您是否希望对象student=。。。;要编译的学生年龄?老实说,异类数组很可能不是您想要的。@jonrsharpe我根据错误消息怀疑这一点,但在执行.getClass时被抛出,但仍然收到了正确的类。我所说的“我知道对象是一本书”是因为代码实际上是专门将一本书放在教室[1][1],而不是人类读者应该推断它是一本书。我认为这足以让代码理解一个Book对象被放置在那里。如果没有办法将不同的类对象放入同一个数组中,我将不得不学习更多关于Java的知识,以了解如何做我想做的事情!getClass之所以能够工作,是因为对象确实具有该方法,所以它可以愉快地编译,并且在运行时您确实可以看到相应的类。但是编译器将嵌套数组中的每一项都视为对象,因为这是您告诉它的。数组引用的编译时类型和引用值的运行时类型之间存在差异。谢谢。我一定要确保我的代码没有违反任何法律。我只需要继续学习更多的Java,以了解如何做我想做的事情@Jonathan注意到,您也可以愉快地在教室[0][0]中写书;编译器会接受这一点,但在运行时会得到ClassCastException。然后您的代码开始填充学生{…}的if项实例。谢谢。我一定要确保我的代码没有违反任何法律。我只需要继续学习更多的Java,以了解如何做我想做的事情@Jonathan注意到,您也可以愉快地在教室[0][0]中写书;编译器会接受这一点,但在运行时会得到ClassCastException。然后您的代码开始填充if item instanceof Student{…}。或者接口中的共享接口no字段,不幸的是。啊,这是真的,只有方法。如果这些字段是通过getter和setter访问的,那么它们可能是一个接口。或者是一个共享接口。令人遗憾的是,接口中没有字段。啊,这是真的,只有方法。如果字段是通过getter和setter访问的,那么它们可能是一个接口。