Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.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/4/oop/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_Oop_Design Patterns - Fatal编程技术网

Java 如何在运行时识别对象的类型?

Java 如何在运行时识别对象的类型?,java,oop,design-patterns,Java,Oop,Design Patterns,课程: public abstract class BaseHolidayPackageVariant { private Integer variantId; private HolidayPackage holidayPackage; private String holidayPackageType; } public class LandHolidayPackageVariant extends BaseHolidayPackageVariant{ } pu

课程:

public abstract class BaseHolidayPackageVariant {
    private Integer variantId;
    private HolidayPackage holidayPackage;
    private String holidayPackageType;
}

public class LandHolidayPackageVariant extends BaseHolidayPackageVariant{

}

public class FlightHolidayPackageVariant extends BaseHolidayPackageVariant{
    private Destination originCity;
}

public class HolidayPackage{
    ArrayList<BaseHolidayPackageVariant> variants;

    BaseHolidayPackageVariant defaultVariant;
}
这个问题源于我问的一个设计问题

试试这个:

if (variant[i] instanceof LandHolidayPackageVariant) {
    LandHolidayPackageVariant obj = (LandHolidayPackageVariant)variant[i];
    // do stuff
}
else if (variant[i] instanceof FlightHolidayPackageVariant) {
    FlightHolidayPackageVariant obj = (FlightHolidayPackageVariant)variant[i];
    // do other stuff
}
请注意,如果您还有从这些类型之一派生的类型,则应该首先检查那些,因为在这种情况下,上面的检查也会返回true


更好的方法可能是让派生类通过定义要在基类上重写的适当方法来实现所需的特定逻辑。这样,您就不需要检查类型,并且可以充分利用多态性。

在良好的面向对象设计中,您不需要知道对象是否属于特定类型。只需对其调用方法,对象就会做正确的事情

例如,
FlightHolidayPackageVariant
有一个字段
originCity
,该字段不在其他
HolidayPackageVariant
类中,您希望在UI中呈现该字段。解决这个问题的面向对象方法是使
HolidayPackageVariant
在某种程度上负责控制自己的渲染。假设您的UI将显示每个变体的属性列表。您可以让变体提供这些列表:

public abstract class BaseHolidayPackageVariant {
    private int cost;

    public Map<String, String> getDetails() {
        HashMap<String, String> details = new HashMap<String, String>();
        details.put("cost", String.format("%.2f", cost / 100.0));
        return details;
    }
}

public class FlightHolidayPackageVariant extends BaseHolidayPackageVariant {
    private Destination originCity;

    @Override
    public Map<String, String> getDetails() {
        Map<String, String> details = super.getDetails();
        details.put("origin city", originCity.getName());
        return details;
    }
}
公共抽象类BaseHolidayPackageVariant{
私人成本;
公共地图获取详细信息(){
HashMap details=新的HashMap();
details.put(“cost”,String.format(“%.2f”,cost/100.0));
退货详情;
}
}
公共类FlightHolidayPackageVariant扩展了BaseHolidayPackageVariant{
私人目的地起源;
@凌驾
公共地图获取详细信息(){
Map details=super.getDetails();
details.put(“originCity”,originCity.getName());
退货详情;
}
}
现在,您的UI代码可以简单地询问每个变量对象的详细信息,而不必知道它是什么类型的变量。

如下所示:

if(object instanceof LandPackageVariant) {
    System.out.println("it's a LandPackageVariant");
}
很好地做到这一点,obj必须是一个
BaseHolidayPackageVariant
,因此您甚至不需要强制转换,也不需要执行
if
之类的操作


如果您希望具有特定类Land或Flight的对象调用特定方法,那么您可能应该查看对象模型。

您可以使用instanceof

例如: {

}

看看:http://www.java2s.com/Tutorial/Java/0060__Operators/TheinstanceofKeyword.htm


更好的选择是设计程序,这样就不需要instanceof操作符

您可以使用
instanceof
操作符执行以下操作:

if (variant[i] instanceof LandHolidayPackageVariant)
    obj = (LandHolidayPackageVariant) variant[i];

然而,通常你不应该需要它。使用
instanceof
来区分类没有什么好的理由,但通常子类本身应该通过它们共同的超类接口提供所需的不同功能。

是的,这里的两个答案都是——矛盾的——正确的

汤姆关于你的问题可疑的回答是正确的。通常没有理由从对象层次结构中的其他对象确定对象的特定类型。(我的意思是在想象的反射之外)

Botz3000的答案在技术上是正确的(就像我打字时出现的所有其他答案一样)

猜测一下,您正在计算在类中调用哪个方法?在这种情况下,请使用@Override注释,在子类中重新定义该方法,并在父类中提供一个抽象方法(或者提供一个执行基本操作的具体版本?)

从您的类名来看,我想您应该对抽象工厂模式和(极其简单的)策略模式有一个快速的了解


PS如果您想使用反射,只需调用getClass()并进行检查。但我想强调的是,没有理由这样做,这是一种不好的做法。但是你在这里。

请注意,如果
variant[i]
的类型是
DerivedLandHolidayPackageVariant
[它扩展了
LandHolidayPackageVariant
],它也会返回
true
这可能是您想要的,也可能不是您想要的-请注意。@Botz3000根据
if
条件的顺序,这种方法容易出现问题,特别是如果在其派生类型之前检查了超类型。我现在有一个小的变体列表,但是我有一些用例,这些用例将会增长。有没有更好的方法来处理这个问题?当然有。在我的帖子中添加了一些澄清@BrainyExtenr也许您可以将逻辑移动到基类上的方法,这样派生类就可以自己提供逻辑了?那么你也不需要进行类型检查。@Botz3000也许我需要改变我设计对象模型的方式,因为有人警告我不要使用一堆
if
来确定它是哪个对象。我的问题源于我在这里提出的设计问题:同意特定类型。否则我不知道如何建模。e、 g.如果您查看
FlightHolidayPackageVariant
,它添加了一个成员:
OriginCity
。在给定的
HolidayPackageVariant
variants[]中,当我呈现
FlightHolidayPackageVariant
时,我希望呈现
原始城市的名称。我无法从
BaseHolidayPackageVariant
中检索到,添加了一个可能解决此问题的示例。感谢您的编辑,我明白您的观点。我脑子里有一个相关的问题,我似乎无法回答。按照以不同方式渲染变体的相同示例,我还希望将(视图)aka渲染细节保留在对象模型之外。我如何用你提供的解决方案来支持这一点?这当然不是一个容易的问题。它归结为找到一种方法,将渲染任务分为两部分,一部分特定于视图,另一部分足够通用,可以在模型中使用,后者功能强大,可以为每个子类执行不同的操作。我的代码试图做到这一点:这些方法只为视图的使用而存在,但它们并不特定于任何类型的视图;你可以用它们来爆炸
if(holidayPackageType.equals("LandHolidayPackageVariant")
 obj = (LandHolidayPackageVariant)variant[i];
else if(holidayPackageType.equals("FlightHolidayPackageVariant")
 obj = (FlightHolidayPackageVariant)variant[i];
enter code here
if (variant[i] instanceof LandHolidayPackageVariant) {
  //do something
} else if(variant[i] instanceof FlightHolidayPackageVariant){
  //do something
}
if (variant[i] instanceof LandHolidayPackageVariant)
    obj = (LandHolidayPackageVariant) variant[i];