Java Reference
In-Depth Information
Coupon coupon = pendingOrder.getCoupon();
if (coupon instanceof PercentageDiscountCoupon) {
PercentageDiscountCoupon percentageCoupon =
(PercentageDiscountCoupon)coupon;
…
}
else if (coupon instanceof FreeShippingCoupon) {
FreeShippingCoupon freeShippingCoupon =
(FreeShippingCoupon)coupon;
…
}
…
This code will certainly work with regular Java objects, but it won't work when the
application uses Hibernate proxies to implement lazy loading. If Hibernate lazily
loads a
Coupon
, then
PendingOrder.getCoupon()
will return a proxy rather than the
real
Coupon
. Unfortunately, the trouble with proxies is that they do not work cor-
rectly with
instanceof
and do not support downcasting. A
Coupon
proxy will never
appear to be an instance of
FreeShippingCoupon
or
PercentageDiscountCoupon
,
and so neither call to
instanceof
will return
true
. Certainly, using
instanceof
is
generally not considered to be good style, but it is useful in cases such as this.
An application can work around this problem by calling
Hibernate.get-
Class()
, which is a static method that returns an object's true class:
Class trueClass = Hibernate.getClass(coupon);
if (PercentageDiscountCoupon.class.isAssignableFrom(trueClass)) {
…
}
The trouble with this solution is that it pollutes application code with calls to
Hibernate
API
s.
The other problem with proxies is that it is not possible to downcast a refer-
ence to a proxy. The downcasts in the previous code will fail if the
Coupon
is a
proxy. The workaround described in the Hibernate manual is to use parallel hier-
archy of interfaces and downcast to an interface instead of a concrete class:
interface ICoupon {..};
interface IPercentageDiscountCoupon extends Coupon {…};
if (PercentageDiscountCoupon.
b
➥
isAssignableFrom(Hibernate.getClass(coupon))) {
IPercentageDiscountCoupon percentageCoupon =
(IPercentageDiscountCoupon)coupon;
…
}
Search WWH ::
Custom Search