访问数组中子项 类 的字段
Accessing fields of children classes within an array
我正在测试 Java 中的继承,我有一个带有两个字段的抽象 class 和三个带有自己字段的扩展 class。在另一个 class 中,我在数组中实例化并添加 class 的对象,但我不确定如何访问子 classes 的字段,该数组是主要摘要 class:
这里是摘要 class 和扩展 class 之一的完整代码:
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;
}
}
public class CD extends MusicRecord {
private int price;
private String title;
public CD(String type, int lenght, String title, int price){
super(type, lenght);
this.price = price;
this.title = title;
}
public String getTitle(){
return title;
}
public int getPrice(){
return price;
}
public String getType(){
return "MusicRecord: " + super.getType();
}
public int getLenght(){
return super.getLength();
}
public void setPrice(int price){
this.price = price;
}
public void setTitle(String title){
this.title = title;
}
}
import java.util.Arrays;
public class Store {
public static void main(String args[]){
CD cd1 = new CD("Jaz", 34, "Music 44", 19);
SD sd1 = new SD("R&B", 45, "Lova is never Lost!!", 21);
BlueRay br1 = new BlueRay("Hell on Earth", 25, "HipHop", 40);
MusicRecord[] mr = {cd1, sd1, br1,
new CD("House", 40, "22 Is the Age", 22),
new SD("Garage", 60, "Boom Boom Boommm", 14),
new BlueRay("is it time to love", 18, "R&B", 35)};
for(MusicRecord r : mr){
System.out.println("Type: " + r.getType() + "\nLength: " + r.getLength());
}
}
如何从 subclass/es 中获取字段?
ow I can access the fields of the subclasses, the array is of the main abstract class:
java 类型系统是协变的。 (除了在泛型中,方差是可选的,默认情况下,不变)。对于此答案的其余部分,您需要注意:
- java.lang.Integer 扩展 java.lang.Number
- java.lang.Double 扩展 java.lang.Number
- java.lang.Number 扩展 java.lang.Object
协变意味着您可以采用类型为 Integer
的表达式,并在需要 Number
的地方使用它:当需要超类型时,任何子类型都可以。 (不变性意味着只有特定类型 Number 的表达式才行,而逆变性则相反:如果需要 Integer,Number 或 Object 也可以)。
因此:
Number[] x = new Number[2];
x[0] = new Integer(5);
x[1] = new Double(10.0);
一切都很好。
这也意味着,如果你翻转它,如果一个表达式是 Number 类型,那么它很可能是 Number 的某个子类型。鉴于 Number 是抽象的,这实际上是保证!不能存在 Number 本身的实例,只能存在它的子类的实例。
您可以使用 instanceof 和转换以及模式匹配来处理这个问题:
注意:这使用 java 在 java15!
中引入的新功能
Object[] x = new Object[2];
x[0] = "hello";
if (x[0] instanceof String y) {
y.toLowerCase();
}
这里我们首先检查 x[0]
是否是一个字符串(它可能是。它也可能是一个整数,或者一个 FileInputStream,或者一个 com.sun.internal.impl.HttpRequestImpl
- 协方差意味着事物的实际类型可以,而且通常是,一些无法保证的内部细节,并且可以在 java 版本和实现之间更改)。 如果它是一个字符串,那么对于所有只有在它是(这里是if块的内部)才能到达的代码,y
作为一个变量存在,并且包含对完全相同的 object 的引用,但这次输入为字符串,因此您可以在其上自由调用字符串方法,例如 .toLowerCase()
.
如果您还没有使用 JDK15,'old' 方法是:
if (x[0] instanceof String) {
String y = (String) x[0];
y.toLowerCase();
}
这称为强制转换运算符,它只是一个类型断言:如果 x[0]
确实是一个字符串,那么这段代码什么都不做。就好像你写了 (String y = x[0];
,除了不会编译,但效果是一样的:y 现在指向相同的东西 x[0]
指向,转换只是告诉编译器你知道这是断言类型,并添加了运行时测试。
另一方面,如果 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 编码人员阅读,那么遵循既定约定是个好主意,并且这些规定您对所有内容进行标题化,甚至是首字母缩略词,在普通情况下写作,在 all-caps 中呈现。 DVD 播放器,不是 DVD 播放器。光盘,不是光盘。当您使用它时,按照惯例直接访问字段是不行的 - 而是制作吸气剂。应该是 cd.getPrice()
.
感谢 Lino、rzwitserloot 和 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 ***************");
}
我正在测试 Java 中的继承,我有一个带有两个字段的抽象 class 和三个带有自己字段的扩展 class。在另一个 class 中,我在数组中实例化并添加 class 的对象,但我不确定如何访问子 classes 的字段,该数组是主要摘要 class:
这里是摘要 class 和扩展 class 之一的完整代码:
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;
}
}
public class CD extends MusicRecord {
private int price;
private String title;
public CD(String type, int lenght, String title, int price){
super(type, lenght);
this.price = price;
this.title = title;
}
public String getTitle(){
return title;
}
public int getPrice(){
return price;
}
public String getType(){
return "MusicRecord: " + super.getType();
}
public int getLenght(){
return super.getLength();
}
public void setPrice(int price){
this.price = price;
}
public void setTitle(String title){
this.title = title;
}
}
import java.util.Arrays;
public class Store {
public static void main(String args[]){
CD cd1 = new CD("Jaz", 34, "Music 44", 19);
SD sd1 = new SD("R&B", 45, "Lova is never Lost!!", 21);
BlueRay br1 = new BlueRay("Hell on Earth", 25, "HipHop", 40);
MusicRecord[] mr = {cd1, sd1, br1,
new CD("House", 40, "22 Is the Age", 22),
new SD("Garage", 60, "Boom Boom Boommm", 14),
new BlueRay("is it time to love", 18, "R&B", 35)};
for(MusicRecord r : mr){
System.out.println("Type: " + r.getType() + "\nLength: " + r.getLength());
}
}
如何从 subclass/es 中获取字段?
ow I can access the fields of the subclasses, the array is of the main abstract class:
java 类型系统是协变的。 (除了在泛型中,方差是可选的,默认情况下,不变)。对于此答案的其余部分,您需要注意:
- java.lang.Integer 扩展 java.lang.Number
- java.lang.Double 扩展 java.lang.Number
- java.lang.Number 扩展 java.lang.Object
协变意味着您可以采用类型为 Integer
的表达式,并在需要 Number
的地方使用它:当需要超类型时,任何子类型都可以。 (不变性意味着只有特定类型 Number 的表达式才行,而逆变性则相反:如果需要 Integer,Number 或 Object 也可以)。
因此:
Number[] x = new Number[2];
x[0] = new Integer(5);
x[1] = new Double(10.0);
一切都很好。
这也意味着,如果你翻转它,如果一个表达式是 Number 类型,那么它很可能是 Number 的某个子类型。鉴于 Number 是抽象的,这实际上是保证!不能存在 Number 本身的实例,只能存在它的子类的实例。
您可以使用 instanceof 和转换以及模式匹配来处理这个问题:
注意:这使用 java 在 java15!
中引入的新功能Object[] x = new Object[2];
x[0] = "hello";
if (x[0] instanceof String y) {
y.toLowerCase();
}
这里我们首先检查 x[0]
是否是一个字符串(它可能是。它也可能是一个整数,或者一个 FileInputStream,或者一个 com.sun.internal.impl.HttpRequestImpl
- 协方差意味着事物的实际类型可以,而且通常是,一些无法保证的内部细节,并且可以在 java 版本和实现之间更改)。 如果它是一个字符串,那么对于所有只有在它是(这里是if块的内部)才能到达的代码,y
作为一个变量存在,并且包含对完全相同的 object 的引用,但这次输入为字符串,因此您可以在其上自由调用字符串方法,例如 .toLowerCase()
.
如果您还没有使用 JDK15,'old' 方法是:
if (x[0] instanceof String) {
String y = (String) x[0];
y.toLowerCase();
}
这称为强制转换运算符,它只是一个类型断言:如果 x[0]
确实是一个字符串,那么这段代码什么都不做。就好像你写了 (String y = x[0];
,除了不会编译,但效果是一样的:y 现在指向相同的东西 x[0]
指向,转换只是告诉编译器你知道这是断言类型,并添加了运行时测试。
另一方面,如果 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 编码人员阅读,那么遵循既定约定是个好主意,并且这些规定您对所有内容进行标题化,甚至是首字母缩略词,在普通情况下写作,在 all-caps 中呈现。 DVD 播放器,不是 DVD 播放器。光盘,不是光盘。当您使用它时,按照惯例直接访问字段是不行的 - 而是制作吸气剂。应该是 cd.getPrice()
.
感谢 Lino、rzwitserloot 和 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 ***************");
}