ClassCastException 类型转换异常 class.Accommodation 无法转换为 class.Attraction。

huangapple go评论73阅读模式
英文:

ClassCastException class.Accomodation cannot be cast to class.Attraction

问题

这是我的模型:

public class Accomodation {
    ...
}

以及

public class Attraction extends Accomodation {
    ...
    private String openingTime;
}

我在我的 Controller 类中有这个方法:

protected Accomodation getAccomodationByFormData(CrudView crudView) {
    Accomodation accomodation = new Accomodation();
    // 设置器方法
    return accomodation;
}

该方法在 AttractionController 中使用(该类扩展了之前的 Controller):

@Override
protected Accomodation getAccomodationByFormData(CrudView crudView) {
    Attraction attraction = (Attraction) super.getAccomodationByFormData(crudAttractionView);
    attraction.setOpeningTime(getOpeningTimeWithFormData()); 
    return attraction;
}

在这个 AttractionController 的另一个地方,我有:

...
Attraction attraction = (Attraction) getAccomodationByFormData(crudAttractionView); // 抛出 ClassCastException
...

但是这给了我以下错误:

> 异常线程 "JavaFX Application Thread" java.lang.ClassCastException: class models.Accomodation cannot be cast to class models.Attraction (models.Accomodation and models.Attraction are in unnamed module of loader 'app')
    at controllers.CrudAttractionController.getAccomodationByFormData(CrudAttractionController.java:302)
    at controllers.CrudAttractionController.lambda$buttonConfermaClicked$4(CrudAttractionController.java:143)
    ...

(注:请注意 CrudAttractionView 类扩展了 CrudView

  • 如何修复?

编辑

Attraction

public class Attraction extends Accomodation {
    private String openingTime;

    public Attraction() {

    }

    public Attraction(Accomodation accomodation) {
        super(accomodation);
    }

    // 获取器和设置器方法
}

Accomodation

public class Accomodation implements Serializable {
    protected String id;
    protected String name;
    protected Integer avarageRating;
    protected Integer avaragePrice;
    protected String phoneNumber;
    protected Address address;
    protected Point point;
    protected List<Review> reviews;
    protected Long totalReviews;
    protected Long totalRating;
    protected List<String> images;
    protected boolean hasCertificateOfExcellence;
    protected String addedDate;
    protected String lastModificationDate;

    public Accomodation() {

    }

    public Accomodation(Accomodation accomodation) {
    }

    // 获取器和设置器方法
}
英文:

These are my mondels:

public class Accomodation {
    ...
}

and

public class Attraction extends Accomodation {
    ... 
    private String openingTime;
}

I have this method in my Controller class:

protected Accomodation getAccomodationByFormData(CrudView crudView) {
        Accomodation accomodation = new Accomodation();
        // setters
        return accomodation;
    }

which is used within AttractionController (which extends previous Controller):

@Override
    protected Accomodation getAccomodationByFormData(CrudView crudView) {
        Attraction attraction = (Attraction) super.getAccomodationByFormData(crudAttractionView);
        attraction.setOpeningTime(getOpeningTimeWithFormData()); 
        return attraction;
    }

in another point of this AttractionController I have:

...
Attraction attraction = (Attraction) getAccomodationByFormData(crudAttractionView); // throws ClassCastException
...

But this is giving me:

> Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: class models.Accomodation cannot be cast to class models.Attraction (models.Accomodation and models.Attraction are in unnamed module of loader 'app')
at controllers.CrudAttractionController.getAccomodationByFormData(CrudAttractionController.java:302)
at controllers.CrudAttractionController.lambda$buttonConfermaClicked$4(CrudAttractionController.java:143)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8879)
at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3851)
at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1200(Scene.java:3579)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1849)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2588)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:390)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
at java.base/java.lang.Thread.run(Thread.java:834)

(Ps. Note that CrudAttractionView class extends CrudView)

  • How can I fix?

EDIT

Attraction

public class Attraction extends Accomodation {
    private String openingTime;

    public Attraction() {

    }

    public Attraction(Accomodation accomodation) {
        super(accomodation);
    }

    // getters and setters
}

Accomodation

public class Accomodation implements Serializable {
    protected String id;
    protected String name;
    protected Integer avarageRating;
    protected Integer avaragePrice;
    protected String phoneNumber;
    protected Address address;
    protected Point point;
    protected List&lt;Review&gt; reviews;
    protected Long totalReviews;
    protected Long totalRating;
    protected List&lt;String&gt; images;
    protected boolean hasCertificateOfExcellence;
    protected String addedDate;
    protected String lastModificationDate;

    public Accomodation() {

    }

    public Accomodation(Accomodation accomodation) {
    }

    // getters and setters
}

答案1

得分: 2

所有的 `Attraction` 都是 `Accomodation`,但并非所有的 `Accomodation` 都是 `Attraction`。

这意味着你不能安全地执行

    Attraction attraction = (Attraction) super.getAccomodationByFormData(crudAttractionView);

即使你在一个 `AttractionController`Java 不会根据你控制器的名称更改 super.getAccomodation 的返回类型)。

一个不需要任何框架的解决方案是这样的

    Accomodation accomodation = super.getAccomodationByFormData(crudAttractionView);
    Attraction attraction = new Attraction(accomodation);
    attraction.setOpeningTime(getOpeningTimeWithFormData())

你只需要确保你有一个接受 `Accomodation``Attraction` 构造函数并将其字段复制到你的景点

类似于

    public Attraction(Accomodation accomodation){
      attraction.setX(accomodation.getX())
      ...
    }

或者只是调用 `super(accomodation)`,并在 `Accomodation` 中有一个构造函数可以将一个 `Accomodation` 复制到一个新的实例中这样你将能够在所有未来的扩展类中使用该构造函数

现在确保你的 `accomodation` 实际上是一个 `Attraction`,然后进行类型转换

在一个更简洁的例子中以下是代码示例

```java
import java.io.Serializable;

class Attraction extends Accomodation {

    public Attraction() {

    }

    public Attraction(Accomodation accomodation) {
        super(accomodation); // 让超类进行简单映射
    }

    // 获取器和设置器

    public void setOpeningTime(String test){
        //
    }

    protected Accomodation getAccomodationByFormData() {
        Accomodation accomodation= new Accomodation();//super.getAccomodationByFormData(crudAttractionView);
        Attraction attraction = new Attraction(accomodation); // 通过构造函数将我们的 accomodation 转换
        attraction.setOpeningTime("..."); // 设置开放时间
        return attraction;
    }
}

class Accomodation implements Serializable {
    protected String id;
    protected String name;
    protected Integer avarageRating;
    protected Integer avaragePrice;
    protected String phoneNumber;
    protected Long totalReviews;
    protected Long totalRating;
    protected boolean hasCertificateOfExcellence;
    protected String addedDate;
    protected String lastModificationDate;

    public Accomodation(Accomodation accomodation) {
        this.id = accomodation.id;
        this.name = accomodation.name;
        this.avarageRating = accomodation.avarageRating;
        this.avaragePrice = accomodation.avaragePrice;
        this.phoneNumber = accomodation.phoneNumber;
        this.totalReviews = accomodation.totalReviews;
        this.totalRating = accomodation.totalRating;
        this.hasCertificateOfExcellence = accomodation.hasCertificateOfExcellence;
        this.addedDate = accomodation.addedDate;
        this.lastModificationDate = accomodation.lastModificationDate;
    }

    public Accomodation() {

    }

    // 获取器和设置器
}
英文:

All Attraction are Accomodation, but not all Accomodation are Attraction.

It means you cannot do safely :

Attraction attraction = (Attraction) super.getAccomodationByFormData(crudAttractionView);

Even if you are in a AttractionController (java doesn't change the return type of super.getAccomadation based on your controller's name).

One solution without the need of any Framework would be to do something like :

Accomodation accomodation = super.getAccomodationByFormData(crudAttractionView);
Attraction attraction = new Attraction(accomodation);
attraction.setOpeningTime(getOpeningTimeWithFormData())

You just have to make sure you have an Attraction Constructor that will take that Accomodation and copy it fields to your attraction.

Something like :

public Attraction(Accomodation accomodation){
attraction.setX(accomodation.getX())
...
}

Or just calling super(accomodation) and having a Constructor in Accomodation that will be able to copy an Accomodation into a new one (so you'll be able to use that Constructor in all future extending classes)

Now, you ensure your accomodation is effectively an Attraction, then you cast it.

In a more concise example, here is what it would looks like

import java.io.Serializable;
class Attraction extends Accomodation {
public Attraction() {
}
public Attraction(Accomodation accomodation) {
super(accomodation); // we let super do the simple mapping
}
// getters and setters
public void setOpeningTime(String test){
//
}
protected Accomodation getAccomodationByFormData() {
Accomodation accomodation= new Accomodation();//super.getAccomodationByFormData(crudAttractionView);
Attraction attraction = new Attraction(accomodation); // we convert our accomodation thanks to our constructor
attraction.setOpeningTime(&quot;...&quot;);
return attraction;
}
}
class Accomodation implements Serializable {
protected String id;
protected String name;
protected Integer avarageRating;
protected Integer avaragePrice;
protected String phoneNumber;
protected Long totalReviews;
protected Long totalRating;
protected boolean hasCertificateOfExcellence;
protected String addedDate;
protected String lastModificationDate;
public Accomodation(Accomodation accomodation) {
this.id = accomodation.id;
this.name = accomodation.name;
this.avarageRating = accomodation.avarageRating;
this.avaragePrice = accomodation.avaragePrice;
this.phoneNumber = accomodation.phoneNumber;
this.totalReviews = accomodation.totalReviews;
this.totalRating = accomodation.totalRating;
this.hasCertificateOfExcellence = accomodation.hasCertificateOfExcellence;
this.addedDate = accomodation.addedDate;
this.lastModificationDate = accomodation.lastModificationDate;
}
public Accomodation() {
}
// getters and setters
}

huangapple
  • 本文由 发表于 2020年10月1日 18:12:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/64153266.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定