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
Objectbecause of type erasure. The javadoc ofAtomicReferenceFieldUpdater#newUpdaterstates that it throwsYou've presumably passed
Long.classorlong.classas an argument for thetypeparameter. It expectsObject.class.In your second example, the field is explicitly defined as being of type
Longso
Long.classwill work, since that is the type of the field expected.