Generic method <?> Type Arguments - java

In a library for charts I found the following class:
public class SeriesBuilder<T> {
private T[] data;
private SeriesBuilder() {
}
public static SeriesBuilder<?> get() {
return new SeriesBuilder();
}
public SeriesBuilder<T> withData(T... data) {
this.data = data;
return this;
}
public Series<T> build() {
Series<T> series = new Series<T>();
series.setData(data);
return series;
}
}
Using code:
SeriesBuilder.get()
.withData(<<<<<???>>>>)
.build()
I'm not able to find out how to use the class because of the <?> Type. I can't find an argument that fullfills the signature. How to use this?

I'm not able to find out how to use the class because of the <?> Type. I can't find an argument that fullfills the signature. How to use this?
You pretty much can't use it. There is no way to obtain a SeriesBuilder instance except via SeriesBuilder.get(), and the type parameter of an instance that you obtain that way is unknown -- in fact, what get actually instantiates is the raw type. You should be able to produce a series of nulls if you wish.
There cannot even be any subclasses of SeriesBuilder (that might be more usable), because its only constructor is private.
Without putting too fine a point on it, this SeriesBuilder is pretty much an abomination. There is an argument to be made for preferring factory methods (such as SeriesBuilder.get()) over constructors, but that implementation is terrible. In addition to the type parameter issues, it does not initialize the resulting object to a valid state. That has to be done separately via withData(), so what is the point of get() supposed to be?
I'm inclined to think that whoever wrote that was looking for something that would have been better expressed via this variation on withData():
public static <T> SeriesBuilder<T> withData(T ... data) {
SeriesBuilder<T> builder = new SeriesBuilder<>();
builder.data = data;
return builder;
}
You might use that as
SomeType item1 = /* value */;
SomeType item2 = /* value */;
SomeType item3 = /* value */;
Series<SomeType> series =
SeriesBuilder.withData(item1, item2, item3)
.build();

Related

Generic overload at compile-time

Its possbile, to design a way to call different method-overloads at compile-time?
Lets say, I have this little class:
#RequiredArgsConstructor
public class BaseValidator<T> {
private final T newValue;
}
Now, I need methods that returns diffrent Objects (depends on the T).
Like this:
private StringValidator getValidator() {
return new ValidationString(newValue);
}
private IntegerValidator getValidator() {
return new Validation(newValue);
}
At the end, I want a call-hierachy that is very fluent and looks like this:
new BaseValidator("string")
.getValidator() // which returns now at compile-time a StringValidator
.checkIsNotEmpty();
//or
new BaseValidator(43)
.getValidator() // which returns now a IntegerValidator
.checkIsBiggerThan(42);
And in my "real"-case (I have a very specific way to update objects and a lot of conditions for every object and the chance of a copy-and-paste issue is very high. So the wizard enforces all developer to implement exact this way.) :
I tried diffrent ways. Complex generics inside the Validators, or play around with the generics. My last approch looks like this.
public <C> C getValidator() {
return (C) getValidation(newValue);
}
private ValidationString getValidation(String newValue) {
return new StringValidator(newValue);
}
private ValidationInteger getValidation(Integer newValue) {
return new IntegerValidation(newValue);
}
What is the trick?
//edit: I want it at compile-time and not with instanceof-checks at runtime.
What is the trick?
Not to do it like this.
Provide static factory methods:
class BaseValidator<T> {
static ValidationString getValidation(String newValue) {
return new ValidationString(newValue);
}
static ValidationInteger getValidation(Integer newValue) {
return new ValidationInteger(newValue);
}
}
class ValidationString extends BaseValidator<String> { ... }
class ValidationInteger extends BaseValidator<Integer> { ... }
Although I consider this to be odd: you are referring to subclasses inside the base class. Such cyclical dependencies make the code hard to work with, especially when it comes to refactoring, but also perhaps in initialization.
Instead, I would suggest creating a utility class to contain the factory methods:
class Validators {
private Validators() {}
static ValidationString getValidation(String newValue) {
return new ValidationString(newValue);
}
static ValidationInteger getValidation(Integer newValue) {
return new ValidationInteger(newValue);
}
}
which has no such cycles.
A really important thing to realize about generics is that it is nothing more than making explicit casts implicit (and then checking that all of these implicit casts are type-safe).
In other words, this:
List<String> list = new ArrayList<>();
list.add("foo");
System.out.println(list.get(0).length());
is just a nicer way of writing:
List list = new ArrayList();
list.add((String) "foo");
System.out.println(((String) list.get(0)).length());
Whilst <String> looks like it is part of the type, it is basically just an instruction to the compiler to squirt in a load of casts.
Generic classes with different type parameters all have the same methods. This is the specific difficulty in your approach: you can't make the BaseValidator<String>.getValidator() return something with a checkIsNotEmpty method (only), and the BaseValidator<Integer>.getValidator() return something with a checkIsGreaterThan method (only).
Well, this isn't quite true to say you can't. With your attempt involving the method-scoped type variable (<C> C getValidator()), you can write:
new BaseValidator<>("string").<StringValidator>getValidator().checkIsNotEmpty()
(assuming StringValidator has the checkIsNotEmpty method on it)
But:
Let's not mince words: it is ugly.
Worse than being ugly, it isn't type safe. You can equally write:
new BaseValidator<>("string").getValidator().checkIsGreaterThan(42)
which is nonsensical, but allowed by the compiler. The problem is that the return type is chosen at the call site: you will either have to return null (and get a NullPointerException when you try to invoke the following method); or return some non-null value and risk a ClassCastException. Either way: not good.
What you can do, however, is to make a generic validator a parameter of the method call. For example:
interface Validator<T> {
void validate(T b);
}
class BaseValidator<T> {
BaseValidator<T> validate(Validator<T> v) {
v.validate(this.value);
}
}
And invoke like so, demonstrating how you can chain method calls to apply multiple validations:
new BaseValidator<>("")
.validate(s -> !s.isEmpty())
.validate(s -> s.matches("pattern"))
...
new BaseValidator<>(123)
.validate(v -> v >= 0)
...
We decided to add more class-steps. You can go a the generic way or a way with explict types (in this examples, String). Our requirement for all updates-methods (we have many database-objects ...) are a little complicated. We want only one update-method (for each db-object), which ...
Ignore fields, that are null.
Ignore field, that are equal to "old" value.
Validate not ignored fields.
Save only, when no validation-issues occur.
To do that with many if-blocks is possbile but not really readable. And copy-paste-fails haves a high probably.
Our code look like this:
private void update(#NonNull final User.UpdateFinalStep params) {
UpdateWizard.update(dbUserService.get(params.getId())
.field(params.getStatus())
.withGetter(DbUser::getAccountStatus)
.withSetter(DbUser::setAccountStatus)
.finishField()
.field(Optional.ofNullable(params.getUsername())
.map(String::toLowerCase)
.orElse(null))
.withGetter(DbUser::getUsername)
.withSetter(DbUser::setUsername)
.beginValidationOfField(FieldName.USERNAME)
.notEmptyAndMatchPattern(USERNAME_PATTERN, () -> this.checkUniqueUsername(params.getUsername(), params.getId()))
.endValidation()
.field(params.getLastName())
.withGetter(DbUser::getLastname)
.withSetter(DbUser::setLastname)
.beginValidationOfField(FieldName.USER_LASTNAME)
.notEmptyAndMatchPattern(LAST_NAME_PATTERN)
.endValidation()
.field(params.getFirstName())
.withGetter(DbUser::getFirstname)
.withSetter(DbUser::setFirstname)
.beginValidationOfField(FieldName.USER_FIRSTNAME)
.notEmptyAndMatchPattern(FIRST_NAME_PATTERN)
.endValidation()
.save(dbUserService::save);
}
This is very readable and allows to add new field in a very simple way. With the generics, we dont give the "stupid developer" a chance to do an misstake.
As you can see in the image, accountStatus and username points to different classes.
At the end, we can use in a very fluent way the update-method:
userService.startUpdate()
.withId(currentUserId)
.setStatus(AccountStatus.INACTIVE)
.finallyUpdate();

How to avoid Generics in this case?

class Attribute<T>{
private T attr;
public Attribute(T attr){
this.attr = attr;
}
}
Class Matrix<T>{
private String name;
List<Attribute<T>> list;
public Matrix(String name, T t){
this.name = name;
list = new ArrayList<>();
list.add(new Attribute<T>(t));
}
}
interface Extractor<T> {
public List<Matrix<T>> extract();
}
InfoExtractor implements Extractor<String>{
public List<Matrix<String>> extract(){
List<Matrix<String>> matrixList = new ArrayList<>();
// The problem is here!!!!
matrixList.add(new Matrix<String>("abc"));
}
}
Document<T>{
Map<String, List<Matrix<T>>> matrixMap;
public void process(){
...
Extractor<T> extractor = (Extractor<T>) new StringExtractor(sent);
List<Matrix<T>> matrix = extractor.extract(...);
}
My question is, is there a way to avoid defining Matrix as a generic type ? The reason I want to avoid is that the "List<Attribute<T>> " is used in multiple other classes, either as private member variables, or method return types. Due to Attribute, it seems I have to define some other related classes as generic types too, which causes my problem.
In this case, is there a way to not define Matrix as generic, but keep the "list" variable as a generic type?
Your problem lies not in the generic implementation, but in its usage:
class InfoExtractor implements Extractor{
// The problem is actually here
public <T> List<Matrix<T>> extract(){
List<Matrix<T>> matrixList = new ArrayList<>(); //and here
// "The problem is here!!!!"
matrixList.add(new Matrix<String>("abc"));
}
}
The <T> indicates that you are binding a new generic type relative to the method invocation. In short, a new T type just for this method's execution. You also make a List<Matrix<T>> but then attempt to add a new Matrix<String> back. If you know the list is going to be of the type Matrix<String>, then you can specify that in InfoExtractor:
//If you cannot generify the interface for some reason
interface Extractor {
public List<? extends Matrix<?>> extract(); //explained at bottom
}
//IDEALLY, then implement Extractor<String> instead
interface Extractor<T> {
public List<Matrix<T>> extract();
}
class InfoExtractor implements Extractor { //or Extractor<String>
public List<Matrix<String>> extract() {
List<Matrix<String>> matrixList = new ArrayList<>();
matrixList.add(new Matrix<>("abc"));
return matrixList;
}
}
Of course, you can see the method signature for Extractor changed. Due to using a nested generic on the return type, things will get a bit messy for type matching at compile-time. The <?> for the Matrix is fairly self-explanatory, we're returning multiple and possibly unknown types inside of the Matrix.
By specifying ? extends Matrix on Extractor, we're specifying the proper variance. Concrete generics are invariant, thus a List<Toyota> isn't a List<Car>, even if Toyota is a subclass of Car. If we want the Matrix to be covariant, then we need the bounding on Matrix as well unfortunately. This means in effect, ignoring Liskov's substitution principal, we'd essentially be referencing the concrete subclasses for the extractors (InfoExtractor ex vs Extractor ex), especially from a usability standpoint (as the concrete classes can return proper type safety whereas the interface cannot).
This of course, is handled much more sanely/cleanly when you specify the <T> for the matrices in the list as a class-level generic type.
It depends on what you would like to do.
If you intend to use Matrix to hold a single type of attribute, that is T then the best approach seems to be the one you posted as you get to have compile time type checking.
If you remove the generic type T from Matrix then you cannot know the type of each attribute. You can completely remove T from Matrix declaration and use the wildcard for the Attribute variable. While this would allow you to store attributes of different T types in the same Matrix object, it will remove the compile type checking. In other words, the classes using the Matrix would have to know what class to expect and perhaps cast each attribute to the class expected.
Class Matrix{
private String name;
List<Attribute<?>> list;
public Matrix(String name, T t){
this.name = name;
list = new ArrayList<>();
list.add(new Attribute<>(t));
}
}
Adding a Class variable and saving the Class object inside the attribute, could help you retain some information in runtime to identify the class of the objects inside the attribute.
class Attribute<T>{
private T attr;
private final Class<T> clazz;
public Attribute(T attr, Class<T> clazz){
this.attr = attr;
this.clazz=clazz;
}
public Attribute(T attr){
this.attr = attr;
Objects.requireNonNull(attr);
this.clazz= (Class<T>) attr.getClass();
}
}
Using this approach the original constructor can be used only for non null values, otherwise the class object should be provided by the programmer.

Getting behavior of Java's Class<? extends Map> in .NET

I have a generic class in java defined as:
public static class KeyCountMap<T>
{
private Map<T, MutableInt> map = new LinkedHashMap<T, MutableInt>();
// ... rest of the properties...
public KeyCountMap()
{ }
#SuppressWarnings({ "unchecked", "rawtypes" })
public KeyCountMap(Class<? extends Map> mapType) throws InstantiationException, IllegalAccessException
{
map = mapType.newInstance();
}
//... rest of the methods...
}
I have defined same class in .NET as:
public static class KeyCountMap<T>
{
private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();
// ... rest of properties...
public KeyCountMap()
{ }
public void KeyCountMap<T>(T obj) where T : Dictionary<T, MutableInt>
{
obj = new T(); // Unable to define new instance of T
map = obj; // Unable to convert T to base class
}
}
And then a method is defined to sort map of type KeyCountMap<T> by value in the descending order . The method is defined as:
public static KeyCountMap<T> SortMapByDescendValue<T>(KeyCountMap<T> _map)
{
List<KeyValuePair<T, MutableInt>> _list = new List<KeyValuePair<T, MutableInt>>(_map.EntrySet());
// whereas _map.EntrySet() return of type HashSet<KeyValuePair<T, MutableInt>>
_list = _list.OrderByDescending(_x => _x.Value).ToList();
KeyCountMap<T> _result = new KeyCountMap<T>();
foreach (KeyValuePair<T, MutableInt> _entry in _list)
{
_result.Put(_entry.Key, _entry.Value);
}
return _result;
}
How can I get corrected the class defined in .NET ?
I assume you know Java erases any generic type information after compiling (there's metadata for variables, but actual objects are void of generic type information). Moreover, your code is not type safe:
#SuppressWarnings({ "unchecked", "rawtypes" })
You're using this because you're creating a non-parameterized instance of Map.
In .NET, you don't get around the type system like this, because generic type information is kept and used at runtime.
Let's see your C# code:
public static class KeyCountMap<T>
A static class in C# is a class that cannot be instanced, it's used for its static members alone. I think you don't want this. Perhaps KeyCountMap is a static nested class in Java, as opposed to an inner class.
In C#, you don't have inner classes. Nested classes don't share data with an instance of the containing class, it's as if the name of the containing class is part of the namespace for the nested class. So, you don't need, and actually don't want, the static keyword here.
{
private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();
In .NET, Dictionary is a class. To keep the intent, you should use IDictionary, the corresponding interface, as the type for the map field.
// ... rest of properties...
public KeyCountMap()
{ }
public void KeyCountMap<T>(T obj) where T : Dictionary<T, MutableInt>
Why the void return type, isn't this a constructor?
In C#, constructors can't be generic. You probably want a Type.
Your C# code just doesn't make sense, so here's what you could do:
public KeyCountMap(Type dictionaryType)
{
if (!typeof(IDictionary<T, MutableInt>).IsAssignableFrom(dictionaryType))
{
throw new ArgumentException("Type must be a IDictionary<T, MutableInt>", nameof(dictionaryType));
}
map = (IDictionary<T, MutableInt>)Activator.CreateInstance(dictionaryType);
}
}
We're checking the type before creating an instance. If we didn't, we would create an instance, the cast would fail and the assignment wouldn't even happen, so the new instance would just be garbage.
It may be that the actual instance will be a proxy; if so, you may not want to check the type before creating an instance.
You can't just copy-paste Java as C# (or vice-versa) and expect to make just a few changes until it works, for some definition of works, e.g. it compiles. The languages are not that similar, and chances are that too many subtle things are wrong.
This approach might be fun at first, but you'll stumble so often it will soon stop being any fun at all. You should learn the basics and understand the way things are done in the target language before you start translating code line-by-line. Many times, you may find that something you had to do in one environment already exists in the other or vice-versa, or that something may take more or less steps to do in the other, etc.
In this particular case, Java made Class be a generic class, while .NET kept Type a non-generic class. In .NET only interfaces and delegates may state generic type covariance or contravariance. This is rather restrictive anyway, if Type was generic, the intended uses could be either covariant or contravariant. But remember that in Java, a generic Class<T> at runtime is as good as Class, it only has any value at compile time and you can tell the compiler you know better anyway, just like you did.
There are two problems. First, you need to tell the compiler that T has a parameterless constructor, so you can call new T(). You can do that by providing the new() argument to the class definition.
You also have to tell the compiler that T is actually the dictionary you are trying to assign, so we have to extend the class a little more:
public class KeyCountMap<K>
{
private Dictionary<K, MutableInt> map = new Dictionary<K, MutableInt>();
// ... rest of properties...
Note that K is the key type of the dictionary, which you didn't specify yet.
Second, the T in your method can be another T than in your class. Omitting that will do the trick:
public void Map()
{
var obj = new Dictionary<K, MutableInt>(); // Unable to define new instance of T
map = obj; // Unable to convert T to base class
}
Maybe this is what you want?
public class KeyCountMap<T>
where T : new()
{
private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();
// ... rest of properties...
public KeyCountMap()
{ }
public KeyCountMap(T obj)
{
obj = new T();
map = (Dictionary<T, MutableInt>)(object)obj;
}
}

Avoiding Returning Wildcard Types

I have a class with a collection of Wildcard Types that is a singleton, something like:
public ObliviousClass{
private static final ObliviousClass INSTANCE = new ObliviousClass();
private Map<Key, Type<?>> map = new HashMap<Key, Type<?>>();
public void putType(Key key, Type<?> type){
map.put(type);
}
// returns the singleton
public static ObliviousClass getInstance(){
return INSTANCE;
}
}
I'd like to be able to add different Parameterized types to this collection in client code:
void clientMethod(){
ObliviousClass oc = ObliviousClass.getInstance();
Type<Integer> intType = ...
Type<String> stringType = ...
oc.putType(new Key(0), intType);
oc.putType(new Key(1), stringType);
}
Up to this point, as I understand it, everything is ok. But a client also needs to be able to get a Type<?> provided the Key. So a method something like the following would be added to ObliviousClass:
public Type<?> getType(Key key){
return map.get(key);
}
But in my handy copy of Effective Java, I read:
Do not use wildcard types as return types.
I understand the issue, as the client would have to cast the returned Type<?>. But I really do not want to make ObliviousClass a generic type, ObliviousClass<T>, because then my client code above would not work...
Is there a better design for what I am trying to do?
-My current solution is to provide a static method for the client; something along the lines of:
public static <T> void getType(ObliviousClass instance, Key key, Type<T> dest){
dest = (Type<T>)instance.getType(key);
}
I searched around, but wasn't able to find an answer that totally cleared my confusion.
Here's a type-safe way to store multiple instances of a given type in a map. The key is that you need to provide a Class instance when retrieving values in order to perform runtime type-checking, because static type information has been erased.
class ObliviousClass {
private final Map<Key, Object> map = new HashMap<Key, Object>();
public Object put(Key key, Object value)
{
return map.put(key, value);
}
public <T> T get(Key key, Class<? extends T> type)
{
return type.cast(map.get(key));
}
}
Usage would look like this:
oc.put(k1, 42);
oc.put(k2, "Hello!");
...
Integer i = oc.get(k1, Integer.class);
String s = oc.get(k2, String.class);
Integer x = oc.get(k2, Integer.class); /* Throws ClassCastException */
Simply type your class:
public ObliviousClass <T> {
private Map<Key, Type<T>> map = new HashMap<Key, Type<T>>();
public void putType(Key key, Type<T> type){
map.put(type);
}
public Type<T> getType(Key key){
map.get(key);
}
}
FYI, at this point you have the delegation pattern in play.
Your example client code would need to declare two instances of ObliviousClass: ObliviousClass<String> and ObliviousClass<Integer>.
Edit:
If you must have a mixed bag of Types, you can impose a type on your method, but you'll get a compiler warning for an unsafe cast:
public class ObliviousClass {
private final Map<Key, Type<?>> map = new HashMap<Key, Type<?>>();
public void putType(Key key, Type<?> value) {
map.put(key, value);
}
#SuppressWarnings("unchecked")
public <T> Type<T> getType1(Key key, Class<T> typeClass) {
return (Type<T>)map.get(key);
}
#SuppressWarnings("unchecked")
public <T> Type<T> getType2(Key key) {
return (Type<T>) map.get(key);
}
}
Clients can type the calls to these methods like this:
Type<Integer> x = obliviousClass.getType1(key, Integer.class);
Type<Integer> y = obliviousClass.<Integer>getType2(key);
Take your pick as to which one you prefer and use that.
For those landing on this question these many years later, this is not how Java generics are designed to be used. (I was going to comment but had more to details.)
The generic pattern manages a single parent class per type ID rather than multiple different classes. If we consider the simpler List<T>, a list of strings OR integers (as List<String> or List<Integer>) is how generics are defined. One class per type. This way, there is a consistent type when the values are referenced. Storing unrelated types would be the same as List<Object>. Only the programmer can know when multiple types are stored and how to retrieve them with casting.
It would be ok to store subclasses to a parent class, but when accessed from the collection without casting, the parent class contact is all that is known. For instance, a generic collection defined with an interface like Map<String, Runnable>. However, only the run() method is visible even if other public methods are added to implementations (unless the programmer explicitly casts). To access additional methods, casting is necessary.
This is a limitation in Java. A language could be defined to know the L-Value type - even Java. But it wasn't. When new features are added, there are many backward compatible considerations [Sun and] Oracle take into account. Code compiled with generics was designed to run on older JVMs with type erasure. Java uses type erasure at compile time once it has determined that the generics are consistently reference. The bytecode uses Object as if the instance was (sort of) defined as List. If the choice was made to abandon backward compatibility, like Java 9 and 11, then multiple types might have been workable.
Your ObliviousClass, by design, doesn't know the parameterized type of the item it holds. So to be type safe, you should avoid such design :-\
But if you want to keep it, first things is that you will have to cast. There is no way out of this. But the way you do it is very error prone. For example:
oc.put(k1, intType);
oc.put(k2, strType);
Type<Integer> tint = oc.get(k1, Integer.class)
Type<String> tstr = oc.get(k1, String.class) // typo in k2: compile fine
And worst, due to type erasure, it will fail at runtime only once you actually use tstr, not when you get it from ObliviousClass.
So you can improve safety by tracking the parameterized type in some other way. For example, you could associate the key to the type, not losing it:
#Value // lombok
class Key<T> {
private int index;
}
class Type<T> {}
class ObliviousClass {
// side note: static final can be public safely
public static final ObliviousClass instance = new ObliviousClass();
private List<Type<?>> map = new ArrayList<>();
public <T> Key<T> appendType(Type<T> type){
// here, I found it nicer that obliviousClass generates and return the key
// otherwise use: "public <T> void appendType(key<T> key, Type<T> type)"
// that binds parametrized type of both key and type arguments
map.add(type);
return new Key<>(map.size() - 1);
}
public <T> Type<T> get(Key<T> key){
return (Type<T>) map.get(key.index);
}
}
Then you can use it such as:
Type<Integer> intType = new Type<>();
Type<String> strType = new Type<>();
Key<Integer> k1 = ObliviousClass.instance.appendType(intType);
Key<String> k2 = ObliviousClass.instance.appendType(strType);
Type<Integer> t1 = ObliviousClass.instance.get(k1);
Type<String> t2 = ObliviousClass.instance.get(k2);
Type<String> t3 = ObliviousClass.instance.get(k1); // won't compile

Creating generic method names in generic class?

Currently, I have something like this:-
public class MyHolder<T> {
private T value;
public MyHolder(T t) {
this.value = t;
}
public T getValue() {
return first;
}
public void setValue(T t) {
this.first = t;
}
}
With this, I can use it like this:-
MyBean bean = new MyBean();
MyHolder<MyBean> obj = new MyHolder<MyBean>(bean);
obj.getValue(); // returns bean
Instead of calling the getter/setter to be getValue() and setValue(..), is it possible to "generify" that too?
Essentially, it would be nice to have it getMyBean() and setMyBean(..), depending on the type passed in. Granted this is a very simple example, however if I create a generic holder class that takes N generic properties, then it would be nice to call it something meaningful instead of getValue1() or getValue2(), and so on.
Thanks.
No. There is no such feature in Java. I can't even imagine how it would look syntactically... void set<T>();? And how would the getter / setter for for instance MyHolder<? extends Number> look?
No, it's not possible unless you use some kind of source code generator to have the MyHolder class generated based on your input.
But on the other hand, even if you had this possibility, how it would be different from using a Map<String, T>? So the invocation would read:
MyBean bean = new MyBean();
MyHolder<MyBean> obj = new MyHolder<MyBean>(bean);
obj.get('value');
No, not possible. Java generics are based on type erasure, i.e. it's mostly syntactic sugar provided by the compiler. That means each generic class is actually implemented by a "raw type" where are type parameters are Object and which already contains all the methods. So it's fundamentally not possible to have different methods depending on type parameters.

Categories