方法链,从列表中返回一个对象并从中获取值
method chaining, returning an object from a list and getting values from it
我有一个 Dog 对象列表,在这些对象中包含一个布尔值,用于显示狗是否完成了训练。我想做的是遍历列表,并且只遍历 return Dog() 已完成训练的对象,例如,如果它们是 12 只狗,并且只有 3 只狗已完成训练,则循环应该只打印这些对象。
else if (input == 1) {
for (int i = 0; i < 12; ++i) {
//Create a temporary value to hold the object.
Object tempHold = dogKennel.getAnimal(i);
//If animal has not graduated, skip, else print.
if (!(tempHold.getGraduation())) {
continue;
}
else {
System.out.println(dogKennel);
}
}
getAnimal(i) returns int i 处的对象
方法 .getGraduation 已定义并执行 return 布尔值,但是编译器不想按原样识别临时值,并且不会超出该值。编译器一直建议转换 tempHold,但即使我这样做了,它也不起作用。
我觉得如果我能让它编译的话它会起作用,因为 returned 的对象会有一个 getGraduation() 方法(它是为超级 class 定义的动物。)
如果您只想过滤具有特定条件的列表,目前最常用的方法是使用 Stream::filter
方法。
看起来像这样:
List<Dog> completedTraining =
dogKennel
.stream()
.filter(
dog -> !dog.getGraduation()
)
.collect(
Collectors.toList()
)
;
正如其他人所说,getGraduation()
方法大概只在 Dog class 中定义。这意味着该方法只能在类型为 Dog
的对象上调用。要定义类型为 Dog
的变量,您可以执行 Dog temphold = *whatever*
。它要你强制转换的原因是因为 Object 是 Dog 的超类型。如果你想阅读更多关于转换的信息,你可以在这里:https://javarevisited.blogspot.com/2012/12/what-is-type-casting-in-java-class-interface-example.html
基本上,您所要做的就是转换对象
if (!(((Dog)tempHold).getGraduation()))
{
continue;
}
此转换告诉编译器,即使 tempHold
是 Object
class 的对象,它也是 Dog
class 的对象并且应该具有它的所有属性
however the compiler doesn't want to recognize temp value as is, ...the compiler keeps suggesting to cast tempHold, but even if I do, it doesn't work.
编译器告诉你两件事:
- 一个
Object
不是一个Dog
(反之亦然。一个Dog
是一个Object
)。
- class
Object
没有为它们定义方法 isGraduated()
。
要解决此问题,您可以将 Object
转换为 Dog
:
Dog tempHold = (Dog)dogKennel.getAnimal(i);
现在我们有了 Dog
,我们可以安全地对其调用 isGraduated()
。但问题是我们不能确定我们有 Dog
。如果我们从另一个犬舍得到 Animal
,我们也可能有一个 Cat
。在这种情况下,您将得到一个 ClassCastException
,告诉您 Cat
s 不能转换为 Dog
s。
为避免出现 运行 时间异常,您可以添加检查:
Object tempHold = dogKennel.getAnimal(i);
if(tempHold instanceof Dog) {
Dog dog = (Dog)tempHold;
System.out.println(dog.isGraduated());
}
instanceof
检查解决了问题。
有一些方法可以完全避免这种 运行 时间检查。一种是创建一个接口:
public interface CanGraduate {
default boolean isGraduated() {
return false;
};
}
然后让所有Animal
实现这个接口:
public abstract class Animal implements CanGraduate {
//Behavior common among all animals
}
您现在可以自由添加新的动物类型,并且放心,您可以安全地对它们调用 isGraduated()
并获得 false
值,只要它们继承上述 Animal
class.
对于狗来说,isGraduated()
应该更有意义。所以你可以在他们的情况下覆盖它:
public class Dog extends Animal {
private boolean _graduated = true;
@Override
public boolean isGraduated() {
return _graduated; //or some complex logic that determines graduation
}
}
有了这个结构,你再也不用担心调用任何类型的方法了Animal
。
举个例子,让我们看一些驱动程序代码:
public class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
Dog dog2 = new Dog();
Cat cat1 = new Cat();
Cat cat2 = new Cat();
List<Animal> dogKennel = List.of(dog1, dog2);
List<Animal> catKennel = List.of(cat1, cat2);
for(Animal x : catKennel) {
System.out.println(x.isGraduated());
}
}
}
程序将简单地输出 false
,因为 Cat
s 永远不会毕业。如果 kennel 包含 Dog
s,它将输出狗的实际毕业状态。
我有一个 Dog 对象列表,在这些对象中包含一个布尔值,用于显示狗是否完成了训练。我想做的是遍历列表,并且只遍历 return Dog() 已完成训练的对象,例如,如果它们是 12 只狗,并且只有 3 只狗已完成训练,则循环应该只打印这些对象。
else if (input == 1) {
for (int i = 0; i < 12; ++i) {
//Create a temporary value to hold the object.
Object tempHold = dogKennel.getAnimal(i);
//If animal has not graduated, skip, else print.
if (!(tempHold.getGraduation())) {
continue;
}
else {
System.out.println(dogKennel);
}
}
getAnimal(i) returns int i 处的对象
方法 .getGraduation 已定义并执行 return 布尔值,但是编译器不想按原样识别临时值,并且不会超出该值。编译器一直建议转换 tempHold,但即使我这样做了,它也不起作用。
我觉得如果我能让它编译的话它会起作用,因为 returned 的对象会有一个 getGraduation() 方法(它是为超级 class 定义的动物。)
如果您只想过滤具有特定条件的列表,目前最常用的方法是使用 Stream::filter
方法。
看起来像这样:
List<Dog> completedTraining =
dogKennel
.stream()
.filter(
dog -> !dog.getGraduation()
)
.collect(
Collectors.toList()
)
;
正如其他人所说,getGraduation()
方法大概只在 Dog class 中定义。这意味着该方法只能在类型为 Dog
的对象上调用。要定义类型为 Dog
的变量,您可以执行 Dog temphold = *whatever*
。它要你强制转换的原因是因为 Object 是 Dog 的超类型。如果你想阅读更多关于转换的信息,你可以在这里:https://javarevisited.blogspot.com/2012/12/what-is-type-casting-in-java-class-interface-example.html
基本上,您所要做的就是转换对象
if (!(((Dog)tempHold).getGraduation()))
{
continue;
}
此转换告诉编译器,即使 tempHold
是 Object
class 的对象,它也是 Dog
class 的对象并且应该具有它的所有属性
however the compiler doesn't want to recognize temp value as is, ...the compiler keeps suggesting to cast tempHold, but even if I do, it doesn't work.
编译器告诉你两件事:
- 一个
Object
不是一个Dog
(反之亦然。一个Dog
是一个Object
)。 - class
Object
没有为它们定义方法isGraduated()
。
要解决此问题,您可以将 Object
转换为 Dog
:
Dog tempHold = (Dog)dogKennel.getAnimal(i);
现在我们有了 Dog
,我们可以安全地对其调用 isGraduated()
。但问题是我们不能确定我们有 Dog
。如果我们从另一个犬舍得到 Animal
,我们也可能有一个 Cat
。在这种情况下,您将得到一个 ClassCastException
,告诉您 Cat
s 不能转换为 Dog
s。
为避免出现 运行 时间异常,您可以添加检查:
Object tempHold = dogKennel.getAnimal(i);
if(tempHold instanceof Dog) {
Dog dog = (Dog)tempHold;
System.out.println(dog.isGraduated());
}
instanceof
检查解决了问题。
有一些方法可以完全避免这种 运行 时间检查。一种是创建一个接口:
public interface CanGraduate {
default boolean isGraduated() {
return false;
};
}
然后让所有Animal
实现这个接口:
public abstract class Animal implements CanGraduate {
//Behavior common among all animals
}
您现在可以自由添加新的动物类型,并且放心,您可以安全地对它们调用 isGraduated()
并获得 false
值,只要它们继承上述 Animal
class.
对于狗来说,isGraduated()
应该更有意义。所以你可以在他们的情况下覆盖它:
public class Dog extends Animal {
private boolean _graduated = true;
@Override
public boolean isGraduated() {
return _graduated; //or some complex logic that determines graduation
}
}
有了这个结构,你再也不用担心调用任何类型的方法了Animal
。
举个例子,让我们看一些驱动程序代码:
public class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
Dog dog2 = new Dog();
Cat cat1 = new Cat();
Cat cat2 = new Cat();
List<Animal> dogKennel = List.of(dog1, dog2);
List<Animal> catKennel = List.of(cat1, cat2);
for(Animal x : catKennel) {
System.out.println(x.isGraduated());
}
}
}
程序将简单地输出 false
,因为 Cat
s 永远不会毕业。如果 kennel 包含 Dog
s,它将输出狗的实际毕业状态。