I didn't even know this was doable, but I saw while perusing some code online a method with a signature like this:
public List<Void> read( ... )
... What? Is there ever a reason to do this? What could this List even hold? As far as I was aware, it's not possible to instantiate a Void object.
It is possible that this method signature was created as a by-product of some generic class.
For example, SwingWorker has two type parameters, one for final result and one for intermediate results. If you just don't want to use any intermediate results, you pass Void as the type parameter, resulting in some methods returning Void - i.e. nothing.
If there were a method List<V> returnAllIntermediateResults() in SwingWorker with Void as the type parameter V, it would have created a method just like you posted in your question.
The code would be perfectly valid. You can instantiate any implementation of the List interface (e.g. ArrayList) with type parameter Void. But the only value a Void type can have is null. So the list could not hold anything else but nulls, if the implementation allows null elements.
One case in which it may be useful is if you wanted to return a collection of return values from a function. Say
static List<T> forEach(Func<A,T> func, List<A> items) {
List<T> ret = new List<T>();
for(int i = 0; i< items.length; i++) {
ret.add(func.call(items[i]);
}
return ret;
}
public static void main() {
...
List<Void> boringResult =
forEach(
new Func<Void, Integer> {#override Void call(Integer i) {...}});
}
Not that useful but you could see a case where it was required.
List<Void> is weird. It can only have null elements, since you can't create an object of type Void. I don't think there is a practical use for such a thing.
Void is part of java.lang. It's not a special keyword or anything. It's a "pseudo-type" (according to the docs) used to as a place-holder to represent the Class object corresponding to void, as in Class<Void>. From the docs for Class:
The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
The Void class exists mainly for the sake of the last part of this, so you can write:
Class<Void> voidType = void.class; // == Void.TYPE
just like you can write:
Class<Integer> intType = int.class; // == Integer.TYPE
I agree, it's odd.
I can see a use for it if you want to extend a generic class and return void from a method. I've bumped into a case were I want to use int and had to use Integer because java generics don't like primitive types.
public interface ObjectUserPool<E, T> {
public E useObject(T o);
}
public class NonReturningObjectUserPool extends ObjectUserPool<Void, Integer> {
public Void useObject(Integer i);
}
I think this is what the java API is saying, though to be honest I can't really find a use for NonReturningObjectUserPool.
Related
I have this:
class Male extends Person{..}
class Women extends Person{..}
// returns true if the return type of the given function is of type Women
boolean isReturnTypeWomen(Function<Integer, Person> function){
Class<?> type = function.getClass().getMethods()[0].getReturnType();
return type.isInstance(Women.class) ? true : false;
}
However, it always return true because type is always Object.
How can I check the instance type of the second parameter (the return type) of the given Function)?
Some Function subclasses will provide an apply method with covariant return type and a synthetic bridge to forward invocation across. However, Function instances will typically be lambdas or function references, so will not.
Consider, as a counterexample, the following method.
public static <T,R> Function<T,R> nothing(Function<T,R> fun) {
return t -> fun.apply(t);
}
The Function returned by this method will always be of the same class, but T may change. Therefore the class cannot reference the type.
A benefit of this is that the function objects do not need to carry around the overhead of extra data to represent type arguments, which are of no use in type-safe code anyway.
It can't not be - the parameter is a Function<Integer, String>.
getMethods[0] doesn't work. For example:
public class Example implements Function<Integer, String> {
public void completelyUnrelatedMethod() {}
public String apply(Integer i) { return null; }
}
This will return void here.
More generally there is no need for that runtime check - the generics take care of it:
Function<Integer, Integer> ohDearThisDoesNotReturnAString = a -> a;
isReturnTypeString(ohDearThisDoesNotReturnAString);
The above doesn't even compile.
To do a deep dive on your actual code, which utterly does not work:
Generics are erased, which mostly means that generics are usually a figment of the compiler's imagination. At runtime the information is simply gone. This isn't always true, but it usually is or can always be, so what you want (a runtime check) is impossible to guarantee.
In addition, you've messed up the check. isInstance does what instanceof does: It requires a type and some object. What you have is 2 instances of Class<?>; the right method for this is isAssignableFrom, not isInstance. As you have discovered, it doesn't work and cannot work - that's that erasure thing.
I've got a problem with my Java code. I want to make my method universal with using of generics types. It's easier to explain it with code:
public interface Destroyable {
void destroy();
default void destroyArray(byte[] array) {
Arrays.fill(array, (byte)0);
}
default void destroyArray(char[] array) {
Arrays.fill(array, (char)0);
}
}
The point is, that I want my default method destroyArray to work with any type, like this:
public interface Destroyable {
void destroy();
default <E> void destroyArray(Class<E>[] array) {
Arrays.fill(array, (E)0);
}
}
It gives me error:
Inconvertible types; cannot cast 'int' to 'E'
Is there any simple solution to achieve this?
Default value of objects
The problem with your code:
default <E> void destroyArray(E[] array) {
Arrays.fill(array, (E) 0);
}
is that a general E type is of course not necessarily an int (or something that can be autoboxed like Integer). But you want to actually write some default value. Therefore you would need to create valid instances of E. Which, in general, is hard because you don't know anything about the type, including its constructors.
However, there is one valid value for all Objects, namely null. It indicates that there simply is no instance at the moment.
So the following would work for arbitrary types E:
default <E> void destroyArray(E[] array) {
Arrays.fill(array, null);
}
Primitives
However, with that you are still not able to fill primitive-type arrays like int[] since E can only be used for Objects, not primitives. You would need to hard-code additional methods for each primitive:
default void destroyArray(int[] array) {
Arrays.fill(array, 0);
}
default void destroyArray(double[] array) {
Arrays.fill(array, 0.0);
}
// ...
Note on Class<E>
Your original code had Class<E>[] instead of E[]. Note that Class<E> means something completely different than E[].
Class<E> is a Class object, a wrapper that provides Reflection-API access to analyze contents of the class. Like getting names of methods and stuff like that. Whereas E is the class itself.
So Person would be a Person class and Class<Person> is like a class which knows stuff about the Person class, like its method names.
See the documentation of Class for more details.
default <E> void destroyArray(E[] array) {
Arrays.fill(array, null);
}
The above might be what you intended. However, this wouldn't work with primitive types. Because primitive types are not allowed to be passed as generic type parameters, you will still need a destroyByteArray, destroyIntArray etc.
Also, destroyArray doesn't seem to belong in Destroyable. Shouldn't it just be in a helper class full of static methods? If I were you I would move it to there. It does not even call the destroy method, so it has no reason to be in Destroyable.
Your original approach with many overloaded methods is fine.
For primitive types, the generics would work for their arrays as:
default <A> void destroyArray(A array) {
Class<?> arrayType = array.getClass();
if (!arrayType.isArray()) {
return;
}
Class<?> type = arrayType.getComponentType();
if (type == int.class) {
Arrays.fill((int[])array, 0);
} else if (type == char.class) {
Arrays.fill((char[])array, '\0');
}
//...
}
As you can see: this is hardly more compact, slower and less type safe, and secure forgotten primitive types.
I'm trying to get familiar with generics in java. I'm still unsure how create a simple class to take two types (String, Integer). Below is a trivial attempt at working with generics in my contexts.
public class Container <T>
{
public T aString()
{
//Do i know I have a string?
}
public T anInt()
{
//How do I know I have an integer?
}
public Container<T>()
{
//What would the constructor look like?
}
}
I'm referencing this page oracle generics but I'm still not sure what I'm doing here. Do you first figure out what type your "T" in the class?
Is generic programming genuinely used for interfaces and abstract classes?
Well that Container class can actually hold a String, Integer or any type, you just have to use it correctly. Something like this:
public class Container<T> {
private T element;
public T getElement() {
return element;
}
public void setElement(T element) {
this.element = element;
}
public Container(T someElement) {
this.element = someElement;
}
}
And you can use it like this:
Container<Integer> myIntContainer = new Container<Integer>();
myIntContainer.setElement(234);
or...
Container<String> myStringContainer = new Container<String>();
myStringContainer.setElement("TEST");
If the class does significantly different things for String and Integer, maybe it should be two classes, each specialized for one of those types.
I see generics as being useful for situations in which references of different types can be handled the same way. ArrayList<String> and ArrayList<Integer> don't need any code that is specific to String or Integer.
Class type = Integer.class
Integer i = verifyType("100",type);
for integer, similar with string...
reference Java Generics with Class <T>
If you want to use String and Integer you'll probably have to use Object as the type. This removes most of the benefit of Generics frankly and you should probably check that you actually have a sound model and reason for inter-weaving strings and integers.
But yes, it's useful for interfaces, custom classes and abstracts. It means you can guarantee the object is of the right type and removes the need to implement them each time for each type of thing.
I have the following class
public class DBField<T>
{
protected String fieldName;
protected FieldConverter c;
protected T value;
protected DataObject dataObject;
public T getValue()
{
return value;
}
public void setValue(T value)
{
this.value = value;
}
public DBField(DataObject dataObject, String fieldName, FieldConverter c)
{
this.fieldName = fieldName;
this.c = c;
this.dataObject = dataObject;
}
}
T is supposed to be Boolean, Float, String etc.
protected void ValuesToFields(List<Object> values, List<DBField<?>> fields) throws Exception
{
if (values.size() != fields.size())
throw new Exception("Length does not match.");
for (int i = 0; i < values.size(); i++)
{
Class valueClass = values.get(i).getClass();
Class fieldClass = fields.get(i).getValue().getClass();
if (valueClass.equals(fieldClass))
{
fields.get(i).setValue(values.get(i));
}
else
throw new Exception("type mismatch");
}
}
Object is also supposed to contain Boolean, Float, String etc.
The problem with this code is
fields.get(i).setValue(values.get(i));
The syntax checker tells me I need to cast values.get(i) (to ? i suspect). How do I do this? I already tried valueClass.cast(values.get(i)) but no luck.
In order for your code to be safe, for each i, the i'th element of values must be an instance of the type parameter of the DBField that is the i'th element of fields. Your code does not guarantee that this holds, and in fact there is no way to declare them in Java to ensure that this relationship between corresponding elements is true. And due to type erasure, you can't even check at runtime that the elements are right, because given a field, you don't know its type parameter. So there must be some unchecked casts, and we must take on faith that the arguments are correct.
The simplest thing to do would be to cast each field to DBField<Object>:
((DBField<Object>)fields.get(i)).setValue(values.get(i));
This is kind of saying "trust us, we know that this field can take any Object", and thus it can take a value of any type. It is kind of lying, because we know there are supposed to be fields whose type parameter is not Object, but since we must make some kind of unchecked cast anyway, this "unsafe cast" is no worse than the other solutions.
Alternately, if you don't want to do this arguably dubious cast, a more "legitimate" way would be to write a private helper method -- a "wrapper helper" -- which explicitly names the type parameter of the field, allowing us to simply cast to the value to this type:
private <T> static void ValueToField(Object value, DBField<T> field) {
field.setValue((T)value);
}
//...
ValueToField(values.get(i), fields.get(i));
Note that the cast here is also an unchecked cast. The disadvantage of this method is that it requires the overhead of writing an extra method.
P.S. Your checks with valueClass and fieldClass are not very good. First of all, if the value of a field is currently null, it will cause a null pointer exception. Also, the value of a DBField<T> is any instance of T, whose actual class may be a subclass of T; so if you use this to check, it might lead to bad results. It's probably best if DBField contains the class object of the class of T, so it can be used to check. Also, you shouldn't compare equality with the value's actual class, since a subclass of T would also work, so you should check fieldClass.isInstance(values.get(i)) instead.
if(values.get(i) instanceof valueClass) ?
You have a List<Object>.
You should have a List<DBField<Object>> to match it, or change your first list to List<?>
Suppose I've got a method that accepts an array and processes each element in it using Java's built in for-each loop, like this:
public static void myFun(SomeClass[] arr) {
for (SomeClass sc : arr) {
// Stuff is processed here
}
}
This works just fine, but now I want to be able to pass the same method a List<SomeClass> instead. Am I destined to use Collection.toArray(T []), or is there a parameter I can use for myFun() that accepts any type that can be used in a for-each construct?
To clarify: I want a method signature that will accept any iterable object, be it a primitive array or a Collection. I can very easily write two methods, with one wrapping the other, but I'm just curious if there's a better way.
I would suggest using Iterable, Collection or List as the parameter type.
IMO, collections should be preferred to reference arrays. If you happen to have an array Arrays.asList does the conversion nicely. Arrays.asList allows gets and sets back through to the array, but obviously not "structural" modifications which would change the array length.
myFun(Arrays.asList(arr));
You may have to use wildcards in extreme/general cases.
public static void myFun(Iterable<? extends SomeClass> somethings) {
for (SomeClass something : somethings) {
// something is processed here
}
}
It is noteworthy that Collections.toArray and Arrays.asList work slightly differently. asList keeps the original array to back the collection, so changes to the collection will be reflected in the array. Collections.toArray makes a (shallow) copy of the collection data. Making a copy is often what you would want anyway if you are returning an array. Asymmetrically, if you are passing as an argument you generally do not copy (unless storing as a field).
Use Iterable. That's what it's for.
As you said, Iterable won't handle arrays.
You don't want to use multiple methods wrapping each other. That rules out Arrays.asList and Collection.toArray.
So the answer to your question is no, there isn't a way. But if you can use Lists, why would you ever use arrays?
I would still go with Iterable here. I like it better than Collection because in the past I've had classes that implemented Iterable but were not collections; this made it easy for them to lazily retrieve values as needed, and I could use the foreach loop on them.
you cannot, java Arrays doesn't implements Iterable:
public static int sum(Iterable<Integer> elements) {
int s = 0;
for (int i : elements) {
s += i;
}
return s;
}
public static void main(String[] args) {
L1: System.out.println(sum(1,2,3));
L2: System.out.println(sum(Arrays.asList(1,2,3)));
L3: System.out.println(sum(new int[] { 1,2,3 }));
}
this results in two compile-time errors in (L1 and L3); so you must design your
method to accept an Iterable (Collections) and/or an Array, at least one method must perform some conversion (to/from array)
WORKAROUND:
you may be try with an adapter:
public class ArrayIterator<T> implements Iterator<T> {
private final T[] array;
private int i;
public ArrayIterator(T[] anArray) {
array = anArray;
i = 0;
}
public boolean hasNext() {
return i < array.length;
}
public T next() {
return array[i++];
}
public void remove() {
throw new UnsupportedOperationException();
}
}
private static int sum(final Integer ... elements) {
return sum(new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new ArrayIterator<Integer>(elements);
}
});
}
you should pay attention only when dealing with primitive arrays; when you use only
reference object (your case) ArrayIterator + anonymous class are cool
hope it helps
Short answer: no, there's no single method signature that type-safely accepts both an Iterable and an array. Obviously you could just accept Object, but that would be a hack as well.
Long-ish answer: Since the enhanced for-loop is effectively defined twice (once for arrays and once for Iterable), you'll need to provide two overloaded methods as well:
public static void myFun(SomeClass[] array) {
for (SomeClass sc : array) {
doTheProcessing(sc);
}
}
public static void myFun(Iterable<? extends SomeClass> iterable) {
for (SomeClass sc : iterable) {
doTheProcessing(sc);
}
}
Although the source of the two methods looks exactly the same, you'll need to define it twice (unless of course you wrap the Array in your own Iterable as #dfa outlined).
There's a little know feature of Java Generics in Java 1.5+ where you can use <? extends Subtype> in your method calls and constructors. You could use <? extends Object>, and then anything that deals with those would have access only to methods on Object. What you might really want is something more like this:
List<? extends MyCrustaceans> seaLife = new ArrayList<? extends MyCrustaceans>();
MyShrimp s = new MyShrimp("bubba");
seaLife.add(s);
DoStuff(seaLife);
...
public static void DoStuff(List<? extends MyCrustaceans> seaLife)
{
for (MyCrustaceans c : seaLife) {
System.out.println(c);
}
}
So if you have a base class (like MyCrustaceans), you can use any methods of that base class in DoStuff (or of the Object class, if your parameter is <? extends Object>). There's a similar feature of <? super MyType>, where it accepts a parameter that is a supertype of the given type, instead of a subtype. There's some restrictions on what you can use "extends" and "super" for in this fashion. Here's a good place to find more info.
public static void myFun(Collection<MyClass> collection) {
for (MyClass mc : collection) {
// Stuff is processed here
}
}