首页 > 解决方案 > 为什么 Java 不理解我放在这个多维数组中的对象的类?

问题描述

我正在开发一个小游戏,但为了举例,我将使用假设类 Student 中的对象和假设类 Books 中的对象。

我有一个多维网格,希望由 Student 对象或 Book 对象填充。也许它被称为

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[][],我将无法放入书籍。

标签: javaarraysclassmultidimensional-array

解决方案


对象的类类型classroomObject,当您调用classroom[0][0].age时,Object类不知道您在自己的自定义类中定义的属性。您将需要classroom[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 原则的东西,然后设计一个合适的解决方案。

编辑:我可能不清楚您必须尝试实现什么,但这里有一个示例实现,可能会给您一些想法。通常避免使用对象直接访问变量,而是使用 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
            }
        }
    }

}

推荐阅读