ksl
ksl

Reputation: 4709

Warning - Class is a raw type. References to generic type Class<T> should be parameterized

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.

Upvotes: 1

Views: 15441

Answers (4)

T.J. Crowder
T.J. Crowder

Reputation: 1074178

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.

Upvotes: 2

n247s
n247s

Reputation: 1918

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)

Upvotes: 2

GhostCat
GhostCat

Reputation: 140427

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.

Upvotes: 0

jarvo69
jarvo69

Reputation: 8339

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

Upvotes: 0

Related Questions