首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从子类获取数据: Java

从子类获取数据: Java
EN

Stack Overflow用户
提问于 2012-11-27 07:29:44
回答 5查看 1.7K关注 0票数 0

我是新来的,所以如果我在事故中没有遵守标准的礼仪,我提前道歉。

我想知道如何使用ArrayLists从子类中获取数据。

代码语言:javascript
复制
import java.io.*;
import java.util.*;

public class MyProgrammingLab {

    public static void main(String[] args){
        ArrayList<Test> testArray = new ArrayList<>();

        testArray.add(new Test("First"));
        testArray.add(new SubTest("Last"));

        System.out.println(testArray.get(0).getFirstName());
        System.out.println(testArray.get(1).getLastName());
    }
}

public class Test {
    private String firstName;

    public Test(){
    }

    public Test(String firstName){
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }
}

public class SubTest extends Test{
    private String lastName;

    public SubTest(){
        super();
    }

    public SubTest(String lastName){
        this.lastName = lastName;
    }


    public String getLastName(){
        return lastName;
    }
}

我的主"System.out.println(test.Array.get(1).getLastName());“中的这行代码向我抛出了错误,而我却不知道为什么?

在我的主程序中,我将使用一个大于1的ArrayList。

提前谢谢你!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-11-27 07:34:12

我建议在使用我即将提出的解决方案时要非常谨慎,但是:

代码语言:javascript
复制
System.out.println(((SubTest) testArray.get(1)).getLastName());

但是,只有在确定位置1处的元素是SubTest时才这样做,否则将得到ClassCastException

如果你不确定,你可能应该检查一下。

代码语言:javascript
复制
Test whatIGot = testArray.get(1);
if(whatIGot instanceof SubTest) {
   SubTest whatIActuallyGot = (SubTest)whatIGot;
   System.out.println(whatIActuallyGot.getLastName());
}

通常,当你有一个超类类型的变量时,你应该避免依赖于子类的属性。这样做是一种代码气味,可能是由糟糕的设计引起的。

正确的解决方案应该包括问你自己这两个问题:

  • 你确定getLastName属于SubTest而不是Test吗?如果getLastName()是在Test中,那就解决了你真正需要从getLastName元素访问testArray的问题了--

如果getLastName()确实属于Test( Test的所有实例都有某个姓氏),但是没有合适的默认值,那么可以考虑让Test成为具有抽象方法getLastName的抽象类。请注意,这会使new Test()停止工作。

票数 4
EN

Stack Overflow用户

发布于 2012-11-27 07:47:00

您的列表已声明为Arraylist<Test>。这意味着它很灵活:您可以在其中放置Test的任何实例(包括子类的实例)。

这种灵活性带来了一个限制:稍后,当您再次取出一个元素时,您所能告诉的关于该元素的所有信息就是它是Test的一个实例-正如您已经发现的那样,如果没有特定的类型检查,您就无法判断该条目是Test还是SubTest。(考虑一下,如果列表必须返回条目的确切类型,那么您将如何在ArrayList上编写get方法-该方法的返回类型将根据传入的索引而变化!)

如果您需要这种灵活性(您的示例代码表明您需要这样做,因为您还将Test实例与SubTest一起存储),那么您最简单的选择就是检查类型和类型转换:

代码语言:javascript
复制
Test secondEntry = testArray.get(1);
if (secondEntry instanceof SubTest) {
    System.out.println(((SubTest) secondEntry).getLastName());
}

尽管如其他人所指出的那样,这在某种程度上削弱了使用泛型的意义。

其他替代方案包括:

  • getLastName方法上移到父类,然后在子类中重写它(如果父类具有此方法是有意义的);
  • 用于实现具有基于类型的调度的strategy pattern

这看起来像这样:

代码语言:javascript
复制
import java.io.*;
import java.util.*;

public class MyProgrammingLab {

    public static void main(String[] args) {
        ArrayList<Test> testArray = new ArrayList<Test>();

        testArray.add(new Test("First"));
        testArray.add(new SubTest("Last"));

        for (Test aTest : testArray) {
            emit(aTest);
        }

    }

    public static void emit(Test aTest) {
        if (aTest instanceof SubTest) {
            System.out.println(((SubTest) aTest).getLastName());
        } else {
            System.out.println(aTest.getFirstName());
        }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2012-11-27 07:37:14

testArray.get(1)返回的类型为Test,而不是SubTest。如果您绝对确定它是一个SubTest (您可以使用instanceof进行检查),那么您可以使用

代码语言:javascript
复制
System.out.println(((SubTest) testArray.get(1)).getLastName());
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13574973

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档