Creating generic method names in generic class? - java

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.

Related

Generic method <?> Type Arguments

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();

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;
}
}

Associating a generic type with Enum in Java

I am creating a store for user preferences, and there are a fixed number of preferences that users can set values for. The names of the preferences (settings) are stored as an Enum:
public enum UserSettingName {
FOO,
BAR,
ETC
}
What I would like to be able to do is store a value type with the name so that the service will store the user's value with the correct Java type. For example, FOO might be a Long, and BAR might be a String. Up until now, we were storing all values as Strings, and then manually casting the values into the appropriate Java type. This has lead to try/catch blocks everywhere, when it makes more sense to have only one try/catch in the service. I understand that Enums cannot have generic types, so I have been playing around with:
public enum UserSettingName {
FOO(Long.class),
BAR(String.class),
ETC(Baz.class)
private Class type;
private UserSettingName(Class type) {
this.type = type;
}
public Class getType() {
return this.type;
}
}
I have a generic UserSetting object that has public T getSettingValue() and public void setSettingValue(T value) methods that should return and set the value with the correct type. My problem comes from trying to specify that generic type T when I create or retrieve a setting because I can't do something like:
new UserSetting<UserSettingName.FOO.getType()>(UserSettingName.FOO, 123L)
Sorry if this isn't exactly clear, I can try to clarify if it's not understood.
Thanks!
UPDATE
Both the setting name and value are coming in from a Spring MVC REST call:
public ResponseEntity<String> save(#PathVariable Long userId, #PathVariable UserSettingName settingName, #RequestBody String settingValue)
So I used the Enum because Spring casts the incoming data automatically.
Firstly you have to step back and think about what you're trying to achieve, and use a standard pattern or language construct to achieve it.
It's not entirely clear what you're going after here but from your approach it almost certainly looks like you're reinventing something which could be done in a much more straightforward manner in Java. For example, if you really need to know and work with the runtime classes of objects, consider using the reflection API.
On a more practical level - what you're trying to do here isn't possible with generics. Generics are a compile-time language feature - they are useful for avoiding casting everything explicitly from Object and give you type-checking at compilation time. You simply cannot use generics in this way, i.e. setting T as some value UserSettingName.Foo.getType() which is only known at runtime.
Look how it done by netty:
http://netty.io/wiki/new-and-noteworthy.html#type-safe-channeloption
They done it by using typed constants:
http://grepcode.com/file/repo1.maven.org/maven2/io.netty/netty-all/4.0.0.Beta1/io/netty/channel/ChannelOption.java#ChannelOption
EDIT:
public interface ChannelConfig {
...
<T> boolean setOption(ChannelOption<T> option, T value);
...
}
public class ChannelOption<T> ...
public static final ChannelOption<Integer> SO_TIMEOUT =
new ChannelOption<Integer>("SO_TIMEOUT");
...
}
EDIT2: you can transform it like:
class Baz {}
class UserSettingName<T> {
public static final UserSettingName<Baz> ETC = new UserSettingName<Baz>();
}
class UserSetting {
public <T> UserSetting(UserSettingName<T> name, T param) {
}
}
public class Test {
public static void main(String[] args) {
new UserSetting(UserSettingName.ETC, new Baz());
}
}
Enums are not the answer here. If you find yourself repeating code everywhere you could just create a utility class and encapsulate all the try/catch logic there. That would cut down on your code redundancy without majorly impacting your current code.
public class Util
{
public static MyObject getObjectFromString(String s)
{
try
{
return (MyObject)s;
}
catch(Exception e)
{
return null;
}
}
}
Then use as follows:
MyObject myObj = Util.getObjectFromString(string);

Is there an easier way to retrieve hard-coded type parameters in subclass implementations?

Given the following interface:
public interface GenericInterface<T> {
T getValue();
void setValue(T newVal);
}
And the following impl:
public class FixedImpl implements GenericInterface<String> {
String value;
public FixedImpl(String value) {
this.value = value;
}
#Override
public String getValue() {
return value;
}
#Override
public void setValue(String newVal) {
value = newVal;
}
}
I want to be able to determine that in the case of FixedImpl, String.class is the value for GenericInterface.T by interrogating FixedImpl.class.
My current idea:
Find a method name in GenericInterface that returns a <T> - in this case, there's "getValue".
Go through all the methods declared in FixedImpl.class with the same name, and collect all the different return types.
The return type farthest from Object is my value for GenericInterface.T.
But there's a couple of issues with this process:
It will only work for generic types containing a method that returns <T>. You can't safely do the same trick using setValue(T), because method overloading by parameter / arity is possible to do in Java source. It only works for T getValue() because overloading by return value isn't (unless I'm mistaken).
It might have weird interactions with Java 8 default methods, or a generic method implementation in a (still generic) possibly abstract superclass.
It's kinda kludgey.
Can anybody point me to an easier / more surefire way to get the same information? I can't seem to find one, but I thought I'd ask the superior intellects of the toobs :)
NB: If you're wondering why I'd need this, it's because I want to programatically construct mocks of container classes with similar hard-coded type parameters, but POJO values rather than simple Strings.
EDIT: I eventually worked out the following solution (before seeing #stony-zhang's):
public static <G> List<Class> getConcreteTypes(Class<? extends G> implClass, Class<G> genericClass) {
List<Class> concreteTypes = new ArrayList<Class>();
for (Type type : implClass.getGenericInterfaces()) {
if (!(type instanceof ParameterizedTypeImpl)) continue;
ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) type;
if (parameterizedType.getRawType() != genericClass) continue;
for (Object arg : parameterizedType.getActualTypeArguments()) {
if (!(arg instanceof Class))
throw new IllegalArgumentException("Class " + implClass + " not concrete for generic type " + genericClass);
concreteTypes.add((Class) arg);
}
}
return concreteTypes;
}
You can get the the class of T by the following way, in the interface add a method getMessageClass(), and in the FixedImpl add the implemented method,
#SuppressWarnings("rawtypes")
public Class getMessageClass() {
int index =0; //In the case, you only have a generic type, so index is 0 to get the first one.
Type genType = getClass().getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
throw new RuntimeException("Index outof bounds");
}
if (!(params[index] instanceof Class)) {
return Object.class;
}
return (Class) params[index];
}
In you case, if you have multiple subclass, to use it, create one abstract class to implement the interface GenericInterface, and then the all subclass extends from the new abstract class,
public class abstract abstractImpl<T> implements implements GenericInterface<T> {
#SuppressWarnings("rawtypes")
#Override
public Class getMessageClass() {
...............
}
}
Remember type erasure. At runtime, there is no type information about your generics anymore, unless you specify it yourself. And this is what you should do. Add this to your interface:
Class<T> getTypeOfT();
And add this to your FixedImpl:
#Override
public Class<String> getTypeOfT()
{
return String.class;
}
That way, you can always call getTypeOfT() on your GenericInterface<T> implementations and find out what type you are dealing with.
I don't think that you will be able to get reliable result because of Type Erasure:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety.
Generate bridge methods to preserve polymorphism in extended generic types.
Your approach of of using the types of objects returned may at first seem alright, but beyond the issues you have pointed out there is no way (at runtime) to know if The return type farthest from Object is my value for GenericInterface.T.
My suggestion would be to use some kind of configuration XML which could be generated at build time based on the java source (using a build tool such as Ant), which would in turn be used to create Mock objects, or you could simply generate the tests based off the source at buildtime.
If you don't mind changing your runtime code for the purposes of testing, Jan Doereenhaus' answer suggests a simple hard-coded mechanism for retrieving the type
EDIT:
Consider the scenario:
public class FixedImpl implements GenericInterface<SomeClass> {
#Override
public SomeClass getValue() {
return new SomeClass();
}
}
public class FixedImpl2 extends FixedImpl {
#Override
public SomeClass getValue()
{
return new SomeSubClass();
}
}
From this example, you can see that the sub class of FixedImpl is able to return a subclass of T (which is further down the inheritance hierarchy from Object)

Instantiate generified class after loading from repository

When writing a type handler for a repository (such as a web service or a database), I need to instantiate the type after the value is loaded from the repository.
Let's say I get a String value from the repository and there is a constructor with one String argument that I can use. If the return type has a type parameter, what else can I do besides instantiating the raw type? It seems raw types exist only for compatibility with legacy code so I would prefer not to use them.
Normally ? can be used as type parameter (if you know the type will be correct at runtime), but not in this case because you can't instantiate classes with wildcards as type parameter.
EDIT: some example code:
Let's say I have a PrimaryKey class like this:
public class PrimaryKey<R extends RepositoryObject<R>> {
private String value;
public PrimaryKey(String value) {
this.value = value;
}
}
And a set of classes that extend RepositoryObject, which is defined like this:
public class RepositoryObject<R extends RepositoryObject<R>> {
private PrimaryKey<R> pk;
public RepositoryObject(PrimaryKey<R> pk) {
this.pk = pk;
}
PrimaryKey<R> getPrimaryKey() {
return pk;
}
}
Example of a subclass:
public class User extends RepositoryObject<User> {
public User(PrimaryKey<User> userId) {
super(userId);
}
}
Now the type handling method for class PrimaryKey will look something like this:
public PrimaryKey<?> getValue(String stringValue) {
return new PrimaryKey<>(stringValue);
}
But this results in a compiler error (in the Maven build, not in Eclipse IDE strangely enough) even though I'm using the diamond operator instead of when instantiating. Maybe for some reason type inference doesn't work well because of the recursion in the type parameters.
In Java 7 you can typically use the diamond operator to get around this limitation:
Container<?> c = new Container<>(arg);
Otherwise you can use a helper factory method:
<T> Container<T> makeContainer(String arg) {
return new Container<T>(arg);
}
...
Container<?> c = makeContainer(arg);
EDIT:
Following your update, I can see you're using a recursive type parameter <R extends RepositoryObject<R>>. This compile error is due to limitations of javac when it comes to wildcard capture and recursive type parameters. See this related post for example: Java CRTP and Wildcards: Code compiles in Eclipse but not `javac`
Unfortunately, using a raw type is necessary as a workaround, but it can be hidden as an implementation detail:
public PrimaryKey<?> getValue(String stringValue) {
#SuppressWarnings("rawtypes") //a raw type is necessary to placate javac
final PrimaryKey<?> pk = new PrimaryKey(stringValue);
return pk;
}
class SomeBogusClass extends RepositoryObject<SomeBogusClass> { }
return new PrimaryKey<SomeBogusClass>(stringValue);
seriously, you can put anything there that satisfies the bounds, even some bogus class that has nothing to do with your code.

Categories