I get the following error :
Exception in thread "main" java.lang.ClassCastException
at java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl.<init>(AtomicReferenceFieldUpdater.java:336)
at java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdater.java:109)
at org.telegram.bot.util.FieldTimer.<init>(FieldTimer.java:27)
at org.telegram.bot.util.FieldTimer.<init>(FieldTimer.java:19)
at org.telegram.bot.util.FieldTimer.main(FieldTimer.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
when using AtomicReferenceFieldUpdater
for generic types.
I'am totally confused and I have no idea why I'm getting such an error.
the code I am using :
public final class FieldTimer<V> {
private volatile V value;
private final V defaultValue;
private final long resetTimeout;
private final AtomicLong lastSet;
private final AtomicReferenceFieldUpdater<FieldTimer, V> updater;
public FieldTimer(V value, Class<V> type, long resetTimeout, TimeUnit unit) {
this(value, value, type, resetTimeout, unit);
}
public FieldTimer(V value, V defaultValue, Class<V> type, long resetTimeout, TimeUnit unit) {
this.value = value;
this.defaultValue = defaultValue;
this.resetTimeout = unit.toMillis(resetTimeout);
lastSet = new AtomicLong(System.currentTimeMillis());
updater = AtomicReferenceFieldUpdater.newUpdater(FieldTimer.class, type, "value");
}
public V get() {
return System.currentTimeMillis() - lastSet.get() >= resetTimeout
? defaultValue
: value;
}
public void set(V value) {
updater.set(this, value);
lastSet.set(System.currentTimeMillis());
}
public boolean compareAndSet(V expect, V update) {
boolean set = updater.compareAndSet(this, expect, update);
if (set) {
lastSet.set(System.currentTimeMillis());
}
return set;
}
}
the exception occurs in this line of code :
updater = AtomicReferenceFieldUpdater.newUpdater(FieldTimer.class, type, "value");
but, if I change it to something like this :
public final class LongFieldTimer {
private volatile Long value;
...
public LongFieldTimer(Long value, Long defaultValue, long resetTimeout, TimeUnit unit) {
...
updater = AtomicReferenceFieldUpdater.newUpdater(LongFieldTimer.class, Long.class, "value");
}
}
then there would be no errors :| (but why???)
what causes this problem? and how to solve it?
Thanks.
Your field
is of type
Object
because of type erasure. The javadoc ofAtomicReferenceFieldUpdater#newUpdater
states that it throwsYou've presumably passed
Long.class
orlong.class
as an argument for thetype
parameter. It expectsObject.class
.In your second example, the field is explicitly defined as being of type
Long
so
Long.class
will work, since that is the type of the field expected.