Java: Can we cast a set into an arraylist ? - java

I have a hashmap called gg. I want to take out its keys using keySet() method and pass them as parameter of another method.
method_A( gg.keySet());
public void method_A(ArrayList<Integer> jj){
....
}
But I got this error:
error: incompatible types: Set<Integer> cannot be converted to ArrayList<Integer>.
Then I saw this:
method_A (new ArrayList<Integer>(gg.keySet()));
What is it doing actually ? It looks like type casting to me. I am puzzled. Could someone explain to me what is going on ?

new ArrayList<Integer>(gg.keySet()) is not type casting. It's more like a copy constructor (though actual copy constructors usually take an argument of the same type that is being instantiated, which is not the case here).
It's creating a new ArrayList<Integer> instance using the constructor that accepts a Collection as an argument. It adds all the elements found in the Collection to the new ArrayList.
Here's the doc of that constructor :
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* #param c the collection whose elements are to be placed into this list
* #throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c)

Related

Adding a something to a wildcard <?> collection in Java

Hello I have this attribute: private Map<Function<T, Collection<?>>, Template<?>> functionTemplateMap = new LinkedHashMap<>(); To make a map from a function to a template (the template is what I'm coding, if needed I can provide the whole code), and then I have a function called forEach:
/**
*
* #param <E> Type of the new objects
* #param function Lambda that returns a collection of objects of any type
* #param string String with gaps
* #param functions Lambda(s) that accept as argument objects of the same type as the collection returns and will be used to fill the gaps
*/
public <E extends Comparable<E>> void addForEach(Function<T, Collection<E>> function, String string, Function<E, Object> ...functions) {
Template<E> temp = new Template<>();
temp.add(string, functions);
this.functionTemplateMap.put(function, temp);
}
The thing is that the collection that returns the function and the list of functions used as parameters must be of the same type, so I added the <E> at the beggining of the function, but since the functionTemplateMap has a Collection<?> so that it is more general, when adding it with put it gives me an error saying collection should be <?>, but then I can not check if the list of functions is of the same type <E>

What Iterable will be used when working with Guava Iterables

Given a class of the below structure:
public class Section extends IterableWidgetTemplate<Item>{
private List<WebElement> items1;
// other non iterable methods
private int indexOf(final Item item) {
int i = Iterables.indexOf(this, new Predicate<Item>() {
. . .
});
return i;
}
where Iterables is a Guava com.google.common.collect.Iterables that, according to its documentation, contains static utility methods that operate on objects of type Iterable.
Now in the class that I described above, this is passed as an iterable to the private int indexOf() method.
Questions:
What am I going to iterate over in this object? Am I right in my assumption that the Iterables class will use the only iterable method that is available in the object that is being passed to it? So in this case we have the List<WebElement> variable inside this object.
If the answer to 1. is "yes", what would have happened if the Section class had more than one iterable variable? Which one of them will be used for iteration?
Iterables.indexOf() takes as its first parameter an object which implements the Iterable interface. So, what Iterables.indexOf() iterates over is defined by the object passed in as a parameter, in your example the Section class. It's not using a variable however - it will call the Iterable.iterator() method on your Section object. It's not possible to have more than one of those methods so there can be no cases where there's confusion about what Iterables.indexOf() will iterate over.

Specifying generics for a class type

I have a method which essentially handles casting for config types, however upon specifying a generic type (such as List), it becomes a problem of how to handle the specific type. In an ideal world, something such as using a type witness:
List<String> someVal = MyConfig.SOME_VAL.<List<String>>.as(List.class);'
(The full as code):
/**
* Attempts to return the {#link Config} value as a casted type. If the
* value cannot be casted it will attempt to return the default value. If
* the default value is inappropriate for the class, the method will
* throw a {#link ClassCastException}.
*
* #since 0.1.0
* #version 0.1.0
*
* #param <T> The type of the casting class
* #param c The class type to cast to
* #return A casted value, or {#code null} if unable to cast. If the passed
* class parameter is of a primitive type or autoboxed primitive,
* then a casted value of -1 is returned, or {#code false} for
* booleans. If the passed class parameter is for {#link String},
* then {#link Object#toString()} is called on the value instead
*/
default public <T> T as(Class<T> c) {
Validate.notNull(c, "Cannot cast to null");
Validate.isTrue(Primitives.unwrap(c) != void.class, "Cannot cast to a void type");
Object o = this.get();
if (o == null) {
T back = Reflections.defaultPrimitiveValue(c);
if (back != null) { //catch for non-primitive classes
return back;
}
}
if (c == String.class) {
return (T) String.valueOf(o);
}
if (c.isInstance(o)) {
return c.cast(o);
}
if (c.isInstance(this.getDefault())) {
return c.cast(this.getDefault());
}
throw new ClassCastException("Unable to cast config value");
}
So essentially that leaves me with a two-part question: Why can't type witnesses be used for generics on a class (such as List(raw) -> List<String>), and how can I go about supporting retrieving a class with generic bounding without doing extraneous casting? The first point particularly baffles me, since this is perfectly legal:
List<String> test = new ArrayList<>();
test = MyConfig.FRIENDLY_MOBS.as(test.getClass());
Despite it returning a raw-typed list
That line is really evil (type erasure / raw type) as there is no check whatsoever whether the Collection type really contains strings.
test = MyConfig.FRIENDLY_MOBS.as(test.getClass());
I think the easiest solution is to write an as method that takes the class object of both the collection type as well as the element class. See this following example (in static scope, so you have to adjust it):
static List<String> words = Arrays.asList("Hello", "Bonjour", "engine");
static public <E, Coll extends Collection<E>> Coll as(Class<? extends Collection> collClass, Class<E> elemClass) {
if (collClass.isInstance(words)) {
Collection coll = collClass.cast(words);
for (Object o : coll)
if (!elemClass.isInstance(o))
throw new ClassCastException("BAM");
return (Coll)coll;
}
return null;
}
Now the following behaviour is found:
final List<String> list = as(List.class, String.class); // works
final List<String> list = as(List.class, Integer.class); // compile error: type check
final List<Integer> list = as(List.class, String.class); // compile error: type check
final List<Integer> list = as(List.class, Integer.class); // ClassCastException
As for other attempts: iirc Jackson had some magic TypeToken stuff going on that allowed to capture types such as List<String>. It somehow abused Enum<T> I think...
Your idea of type witnesses is indeed the way to go, but you need a better type witness that does not only capture the raw type (here List) but also its generic parameters. This is not easy in Java because in most places the generic parameters are not available at runtime due to type erasure. Java's reflection API uses interfaces that are subinterfaces of Type as a runtime representation of generic types, but these are unsuited for your purpose because they do not provide any compile-time type information.
However, with a trick it is possible to achieve what you want.
The trick is based on the fact that if a class (example: MyClass) inherits from a generic type (example: List<String>), there is no type erasure. You can at runtime retrieve the information that MyClass inherits from List<String> (using the method Class.getGenericSuperclass()).
Subclassing the actual type we want to pass would however be very inflexible (for example this would not work for final classes). Thus we create a special class (often called TypeToken) from which we can inherit. The TypeToken class has a generic parameter, and in the subclass we specify the type we want to pass as this parameter. Of course creating a special class for every different value you want to pass would usually be quite cumbersome, but fortunately we can use anonymous classes to make this easy.
Putting it all together, a solution could look like the following.
Definition of our type token:
public abstract class TypeToken<T> {}
Definition of method as:
public <T> T as(TypeToken<T> typeToken) {
Type targetType = typeToken.getClass().getGenericSuperclass();
// use targetType here, e.g.
if (targetType instanceof ParameterizedType) { ... }
And calling it:
List<Integer> list = MyConfig.SOME_VAL.as(new TypeToken<List<String>>() {});
Notice the {} that declares the anonymous subclass and avoids the type erasure.
Even better would be to use an existing class as the type token, for example the class TypeToken of the great Guava library (if you do not know this library yet, also look at what else it offers and consider using it!). This class also provides additional helper methods that make it easer to use the token in the as method (directly using Type instances can be difficult). The Guava wiki has more information on its TypeToken class.
If you are worried about creating too many classes, you can of course easily provide a few default instances for common cases like TypeToken<List<String>> etc. Guava's TypeToken also has an of(Class<T>) method that can be used for non-generic types, so the subclasses would be restricted to cases where it is actually necesary.
Other projects also use this trick, for example Guice with class TypeLiteral (explanation), Gson (TypeToken), and Jackson (TypeReference). So I would not worry too much about the amount of subclasses, given that they do not clutter your source code.

Java - Casting to E[]

When I cast to E[] (the class parameter), it requires me to add
#SuppressWarnings("unchecked")
For example:
E[] anArray = (E[]) new Object[10];
Should I be doing something different, or is it supposed to be like this?
Thanks
It is correct. Imagine:
Object[] o = new Object[10];
o[0] = new A(); // A is not a subclass of E
E[] e = o; // Now you have broken the type system: e[0] references something that is not an E.
The way it works, you have to explicitly cast in order to make the compiler ignore this possibility.
You should probably read the Effective Java book. In short, it is impossible to tell exactly what is the right course of action for you is because we don't know what you are doing, but generally you should not be suppressing this warning. So most likely the solution for you is to use typesafe generic collections instead of arrays.
It's supposed to be doing that because of type erasure.
To avoid having to suppress that warning, the only thing you can do is use a List<E> (or similar Collection).
Yes, you are supposed to do it this way, since we can't initialise arrays of generics like this:
E[] array = new E[10]; // Compile error
You really have to do it as you wrote. There is no way around that I know.
Another approach is to use an array of Objects (instead of E). You can see that the Java API developers did it also like this inside the ArrayList class:
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private transient Object[] elementData;
And they simply initialise this array like this:
elementData = new Object[size];
And everywhere they use it they cast the array content:
/**
* Returns the element at the specified position in this list.
*
* #param index index of the element to return
* #return the element at the specified position in this list
* #throws IndexOutOfBoundsException {#inheritDoc}
*/
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
I'm not really sure, but I think that the first approach is faster since the casting is not needed at runtime. The Java VM will spent some time casting it, I think. Why do I think that? Because this gives an error at runtime:
Integer i = new Integer(34);
Object o = i;
String s = (String) o; // Runtime error
So this means that the VM really checked if it is a String. But the fact that the compiler does type erasure makes me think it doesn't make any difference. Can someone clarify?

Suspicious call to java.util.Collection.contains

I am getting the following warning from my NetBeans IDE.
Suspicious call to java.util.Collection.contains
Expected type T, actual type Object
May I know what does that means?
This doesn't make sense to me. Both List and Collection class's contains method, are using Object as their method parameter.
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
*
* #author yan-cheng.cheok
*/
public abstract class AbstractCollection<T> implements Collection<T> {
protected List<T> list = new ArrayList<T>();
public boolean contains(Object o) {
// Suspicious call to java.util.Collection.contains
// Expected type T, actual type Object
return list.contains(o);
}
Code snippet from Collection class
/**
* Returns <tt>true</tt> if this collection contains the specified element.
* More formally, returns <tt>true</tt> if and only if this collection
* contains at least one element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>.
*
* #param o element whose presence in this collection is to be tested
* #return <tt>true</tt> if this collection contains the specified
* element
* #throws ClassCastException if the type of the specified element
* is incompatible with this collection (optional)
* #throws NullPointerException if the specified element is null and this
* collection does not permit null elements (optional)
*/
boolean contains(Object o);
Code snippet from List class
/**
* Returns <tt>true</tt> if this list contains the specified element.
* More formally, returns <tt>true</tt> if and only if this list contains
* at least one element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>.
*
* #param o element whose presence in this list is to be tested
* #return <tt>true</tt> if this list contains the specified element
* #throws ClassCastException if the type of the specified element
* is incompatible with this list (optional)
* #throws NullPointerException if the specified element is null and this
* list does not permit null elements (optional)
*/
boolean contains(Object o);
In the call to list.contains you are comparing an object to a type T. Casting o to type T should resolve your warning.
Calling the contains method with an Object instead of the generic type may be a programming error. Since the code is still valid the compiler will only show a warning.
An example why this warning is necessary:
List<Long> l = new ArrayList<Long>();
l.add(1l);
l.contains(1);
The code is valid but would always return false. An error that is normally hidden by contains accepting object instead of a generic type, so the compiler is limited to warnings.
Since there are valid use cases for passing an object, you should be able to use a #SuppressWarnings() annotation to hide this warning (only do this if you know what you are doing).

Categories