Reputation: 11447
I'm trying to write a custom UI component (on android) that will display a text edit control along with two buttons which can be clicked up or down. Up increments the number in the edit control and down decrements it.
I'd like this class to be generic on the numeric type i.e. i'd like to specialize the class for int and float types.
I've been reading this nice Java Generics Tutorial but my particular implementation doesn't seem to compile. Here's what I have got:
public class NumberPicker<T> extends LinearLayout implements OnClickListener,
OnFocusChangeListener, OnLongClickListener {
public interface OnChangedListener<T> {
void onChanged(NumberPicker<T> picker, T oldVal, T newVal);
}
public interface Formatter<T> {
String toString(T value);
}
// Error: Cannot make a static reference to the non-static type T
public static final NumberPicker.Formatter<T> TWO_DIGIT_FORMATTER =
new NumberPicker.Formatter<T>() {
public String toString(T value) {
// Do something with T value
}
};
}
I'm getting the following compiler error in the declaration of the TWO_DIGIT_FORMATTER
:
Cannot make a static reference to the non-static type T
Can someone please help me with the syntax. Coming from C++ I understand generic well enough and am aware of some of the differences between the two. I just need help with the syntax.
I tried changing to:
// "Syntax error on token "int", Dimensions expected after this token"
public static final NumberPicker.Formatter<int> TWO_DIGIT_FORMATTER =
new NumberPicker.Formatter<int>() {
public String toString(int value) {
return mFmt.toString();
}
};
This gives "Syntax error on token "int", Dimensions expected after this token"
Upvotes: 1
Views: 1280
Reputation: 49814
The T
parameter belongs to a NumberPicker
instance, each instance can have a different value to it, so it can't be relied on in a static field of the class.
Nor can it be referenced in the public interface Formatter<T>
, as interface members are by default static.
One way to work around this is:
TWO_DIGIT_FORMATTER
, being a constant should have the parameter bound. When you think about it, an unbound parameter doesn't really make much sense in this situation.Formatter
can have its own separate parameter, checked when you pass it to a NumberPicker
instance. (This is already done implicitly in OnChangedListener
.)So your code will be something like this:
public class NumberPicker<T> {
public interface OnChangedListener<Y> { //
void onChanged(NumberPicker<Y> picker, Y oldVal, Y newVal);
}
public interface Formatter<X> {
String toString(X value);
}
public void setFormatter( Formatter<T> formatter ) { ... }
public static final NumberPicker.Formatter<? extends Number> TWO_DIGIT_FORMATTER =
new NumberPicker.Formatter<Number>() {
public String toString(Number value) {
// Do something with T value
}
};
}
I replaced T
with X
and Y
in the interface definitions to avoid confusion. The parameter of the interfaces is completely separate from the parameter of NumberPicker
By giving them different names this becomes readily apparent.
Upvotes: 1
Reputation: 5230
You cannot use generic in static method. Generic will paremetrize your instances, and static is not instance but class scope.
You can change it to (remove static):
public final NumberPicker.Formatter<T> TWO_DIGIT_FORMATTER = ...
Upvotes: 0
Reputation: 200306
Your field TWO_DIGIT_FORMATTER
is a static field, that is, a class field, not belonging to any specific instance. On the other hand, the type parameter T
is getting resolved only when you refer to a specific instance of NumberPicker
where you have bound T
to a concrete type. The type of T
changes with different instances so naturally it has no meaning on a class field. You'll have to remove the static
qualifier from TWO_DIGIT_FORMATTER
and then you'll have to access it through an instance of the class.
Upvotes: 0
Reputation: 110104
This doesn't have to do with syntax, it has to do with the fact that your type T
is associated with instances of NumberPicker
, while your TWO_DIGIT_FORMATTER
is static
and as such not associated with any instance of NumberPicker
. So there is no type T
for it to refer to.
Upvotes: 2