I was trying to do something like:
public class MyClass <A, B, C <A, B> > {
...
}
But Eclipse highlights "B," and says "unexpected , expected extends". What gives? Are nested generics not allowed?
It's because you haven't defined C
as a type that is itself typed with 2 type parameters.
Try something like this:
public class MyClass <A, B, C extends Map<A, B>> {
// This compiles
}
If your template parameters don't share share a class hierarchy, you can use an interface.
For example:
interface IConverter<TFrom, TTo>
{
TTo convert(TFrom from);
}
class IntToStringConverter implements IConverter<Integer, String>
{
public String convert(Integer from)
{
return "This is a string: " + from.toString();
}
}
class ConverterUser<TConverter extends IConverter<TFrom, TTo>, TFrom, TTo>
{
public ConverterUser()
{
}
private List<TConverter> _converter2;
private TConverter _converter;
public void replaceConverter(TConverter converter)
{
_converter = converter;
}
public TTo convert(TFrom from)
{
return _converter.convert(from);
}
}
class Test
{
public static void main(String[] args)
{
ConverterUser<IntToStringConverter, Integer, String> converterUser =
new ConverterUser<IntToStringConverter, Integer, String>();
converterUser.replaceConverter(new IntToStringConverter());
System.out.println(converterUser.convert(328));
}
}
This is not possible in Java. See the Type Variables section of the language definition along with Generic Classes and Type Parameters . I recently saw (somewhere) a mention that Java is incapable of this but Scala can do it. This is confirmed by S4.4 of the Scala Language Specification .
This is also somewhat confirmed by the following code compiling successfully.
class MyClass [A, B, C [A, B]] {
}
Compiling in java yielded the follwing answers.
MyClass.java:1: > expected
class MyClass <A, B, C<A, B>> {
^
MyClass.java:1: <identifier> expected
class MyClass <A, B, C<A, B>> {
^
MyClass.java:1: ';' expected
class MyClass <A, B, C<A, B>> {
^
MyClass.java:2: reached end of file while parsing
}
^
4 errors
I would guess that there is an easier solution to your problem however, as this is somewhat unusual.
You don't have to declare nested types like that. Simply
class MyClass<A, B, C> {}
And when you create a MyClass, you could do something like
MyClass<List<String>, Set<Date>, Map<Integer, Long>> instance;
I am guessing you want MyClass to be a generic class with type parameters A, B, and C. Furthermore you want C to be a generic class with type parameters A and B.
So that I could write
MyClass < String , Date , Map < String , Date > >
MyClass < String , Date , Hashtable < String , Date > >
but not MyClass < String , Date , ElementVsitor < Date , String > >
Then I don't think you can do that.
This is effectively asking for higher kinded types in Java. Java does not support this directly, but it can be simulated in a somewhat roundabout way like so
interface H<K, T> { }
Here H
encodes a higher kinded type that takes a type parameter K
which itself takes parameter T
.
You can use this to eg implement a generic functor. Note how fmap
is effectively a function from H<K<T>>
to H<K<R>>
although we cannot directly declare it that way.
public interface Functor<K> {
<T, R> Function<H<K, T>, H<K, R>> lift(Function<T, R> f);
default <T, R> H<K, R> fmap(Function<T, R> f, H<K, T> h) {
return lift(f).apply(h);
}
}
See also my Github repository for full working examples. Further more have a look at this question , which takes the concept much further still.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.