Not implementing generic method in generics class - java

Imagine code like this:
public class Value<T> {
private T value;
public Value(T value) {
this.value = value;
}
public int size() {
return sizeOf(value);
}
private int sizeOf(int value) {
return Integer.BYTES;
}
private int sizeOf(String value) {
return value.length() * Character.BYTES;
}
}
and somewhere (e.g. main)
Value<String> value = new Value<String>("hello");
The problem is that the code will not compile, because I haven't implemented sizeOf(T value), but I don't understand why would the compiler complain --- it sees that I only use it with <T=String>. And if I implement the generic sizeOf(T value) , it will take precedence (as explained here Java generics (template) specialization possible (overriding template types with specific types) )
Note that the solution proposed there (having a StringValue subclass) doesn't really apply in my case, because I already have some subclasses which I am using, so I would need to create lots of extra classes (times by types)
But I would prefer something much more straight-forward, such as this

You have to declare sizeOf(T value) because T can be of any type, so to maintain type controll, compiler needs "universal" version of sizeOf method that will hindle any possible type.
Think of what would happend if you would use something like new Value<List<Object>>(new ArrayList<Object>).size() - what would happen then as you have no method specialized in returning size of collection?
The thing is, that during runtime, generic type is erased, so JVM have no idea whitch of the overloaded methods should be used. Check more info about type erasure here. https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

There's no getting around having to provide an implementation for size(). Your code is half way to the double dispatch pattern, but going all the way isn't possible, because you've got no way of requiring types like String to implement size().
One approach is to require the size code on construction:
public class Value<T> {
private T value;
private Function<T, Integer> size;
public Value(T value, Function<T, Integer> size) {
this.value = value;
this.size;
}
public int size() {
return size.apply(value);
}
}
To create a Value<String> for example:
Value<String> val = new Value("foo", s -> s.length() * Character.BYTES)
or if that doesn't work, use instanceof for supported types:
public int size() {
if (value instanceof Integer)
return Integer.BYTES;
if (value instanceof String)
return ((String)value).length() * Character.BYTES;
// other supported types
throw new IllegalStateException();
}

Related

Parameterize a class with one of a fixed set of types

Say I have a generic class Foo which can hold an object of type T. Furthermore, let's say I only want to be able to instantiate the class with objects that are one of two types. Finally, let's say that the lowest common upper bound of these two types is a type that has many more subclasses than those two types that I want to allow, so I can't simply specify an upper bound for the type parameter (as in class Foo<T extends Something>), because then I would allow to instantiate the class with other types than the two I expect.
For illustration, let's say I want Foo to hold only either a String or an Integer. The lowest common upper bound is Object, so specifying an upper bound won't do the trick.
Certainly, I could do something along the lines of
class Foo<T> {
private T obj;
public Foo(T obj) throws IllegalArgumentException {
if (!(obj instanceof String || obj instanceof Integer)) {
throw new IllegalArgumentException("...");
}
this.obj = obj;
}
}
However, in this case, I can still call the constructor with any object; if I try to instantiate it with something that is neither a String nor an Integer, I will get an exception at runtime.
I would like to do better. I would like the compiler to infer statically (i.e., at compile time) that I can only instantiate this class with objects that are either String or Integer.
I was thinking something along those lines might do the trick:
class Foo<T> {
private T obj;
public Foo(String s) {
this((T) s);
}
public Foo(Integer i) {
this((T) i);
}
private Foo(T obj) {
this.obj = obj;
}
}
This works, but it looks really, really odd. The compiler warns (understandably) about unchecked casts. Of course I could suppress those warnings, but I feel this is not the way to go. In addition, it looks like the compiler can't actually infer the type T. I was surprised to find that, with the latter definition of class Foo, I could do this, for instance:
Foo<Character> foo = new Foo<>("hello");
Of course, the type parameter should be String here, not Character. But the compiler lets me get away with the above assignment.
Is there a way to achieve what I want, and if yes, how?
Side question: why does the compiler let me get away with the assignment to an object of type Foo<Character> above without even so much as a warning (when using the latter definition of class Foo)? :)
Try using static factory method to prevent compiler warning.
class Foo<T> {
private T obj;
public static Foo<String> of(String s) {
return new Foo<>(s);
}
public static Foo<Integer> of(Integer i) {
return new Foo<>(i);
}
private Foo(T obj) {
this.obj = obj;
}
}
Now you create instance using:
Foo<String> foos = Foo.of("hello");
Foo<Integer> fooi = Foo.of(42);
Foo<Character> fooc = Foo.of('a'); // Compile error
However the following are still valid since you can declare a Foo of any type T, but not instantiate it:
Foo<Character> fooc2;
Foo<Character> fooc3 = null;
Foo<Object> fooob1;
Foo<Object> fooob2 = null;
one word: interface. You want your Z to wrap either A or B. Create an interface implementing the smallest common denominator of A and B. Make your A and B implement that interface. There's no other sound way to do that, AFAIK. What you already did with your constructors etc. is the only other possibility, but it comes with the caveats you already noticed (having to use either unchecked casts, or static factory wrappers or other code smells).
note: If you can't directly modify A and/or B, create wrapper classes WA and WBfor them beforehand.
example:
interface Wrapper {
/* either a marker interface, or a real one - define common methods here */
}
class WInt implements Wrapper {
private int value;
public WInt( int value ) { this.value = value; }
}
class WString implements Wrapper {
private String value;
public WString( String value ) { this.value = value; }
}
class Foo<T> {
private Wrapper w;
public Foo(Wrapper w) { this.w = w; }
}
because you call your private Foo(T obj) due to diamond type inference. As such, it's equal to calling Foo<Character> foo = new Foo<Character>("hello");
Long story short: You are trying to create a union of two classes in java generics which is not possible but there are some workarounds.
See this post
Well the compiler uses the Character class in T parameter. Then the String constructor is used where String is casted to T (Character in this case).
Trying to use the private field obj as a Character will most likely result in an error as the saved value is an instance of the final class String.
Generics is not suitable here.
Generics are used when any class can be used as the type. If you only allow Integer and String, you should not use generics. Create two classes FooInteger and FooString instead.
The implementations should be pretty different anyway. Since Integers and Strings are very different things and you would probably handle them differently. "But I am handling them the same way!" you said. Well then what's wrong with Foo<Double> or Foo<Bar>. If you can handle Integer and String with the same implementation, you probably can handle Bar and Double and anything else the same way as well.
Regarding your second question, the compiler will see that you want to create a Foo<Character>, so it tries to find a suitable overload. And it finds the Foo(T) overload to call, so the statement is perfectly fine as far as the compiler is concerned.

Can I have function types in Java's Enum like Swift?

Is it possible to write an equivalent code in Java for the following swift code? In fact, I want to know if it's possible to have a case of functions inside Java's enum (X, Y in MyEnum)
enum MyEnum{
case X((Int) -> String)
case Y((Double) -> Int)
}
No, you can't; at least, not if you want the differing types to be available when you use the enum. All enum values have to have the same type.
When you want "enum" values to have heterogenous types, you could use a class with static final fields:
final class MyHeterogeneousEnum {
private MyHeterogeneousEnum() {} // Not instantiable.
static final Function<Integer, String> X = ...;
static final Function<Double, Integer> Y = ...;
}
which allows you to use the values with their full type information:
String s = MyHeterogeneousEnum.X.apply(123);
Integer i = MyHeterogeneousEnum.Y.apply(999.0);
Of course, you don't have useful methods like name(), or values() to iterate over the constants in this class, nor is it inherently serializable. You can make implement these yourself - but for values() you have to use wildcards in the return type, in order that all values can be returned:
static Iterable<Function<?, ?>> values() {
return Collections.unmodifiableList(Arrays.asList(X, Y));
}
However, note that a Function with a wildcard input type parameter is pretty much useless: you can't actually pass anything into it (other than null); so the values() method has limited utility.
It is possible (technically), but it might not be that useful, as creating a simple class, that consumes a Function instance.
As you might already know, in Java, the enums represent one or more constants of the same type, which could have their own properties - this include java.util.Function instances. However, these Function instances cannot be passed dynamically at Runtime, but should be rather set at compile time, so that the constant is created.
Of course, you could make each enum constant have a different typed Function, by just creating the enum's constructor Generic:
enum MyEnum {
X((String x) -> "Hello"), Y((Double d) -> 1);
Function<?, ?> function;
MyEnum(Function<?, ?> function) {
this.function = function;
}
}
This, however, is not quite useful (although it compiles just fine). The Function in X doesn't use it's String parameter and returns a fixed value. So does the one in Y.
I'd rather introduce two separate instances of the same class:
class Instance<T, U> {
private Function<T, U> function;
public Instance(Function<T, U> function) {
this.function = function;
}
}
This will allow you to dynamically pass a Function instance, instead of setting it at compile-time.
Yes for sure you can, in java enums can be more that just constants... every one of it values can be an anonymous class (take a look to TimeUnit.class for example)
now, you can do somthing like:
interface IFunction {
double getY(double x);
}
enum Function implements IFunction {
LINE {
#Override
public double getY(double x) {
return x;
}
},
SINE {
#Override
public double getY(double x) {
return Math.sin(x);
}
}
}
and then the implementation
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Function.LINE.getY(i));
System.out.println(Function.SINE.getY(i));
}
}

How do I bound a generic type to 2 types that are almost completely separated in hierarchy

How do I do this? Because you can only extend one class so it can only have one upper bound.
In my case I need the generic type to be bounded in String and int. If I use an Integer wrapper instead of int and rely on auto-boxing, I can make it but the problem is other classes can be passed as a type parameter as well.
What's the best way to do this?
You could use the non generic variants of collections (e.g List), or
more cleanly explicitly List<Object> to show code's intention.
Wrap that in a MyList class, and create add(), get() methods for each type you want to support:
add(Integer elem);
add(String elem);
But Object get() cannot be typed, such that it makes sense.
So finally you also can use Object with List, and omit the wrapper.
I don't think you can do it. String also is a final class and all that stuff. As #NimChimpsky said, you are probably better using Object itself. Another solution is a wrapper for both classes, but you will still have a resulting object which you will probably need to cast around and rely on instanceof:
class StringInt {
private String string;
private Integer integer;
public StringInt(String s) { this.string = s; }
public StringInt(Integer i) { this.integer = i; }
public Object getValue() { return string != null ? string : integer; }
}
Or with an ugly verification, which, obviously, will only apply at runtime...
class StringIntGen<T> {
private T t;
public StringIntGen(T t) {
if (!(t instanceof String) && !(t instanceof Integer))
throw new IllegalArgumentException(
"StringIntGen can only be Integer or String");
this.t = t;
}
public T getValue() { return t; }
}

Dynamic casting in Java

Before I get chided for not doing my homework, I've been unable to find any clues on the multitude of questions on Java generics and dynamic casting.
The type Scalar is defined as follows:
public class Scalar <T extends Number> {
public final String name;
T value;
...
public T getValue() {
return value;
}
public void setValue(T val) {
this.value = val;
}
}
I would like to have a method that looks like this:
public void evilSetter(V val) {
this.value = (T) val;
}
Sure, this is generally discouraged. The reason I want such a method is because I have a collection of Scalars whose values I'd like to change later. However, once they go in the collection, their generic type parameters are no longer accessible. So even if I want make an assignment that's perfectly valid at runtime, there's no way of knowing that it'll be valid at compile time, with or without generics.
Map<String, Scalar<? extends Number>> scalars = ...;
Scalar<? extends Number> scalar = scalars.get("someId");
// None of this can work
scalar.value = ...
scalar.setValue(...)
So how do I implement a checked cast and set method?
public <V extends Number> void castAndSet(V val) {
// One possibility
if (this.value.getClass().isAssignableFrom(val.getClass()) {
// Some cast code here
}
// Another
if (this.value.getClass().isInstanceOf(val) {
// Some cast code here
}
// What should the cast line be?
// It can't be:
this.value = this.value.getClass().cast(val);
// Because this.value.getClass() is of type Class<?>, not Class<T>
}
So I'm left with using
this.value = (T) val;
and catching a ClassCastException?
You have:
this.value.getClass().isAssignableFrom(val.getClass())
This is probably going to be a problem unless you can be certain value will never be null.
You also have:
this.value = (T) val;
This will only cast to Number and not to T because under the hood T is just a Number due to type-erasure. Therefore if value is a Double and val is an Integer, no exception will be thrown.
If you actually want to perform a checked cast, you must have the correct Class<T> object. This means you should be passing Class<T> in the constructor of your object. (Unless you can be sure value is never null, in which case you can go with your first idea.) Once you have that object (stored in a field), you can perform the checked cast:
T value = valueClass.cast(val);

Java Generics and Infinity (Comparable)

With the type Integer you can do this:
int lowest = Integer.MIN_VALUE;
What can I do if I use generics?
K lowest = <...>;
I need this in order to implement something similar to a PriorityQueue.
I have access to a node I want to remove from the queue, but it is not the min.
1. I need to make it the min by decreasing the key of that node,
2. And then remove the min.
I am stuck on the first step. The only thing I can do is set the key of the node to the current min. Not sure it is enough.
There is no generic form of MIN_VALUE or MAX_VALUE for all Comparable types.
Think about a Time class that implements comparable. There is no MAX_VALUE for Time even though it is Comparable.
I am trying to imagine what scenario would require such behavior. This is the best I can come up with...
WARNING: This code is dangerous. Please be merciful to me for posting such an abomination. It is only a proof of concept.
public class Lowest<K> implements Comparable<K> {
public int compareTo(K other) {
return -1;
}
}
And then...
public class Test {
public <K extends Comparable<K>> K findMaximum(List<K> values) throws Exception {
K lowest = (K) new Lowest<K>(); /// XXX DANGER! Losing compile-time safety!!!
K maximum = lowest;
for (K value : values) {
if (maximum.compareTo(value) < 0) {
maximum = value;
}
}
if (maximum == lowest) {
throw new Exception("Could not find a maximum value");
} else {
return maximum;
}
}
}
This doesn't make any sense...
Given that you don't know what K is at that point, (i.e. You're implementing it generically... duh!) you can't specify a min/max bound for it.
in a case where K could be a int, long, string OR object, you couldn't sensibly guess to use
Integer.MIN_VALUE, "" OR NULL.
I guess what you're looking for is a K.MIN_VALUE_OF_EVENTUAL_TYPE but that doesn't exist.
You can make a wrapper class that "adds" a minimum and maximum value to all types. It just has two static instances that represent minimum and maximum, and then other instances wrap some other value of some type. When we do a comparison, we check if one of the things is the minimum or maximum, and return the proper result; and otherwise we just do the same comparison as the underlying type. Something like this:
class Extended<T extends Comparable<? super T>> implements Comparable<Extended<T>> {
private Extended() { }
private static Extended min = new Extended();
private static Extended max = new Extended();
#SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Extended<T> getMin() {
return (Extended<T>)min;
}
#SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Extended<T> getMax() {
return (Extended<T>)max;
}
public T value;
public Extended(T x) { value = x; }
public int compareTo(Extended<T> other) {
if (this == other) return 0;
else if (this == min || other == max) return -1;
else if (this == max || other == min) return 1;
else return this.value.compareTo(other.value);
}
}
Consider not making K a generic, but using an interface that wraps the primitive wrapper (a double wrapper!).
import java.util.HashMap;
public class NodeWrapper<K extends Comparable<K>> implements Comparable<NodeWrapper<K>> {
private static HashMap<Class, NodeWrapper> minVals = new HashMap<Class, NodeWrapper>();
private K value;
private NodeWrapper() {
super();
}
public NodeWrapper(K value, Class<K> clazz) {
super();
this.value = value;
if (minVals.get(clazz)==null) {
minVals.put(clazz, new NodeWrapper<K>());
}
}
public K getValue() {
return value;
}
public static NodeWrapper getMinValue(Class clazz){
return minVals.get(clazz);
}
public void setValue(K value) {
this.value = value;
}
#Override
public int compareTo(NodeWrapper<K> o) {
NodeWrapper min = minVals.get(this.getClass());
if (this==min && o==min) {
return 0;
} else if (this==min){
return -1;
} else if (o==min){
return 1;
} else {
return this.value.compareTo(o.value);
}
}
}
Briefly, the idea is that whenever a new class is instantiated, a minimum value is created and put into a static hashmap that stores the minimum values for each class. (In fact, these values are NOTHING at all, just a sentinel object, but since we will use object equality to determine if something is the min value, this is no problem at all.) All that's necessary is that the wrapped object be comparable to other instances of itself in general.
One drawback is that when you call getMinValue you will have compiler warnings, since the return type will have no generic information. There may be a more elegant way around this, but I can't think of it right now.
This general idea might be rather nice overall. However, I should really stress: this will absolutely break if you try it with any polymorphism or any mixing of mutually comparable classes. Longs and Integers in the same tree will completely destroy you.
er... what's the problem again?
PriorityQueue, like all Collections, allows you to use an instance of an object to remove it from the collection.
Uh doesn't this depend on what type K is?
The point of Generics is that K can be any type (or any subclass of a certain type); in order to be able to call methods on K or access properties of it, you need to restrict it's type bounds with wildcards.
just because an object is a comparable does not mean it has to have a minimum value. The reason int has a min value of -(2^(31)) is because you need 1 bit for a sign, so 2^31 is the largest (or smallest) possible integer that can be stored. For things like string, it does not make any sense since there is no largest/smallest possible string, it is memory bound.
You might have to create an interface "IInfinity", and have K extends IInfinity, and IInfinity to have a method "getInfinityValue()", and then wrap/extend Integer, Double, BigDecimal, etc in a class that implements IInfinity ... and ugh!
Basically you want any type K to implement some static functions say lowest and highest which obey the standard mathematical properties.
I assume that for this sense of lowest (or highest) to be usable you would want any Comparable object to have these methods. (or static fields). If you are only interested in your own custom objects, the way to do this would be to have everything inherit from an abstract data type which declared static fields for MINVALUE and MAX_VALUE and then your type varaibles would be . If you need this functionality for other classes you will need to cre4ate some sort of external hashmap which tracks these properties for different classes (but that would get pretty ugly)

Categories