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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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_Object_Foreach_Iterator - Fatal编程技术网

Java 访问数组中子类的字段

Java 访问数组中子类的字段,java,arrays,object,foreach,iterator,Java,Arrays,Object,Foreach,Iterator,我在Java中测试继承,我有一个带有两个字段的抽象类和三个带有自己字段的扩展类。在另一个类中,我实例化并在数组中添加该类的对象,但我不确定如何访问子类的字段,该数组是主抽象类: 以下是抽象类和扩展类之一的完整代码: public abstract class MusicRecord { private String type; private int length; public MusicRecord(String type, int length){ t

我在Java中测试继承,我有一个带有两个字段的抽象类和三个带有自己字段的扩展类。在另一个类中,我实例化并在数组中添加该类的对象,但我不确定如何访问子类的字段,该数组是主抽象类:

以下是抽象类和扩展类之一的完整代码:

public abstract class MusicRecord {
    private String type;
    private int length;
  
    public MusicRecord(String type, int length){
    this.type = type;
    this.length = length;
    }
  
    public String getType(){
    return type;
    }
    public int getLength(){
    return length;
    }
  
    public void setType(String type){
    this.type = type;
    }
  
    public void setLength(int length){
        this.length = length;
    }
  
    }
如何从子类中获取字段

通过访问子类的字段,数组是主要的抽象类:

java类型系统是协变的。(除了在泛型中,方差是可选择的,并且默认情况下,不变的)。对于本答案的其余部分,您需要了解:

  • Integer扩展了java.lang.Number
  • Double扩展了java.lang.Number
  • java.lang.Number扩展了java.lang.Object
协方差意味着您可以采用类型为
Integer
的表达式,并在需要
数字的地方使用它:当需要超类型时,任何子类型都可以。(不变性意味着只有特定类型的数字表达式才可以,反之亦然:如果需要整数,数字或对象也可以)

因此:

一切都好

这也意味着,如果你把它翻过来,如果一个表达式是Number类型的,那么它很可能是Number的某个子类型。鉴于这个数字是抽象的,这实际上是一种保证!数字本身不可能存在,只能存在其子类的实例

您可以使用instanceof和casting以及模式匹配来处理此问题:

注意:这使用了java15中引入的新java特性

Object[] x = new Object[2];
x[0] = "hello";

if (x[0] instanceof String y) {
    y.toLowerCase();
}
这里我们首先检查
x[0]
是否为字符串(可能是。也可能是整数,也可能是FileInputStream,也可能是
com.sun.internal.impl.HttpRequestImpl$1
——协方差意味着实际的事物类型可能是,通常是一些内部细节,这些细节无法保证,并且可以在java版本和实现之间更改).如果它是一个字符串,那么对于所有只有在它是字符串时才能访问的代码(这里是If块的内部),
y
作为变量存在,并且包含对完全相同的对象的引用,但这次是作为字符串键入的,因此您可以自由调用它上的字符串方法,例如
.toLowerCase()

如果您尚未使用JDK15,“旧”方法是:

if (x[0] instanceof String) {
    String y = (String) x[0];
    y.toLowerCase();
}
这就是所谓的cast操作符,它只是一个类型断言:如果
x[0]
确实是一个字符串,那么这段代码什么也不做。这就像你写的(
String y=x[0];
),除了不会编译之外,效果是一样的:y现在指向同一个东西
x[0]
指出,cast只告诉编译器您知道这是断言类型,并添加运行时测试)

另一方面,如果
x[0]
没有指向某个j.l.String实例,则该行将抛出ClassCastException

因此,您可以执行以下操作:

int totalPrice = 0;
for (MusicRecord mr : records) {
    if (mr instanceof CD cd) totalPrice += cd.price;
}

注意:用java编写的正确方法是
Cd
,而不是
Cd
。当然,按照惯例,java规范允许您编写任何您想要的东西。但是,如果您希望您的代码与库交互良好,并可供其他java代码编写者阅读,那么遵循既定惯例是一个好主意,这些惯例规定您必须全部使用这些东西,即使是缩写词,在普通写作中,都是以大写形式呈现的。DvdPlayer,而不是DvdPlayer。Cd,而不是Cd。当你使用它时,直接字段访问按惯例是不好的-改为制作getter。应该是
Cd.getPrice()

多亏了Lino、Rzwitserroot和Federico klez Culloca,我才能够通过以下补充解决这个问题

for(MusicRecord r : mr){
      if(r instanceof CD){
        System.out.println("Type: " + r.getType() + "\nLength: " + r.getLength() + "\nTitle: " + ((CD)r).getTitle() + "\nPrice: " + ((CD)r).getPrice() + "\n ***************");
      } else if (r instanceof SD){
        System.out.println("Type: " + r.getType() + "\nLength: " + r.getLength() + "\nTitle: " + ((SD)r).getTitle() + "\nPrice: " + ((SD)r).getPrice() + "\n ***************");
      } else {
        System.out.println("Type: " + r.getType() + "\nLength: " + r.getLength() + "\nTitle: " + ((BlueRay)r).getTitle() + "\nPrice: " + ((BlueRay)r).getPrice() + "\n ***************");
      }

为什么你想从子类中获取字段?我不太明白你想要实现什么。你想使用多态性来打印每个子类的特定内容->创建一个被覆盖的方法。你只是想专门访问字段->使用
instanceof
和castsIf,如果你想调用
>getPrice
在声明为
MusicRecord
但在运行时实际上是
CD
的对象上,您必须强制转换它,如
((CD)r).getPrice()
,但我想知道为什么
MusicRecord
本身没有一个
getPrice
方法作为开始。而且这看起来像是子类的滥用。因为每个子类看起来都一样,即具有相同的字段。->
MusicRecord
应该是一个具体的类,并且您应该能够提供一个类型,例如
enum R生态类型{CD,SD,BLUE_-RAY}
您自己,在创建recordhi实例时,这只是一个测试,我想知道是否有办法访问添加到给定数组中的子类中的对象字段。子类将有自己的字段,这些字段与其他子类的字段不匹配。我已将它们命名为相同的字段,但假设t嘿,是不同的。casting会给我一个错误,但我已经用instanceof的if语句解决了这个问题。再次,rzwitserloot,这实际上回答了我的问题,我正在阅读我能找到的所有文档,但是没有详细的解释来指出你发布的这些详细信息。所以谢谢你,我记住你的帮助关于命名约定也有很多建议。
if (x[0] instanceof String) {
    String y = (String) x[0];
    y.toLowerCase();
}
int totalPrice = 0;
for (MusicRecord mr : records) {
    if (mr instanceof CD cd) totalPrice += cd.price;
}
for(MusicRecord r : mr){
      if(r instanceof CD){
        System.out.println("Type: " + r.getType() + "\nLength: " + r.getLength() + "\nTitle: " + ((CD)r).getTitle() + "\nPrice: " + ((CD)r).getPrice() + "\n ***************");
      } else if (r instanceof SD){
        System.out.println("Type: " + r.getType() + "\nLength: " + r.getLength() + "\nTitle: " + ((SD)r).getTitle() + "\nPrice: " + ((SD)r).getPrice() + "\n ***************");
      } else {
        System.out.println("Type: " + r.getType() + "\nLength: " + r.getLength() + "\nTitle: " + ((BlueRay)r).getTitle() + "\nPrice: " + ((BlueRay)r).getPrice() + "\n ***************");
      }