繁体   English   中英

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

[英]Why doesn't Java understand the class of the object I've placed in this multi-dimensional array?

我正在做一个小游戏,但是为了举例,我将使用假设类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 [] [],那么我将无法放入书籍。

对象classroom的类类型为Object ,当您调用classroom[0][0].ageObject类不了解您在自定义类中定义的属性。 您需要像这样将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原则的知识,然后设计一个合适的解决方案。

编辑:关于您必须要实现的目标,我可能不清楚,但是这里有一个示例实现,可能会给您一些想法。 通常,避免直接使用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
            }
        }
    }

}

与动态类型的Javascript相反,Java被称为静态类型的语言。 这意味着,每个表达式的类型都应该在Java编译时就知道了。 classroom声明为Object[][] ,表达式classroom[0][0]类型为Object并且此类型没有age字段。 您需要像这样将表达式显式转换为Student

if (classroom[0][0] instanceof Student)
    System.out.println(((Student)classroom[0][0]).age);

或将教室元素的类型更改为具有age属性的内容。

如果要将不同类型的对象存储在同一数组中,并且仍然能够在不进行显式类型强制转换的情况下访问公共属性,请将公共属性移至公共超类,例如:

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

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

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

ClassroomObject [][] classroom;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM