2

This question is not the same as Eclipse warning - Class is a raw type. References to generic type Class<T> should be parameterized. Only the generated warning is the same.

The code below results in the warning:

X.PropertyType is a raw type. References to generic type X.PropertyType should be parameterized.

at the lines indicated when built using Eclipse. One quick fix offered by Eclipse is to add @SuppressWarnings("unchecked") but I don't want to do that without fully understanding the implications, which at the moment I don't.

How can I eliminate the warning without suppressing it? I've seen other questions on SO related to this warning but I think I need an answer specific to the code below to understand the issue.

import java.util.HashMap;
import java.util.Map;

public class X
{
    // *** WARNING ***
    private final Map<String, PropertyType> m_properties = new HashMap<String, PropertyType>();

    public class PropertyType<T>
    {
        private final String m_name;
        private final T m_value;
        private final Class<T> m_type;

        public PropertyType(String name, T value, Class<T> type)
        {
            m_name = name;
            m_value = value;
            m_type = type;
        }

        public String getName() { return m_name; }

        public T getValue() { return m_value; }

        public Class<T> getType() { return m_type; }
    }

    public <U> void setProperty(String name, U value)
    {
    // *** WARNING ***
        m_properties.put(name, new PropertyType(name, value, String.class));
    }
}

Also, in the method setProperty, I would like to pass the type of value when creating an instance of PropertyType. I'm just passing a String type at the moment. What is the best way to do that?

I could modify setProperty as follows:

public <U> void setProperty(String name, U value, Class<U> type)

but I've been looking for a better way.

Community
  • 1
  • 1
ksl
  • 4,519
  • 11
  • 65
  • 106
  • You will need to pass a Type while declaring your hashmap like example below: `private final Map> m_properties = new HashMap>();` Because it is class level parameter – jarvo69 Aug 16 '16 at 08:53
  • You require `m_properties` to have `String` by passing it `String.class` inside `setProperty`. But then you have a generic `T`. Why? Only `T = String` makes sense in this case. Or remove that and give a `Class` as parameter. – Tunaki Aug 16 '16 at 08:53

4 Answers4

2

Here, you're using a raw PropertyType type:

private final Map<String, PropertyType> m_properties = new HashMap<String, PropertyType>();
// -----------------------^^^^^^^^^^^^^

...but you've declared PropertyType as a parameterized type, so naturally the compiler and IDE warn you that you're doing the parameterized-to-raw thing, which usually indicates a bug.

Normally I'd say you need to parameterize it:

private final Map<String, PropertyType<T>> m_properties = new HashMap<String, PropertyType>();
// -----------------------------------^^^

...but you've said you don't want to parameterize X, the containing class.

You either need to parameterize X, or make PropertyType a raw type. Consider this method:

public <U> void setProperty(String name, U value)
    m_properties.put(name, new PropertyType(name, value, String.class));
}

It can be called with any U type, but your m_properties can only be created with a single T (or be raw).

Based on X, you don't want PropertyType to be parameterized. Or you want X to be (in which case you drop <U> from the setProperty declaration). That's basically the choice.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • If I do what you suggest then I get an error `T cannot be resolved to a type`, which can only be resolved by parameterising `X`. But that can't be right as I want an instance of `X` to contain a map with of different property types. – ksl Aug 16 '16 at 09:00
  • I don't want to parameterise `class X`. – ksl Aug 16 '16 at 09:21
  • Ah, I see you're point. I've changed it to `U` in the question. – ksl Aug 16 '16 at 09:39
  • @ksl: Either you parameterize `X` or you make `m_properties` use a raw type. I don't think you have a third option. :-) – T.J. Crowder Aug 16 '16 at 09:41
  • I don't want to parameterise `X` but I don't fully understand the implications of using raw types. Please can you elaborate. – ksl Aug 16 '16 at 09:49
  • 1
    @ksl: It means `m_value` in `PropertyType` would be `Object`, since the structure of `X` allows the calling code to add values of any type. – T.J. Crowder Aug 16 '16 at 09:53
  • Thanks for the clarification. I've just got totally confused over the whole thing and need to rethink it. I wonder if I should just delete the question to avoid any other users stumbling across this. – ksl Aug 16 '16 at 14:29
  • @ksl: I don't think you can, but you can flag it and ask a mod to do it for you if you like. – T.J. Crowder Aug 16 '16 at 14:39
2

You can use a wildCard to workaround the warning at the HashMap declaration. E.g.

HashMap<String, PropertyType<?>> map; //declare

Or pass in the final genericType if possible.

For the second problem, you can use

value.getClass();

To get its classType, and use that as identifier at the same time. (Might improve performance on the HashMap operations if the classObject is used as key instead of a String, though its micro optimization)

n247s
  • 1,898
  • 1
  • 12
  • 30
0

You will need to pass a Type while declaring your hashmap like example below:

private final Map<String, PropertyType<String>‌​> m_properties = new HashMap<String, PropertyType<String>‌​>();

Because it is class level parameter

jarvo69
  • 7,908
  • 2
  • 18
  • 28
0

What you are asking for probably doesn't work as you want it to.

You could have something like:

public class X<T> {
  private final Map<String, PropertyType<T>> m_properties = new HashMap<>();

Meaning: there is no way to use generics to allow for different kinds of PropertyType<T> objects within your Map ... and still have the compiler be checking those types. That is simply not possible.

And hint: read about java coding style guidelines. "Hungarian" notation together with "_" for variables names; bad style that is.

GhostCat
  • 137,827
  • 25
  • 176
  • 248