Function with generic list parameter? (Overloading function) - java

Objective: What I need is to create a function or functions to handle different types of List parameter, and I will be iterating through the list in the function.
Attempts:
1- Multiple functions with different type of List
public static int update(List<MyClass> myClasses){};
public static int update(List<Project> rojects){};
public static int update(List<Time> times){};
But that deemed to be in-compilable as due to multiple functions with same parameter type List.
2- Generic type of list, and using (instanceof) However, I failed to completely do this as I am not sure how, and as much as I read, this seems to be an unfavorable way of such action.
My question: what is the Java way of implementing such requirement? I need a clean code, I don't care if it is complicated, I care mostly about accuracy and proper coding.
PS: if the instanceof the correct way, then would you please provide me with a small example on how to iterate the list with the different types.
Thanks in advance :)
EDIT: The different objects have no relation with each other, as in, they do not extend each other nor do they extend a super class. The blocks of each function are generating an SQLite statements which would be different for each type.
Respond to 'harsh's answer:
So I ended up using a combination of your suggestions, and that is to implement a base class with a function of getClassType() which returns a string of the class name, then I would check the returned value in the update(List<T> list) function.
public static <T extends Item> int update(List<T> list){
...
// Loop through the list and call the update function
for (T item: list){
if (item.getClassType() == MyClass.CLASS_TYPE)
update((MyClass) item);
}
...
}
public interface Item {
/**
* #return Return the class type, which is the name of the class
*/
public String getClassType();
}
public class ClassProject implements Item{
public static final String CLASS_TYPE = "ClassProject";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
public class ClassTime implements Item{
public static final String CLASS_TYPE = "ClassTime";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
public class MyClass implements Item{
public static final String CLASS_TYPE = "MyClass";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
Reason for doing this whole interface is because I don't like istanceof and not sure about it's performance and cost, so I attempted to make one of my own. Now is this a terrible way of doing this?

Can you do something like this:
public class Update<T>
{
public static int update(List<T> objects){};
}
OR
public static <T> int update(List<T> objects){};
whichever is more appropriate in your case.
So if you go by second approach and due to type erasure at runtime, you are left with instanceof checking:
public static <T> int update(List<T> objects){
for(T object : objects)
{
if(object.getClass().isInstance(Pair.class))
{
//do something
}else if(object.getClass().isInstance(Time.class))
{
}
}
return 0;
}
But that's doesn't look a good design, you can improve above by using a factory method:
static Handler getHandler(Class<?> handlerClass)
{
if(handlerClass.isInstance(Project.class))
{
//return ProjectHandler
}else if(handlerClass.isInstance(Time.class))
{
//return TimeHandler
}
//return errorHandler
}
interface Handler {
int handle();
}
public static <T> int update(List<T> objects){
for(T object : objects)
{
getHandler(object.getClass()).handle();
}
return 0;
}
Now a nicer approach IMO would be to designate your classes under update via marker interface and then cleanly handle update in each of the classes:
interface Updateable {
int update();
}
public static <T extends Updateable> int update2(List<T> objects){
for(T object : objects)
{
object.update();
}
return 0;
}

Based on your answer to my comment you are left with two approaches. The first would be to try to come up with an interface that all the possible types that would be passed to this method implement. If your interface was called Foo you could define the method as something like:
public int update(List<Foo> list)
Then your code inside would be based on the methods available in Foo.
If you can't do this then you will need separate methods per possible type. You can't do instanceof at runtime due to Type Erasure. The underlying type if the list is erased in the compiled code and therefor will not be available for instanceof logic.
EDIT:
To clear up a little confusion on my above answer. You can do instanceof on a per element basis when iterating the list, something like this:
for(Object item:list){
if (item instanceof A){
//do A based logic
}
else if (item instanceof B){
//do B based logic
}
}
You can't however check the list type at runtime like so:
if (list instanceof List<A>)
Your best bet really would be to try and generalize the types supported via an interface as suggested in my first solution. Doing the instanceof approach will lead to code that will constantly need to be modified as you add more supported types.

Expanding harsh's answer, can't you do:
public class Update
{
public static <T> int update(List<T> objects, Class<T> clazz){};
}
And then, in your implementation, vary behavior according to the passed Class instance?

Related

Number.valueOf() implementation for Java generics

I have been using a Collection of number values and have implemented some related functionality (mapping x->y values, etc). So far I have made use of generics to allow any subclass of Number in the Collection.
In this particular class I keep running into the problem that there is no easy way to cast to the generic. The usual methods like Double.valueOf() cannot be invoked because Number does not provide such a method.
Is there a good way around this?
I have found this post and thought that would solve it, but I cannot pass the Class.class parameter to it.
public class myList<T extends Number> extends Collection<T> {
#Override
public boolean add(T value){
// this is no problem
}
// What I want to do:
public boolean add(double value){
return this.add(T.valueOf(value));
}
// Using the example I found:
public void add(double value){
return this.add( (T) Ideone.parse(value, T.class) ); // no such option
}
}
Thanks in advance.
There's no way for the myList class to be able to convert double to T, because T is unknown.
One way you can solve this is to let the caller provide a function that converts from double to T. Here's an example:
public class myList<T extends Number> implements Collection<T> {
private DoubleFunction<T> fromDoubleFunction;
public myList(DoubleFunction<T> function) {
this.fromDoubleFunction = function;
}
public boolean add(double value) {
return this.add(this.fromDoubleFunction.apply(value));
}
//rest of code
}
That can then be used in this way:
myList<Integer> intList = new myList(d -> Double.valueOf(d).intValue());
Provide a DoubleFunction<T> to your class as a constructor parameter.
public class myList<T extends Number> extends Collection<T> {
private final DoubleFunction<T> theDoubleFn;
public myList(DoubleFunction<T> theDoubleFn) {
this.theDoubleFn = theDoubleFn;
}
// ...
Then invoke:
return this.add(theDoubleFn.apply(value));
in the method.

Can I define the Negatable interface in Java?

Asking this question to clarify my understanding of type classes and higher kinded types, I'm not looking for workarounds in Java.
In Haskell, I could write something like
class Negatable t where
negate :: t -> t
normalize :: (Negatable t) => t -> t
normalize x = negate (negate x)
Then assuming Bool has an instance of Negatable,
v :: Bool
v = normalize True
And everything works fine.
In Java, it does not seem possible to declare a proper Negatable interface. We could write:
interface Negatable {
Negatable negate();
}
Negatable normalize(Negatable a) {
a.negate().negate();
}
But then, unlike in Haskell, the following would not compile without a cast (assume MyBoolean implements Negatable):
MyBoolean val = normalize(new MyBoolean()); // does not compile; val is a Negatable, not a MyBoolean
Is there a way to refer to the implementing type in a Java interface, or is this a fundamental limitation of the Java type system? If it is a limitation, is it related to higher-kinded type support? I think not: it looks like this is another sort of limitation. If so, does it have a name?
Thanks, and please let me know if the question is unclear!
Actually, yes. Not directly, but you can do it. Simply include a generic parameter and then derive from the generic type.
public interface Negatable<T> {
T negate();
}
public static <T extends Negatable<T>> T normalize(T a) {
return a.negate().negate();
}
You would implement this interface like so
public static class MyBoolean implements Negatable<MyBoolean> {
public boolean a;
public MyBoolean(boolean a) {
this.a = a;
}
#Override
public MyBoolean negate() {
return new MyBoolean(!this.a);
}
}
In fact, the Java standard library uses this exact trick to implement Comparable.
public interface Comparable<T> {
int compareTo(T o);
}
In general, no.
You can use tricks (as suggested in the other answers) that will make this work, but they do not provide all of the same guarantees that the Haskell typeclass does. Specifically, in Haskell, I could define a function like this:
doublyNegate :: Negatable t => t -> t
doublyNegate v = negate (negate v)
It is now known that the argument and return value of doublyNegate are both t. But the Java equivalent:
public <T extends Negatable<T>> T doublyNegate (Negatable<T> v)
{
return v.negate().negate();
}
doesn't, because Negatable<T> could be implemented by another type:
public class X implements Negatable<SomeNegatableClass> {
public SomeNegatableClass negate () { return new SomeNegatableClass(); }
public static void main (String[] args) {
new X().negate().negate(); // results in a SomeNegatableClass, not an X
}
This isn't particularly serious for this application, but does cause trouble for other Haskell typeclasses, e.g. Equatable. There is no way of implementing a Java Equatable typeclass without using an additional object and sending an instance of that object around wherever we send values that need comparing, (e.g:
public interface Equatable<T> {
boolean equal (T a, T b);
}
public class MyClass
{
String str;
public static class MyClassEquatable implements Equatable<MyClass>
{
public boolean equal (MyClass a, MyClass b) {
return a.str.equals(b.str);
}
}
}
...
public <T> methodThatNeedsToEquateThings (T a, T b, Equatable<T> eq)
{
if (eq.equal (a, b)) { System.out.println ("they're equal!"); }
}
(In fact, this is exactly how Haskell implements type classes, but it hides the parameter passing from you so you don't need to figure out which implementation to send where)
Trying to do this with just plain Java interfaces leads to some counterintuitive results:
public interface Equatable<T extends Equatable<T>>
{
boolean equalTo (T other);
}
public MyClass implements Equatable<MyClass>
{
String str;
public boolean equalTo (MyClass other)
{
return str.equals(other.str);
}
}
public Another implements Equatable<MyClass>
{
public boolean equalTo (MyClass other)
{
return true;
}
}
....
MyClass a = ....;
Another b = ....;
if (b.equalTo(a))
assertTrue (a.equalTo(b));
....
You'd expect, due to the fact that equalTo really ought to be defined symmetrically, that if the if statement there compiles, the assertion would also compile, but it doesn't, because MyClass isn't equatable with Another even though the other way around is true. But with a Haskell Equatable type class, we know that if areEqual a b works, then areEqual b a is also valid. [1]
Another limitation of interfaces versus type classes is that a type class can provide a means of creating a value which implements the type class without having an existing value (e.g. the return operator for Monad), whereas for an interface you must already have an object of the type in order to be able to invoke its methods.
You ask whether there is a name for this limitation, but I'm not aware of one. It's simply because type classes are actually different to object-oriented interfaces, despite their similarities, because they are implemented in this fundamentally different way: an object is a subtype of its interface, thus carries around a copy of the interface's methods directly without modifying their definition, while a type class is a separate list of functions each of which is customised by substituting type variables. There is no subtype relationship between a type and a type class that has an instance for the type (a Haskell Integer isn't a subtype of Comparable, for example: there simply exists a Comparable instance that can be passed around whenever a function needs to be able to compare its parameters and those parameters happen to be Integers).
[1]: The Haskell == operator is actually implemented using a type class, Eq ... I haven't used this because operator overloading in Haskell can be confusing to people not familiar with reading Haskell code.
I interpret the question as
How can we implement ad-hoc polymorphism using typeclasses in Java?
You can do something very similar in Java, but without the type safety guarantees of Haskell - the solution presented below can throw errors at runtime.
Here is how you can do it:
Define interface that represents the typeclass
interface Negatable<T> {
T negate(T t);
}
Implement some mechanism that allows you to register instances of the typeclass for various types. Here, a static HashMap will do:
static HashMap<Class<?>, Negatable<?>> instances = new HashMap<>();
static <T> void registerInstance(Class<T> clazz, Negatable<T> inst) {
instances.put(clazz, inst);
}
#SuppressWarnings("unchecked")
static <T> Negatable<T> getInstance(Class<?> clazz) {
return (Negatable<T>)instances.get(clazz);
}
Define the normalize method that uses the above mechanism to get the appropriate instance based on the runtime class of the passed object:
public static <T> T normalize(T t) {
Negatable<T> inst = Negatable.<T>getInstance(t.getClass());
return inst.negate(inst.negate(t));
}
Register actual instances for various classes:
Negatable.registerInstance(Boolean.class, new Negatable<Boolean>() {
public Boolean negate(Boolean b) {
return !b;
}
});
Negatable.registerInstance(Integer.class, new Negatable<Integer>() {
public Integer negate(Integer i) {
return -i;
}
});
Use it!
System.out.println(normalize(false)); // Boolean `false`
System.out.println(normalize(42)); // Integer `42`
The main drawback is that, as already mentioned, the typeclass instance lookup can fail at runtime, not at compile-time (as in Haskell). Using a static hash map is suboptimal too, because it brings all the problems of a shared global variable, this could be mitigated with more sophisticated dependency injection mechanisms. Automatically generating typeclass instances from other typeclass instances, would require even more infrastructure (could be done in a library). But in principle, it implements ad-hoc polymorphism using typeclasses in Java.
Full code:
import java.util.HashMap;
class TypeclassInJava {
static interface Negatable<T> {
T negate(T t);
static HashMap<Class<?>, Negatable<?>> instances = new HashMap<>();
static <T> void registerInstance(Class<T> clazz, Negatable<T> inst) {
instances.put(clazz, inst);
}
#SuppressWarnings("unchecked")
static <T> Negatable<T> getInstance(Class<?> clazz) {
return (Negatable<T>)instances.get(clazz);
}
}
public static <T> T normalize(T t) {
Negatable<T> inst = Negatable.<T>getInstance(t.getClass());
return inst.negate(inst.negate(t));
}
static {
Negatable.registerInstance(Boolean.class, new Negatable<Boolean>() {
public Boolean negate(Boolean b) {
return !b;
}
});
Negatable.registerInstance(Integer.class, new Negatable<Integer>() {
public Integer negate(Integer i) {
return -i;
}
});
}
public static void main(String[] args) {
System.out.println(normalize(false));
System.out.println(normalize(42));
}
}
You're looking for generics, plus self typing. Self typing is the notion of generic placeholder that equates to the class of the instance.
However, self typing doesn't exist in java.
You can get close with generics, but it's clunky:
public interface Negatable<T> {
public T negate();
}
Then
public class MyBoolean implements Negatable<MyBoolean>{
#Override
public MyBoolean negate() {
//your impl
}
}
Some implications for implementers:
They must specify themselves when they implement the interface, e.g. MyBoolean implements Negatable<MyBoolean>
Extending MyBoolean would require one to override the negate method again.

create new Bounded Type Parameter

I'm looking to implement a generic search function to basically look if a mouse click is within one of several list of rectangles (of varying types, all children of G3_gRect). When nothing is found, it should return a new object of type T with a property defining it as being invalid (as opposed to other things that it could be).
This all works fine until I try to make it return the generic type T.
What can I do differently to make this work?
This breaks in the last line when trying to initialize a new object of type T. I assume because it doesn't know that it could always initialize that type.
private <T extends G3_gRect> T whatRect(MouseEvent e, List<List<T>> maps) {
while (!maps.isEmpty()) {
List<T> map = maps.remove(0);
for (T entry : map) {
if(entry.R.contains(e.getPoint())) return entry;
}
}
return new T(G2_gObj.ObjType.NONE); //return with empty object rather than null.
}
A few of the relevant parts of related classes:
public abstract class G2_gObj {
public enum ObjType {
FUNCTION, RIBBON, D_LINE, D_START, D_END, D_IN_AREA, C_IN_AREA, M_IN_AREA, D_OUT_AREA, M_OUT_AREA, NONE, C_OUT_AREA
}
public ObjType t;
public G2_gObj(ObjType t) {
this.t = t;
}
}
public class G3_gRect extends G2_gObj{
public G3_gRect(ObjType t) {
super(t);
}
}
public class G4_gFunct extends G3_gRect{
public G4_gFunct(ObjType t) {
super(t);
}
}
public class G4_gDPoint extends G3_gRect{
public G4_gFunct(ObjType t) {
super(t);
}
}
Right now my workaround is to pass in an object of type T into this method to return if nothing is found. It works, its fine, but I imagine there is a better way to actually make this work.
Thanks!
There's no way to construct an object without knowing its exact class. Barring the use of reflection, your only option would be to have the caller pass a default value, or to return null (which would avoid unnecessary object creation).
If you do want to use reflection (a questionable decision), you can have a parameter Class<T> clazz, and return
clazz.getConstructor(ObjType.class).newInstance(G2_gObj.ObjType.NONE)

Iterate over specific instances in a List

I have an ArrayList witch constains some instances of different classes ,I want to iterate over a specific type of classes(for example classes tha extend OnRender.class) in a for loop;
I have a working code but the code breaks the OO rules resulting in some warnings.
Can I make this happen or I will be always break OO by downcasting.
Looking back at what I wrote ,I see that I didnt explained it very good ,so check the code below to see what I mean
the code:
public class ListenerManager{
List<Object> listeners=new ArrayList<Object>();
int it;
Class clazz;
public <T extends Object> T begin(Class<T> clazz){
it=-1;
this.clazz=clazz;
return next();
}
public <T extends Object> T next(){
while((++it)<listeners.size()){
if (clazz.isInstance(listeners.get(it))){
return (T)listeners.get(it);
}
}
return null;
}
public void add(Object listener){
listeners.add(listener);
}
}
I use it like that:
ListenerManager lm=new ListenerManager();
lm.add(new OnRenderListener(){
........
});
for(OnRenderListener orl=lm.begin(OnRenderListener.class);orl!=null;orl=lm.next){
.......
}
the warning I get:
Class clazz; -> Class is a raw type. References to generic type Class should be parameterized
return (T)listeners.get(it); -> Type safety: Unchecked cast from Object to T
I don't want to suspend the warnings with just a Suspecnd annotation,I want to follow the OO rules.
If you want to identify particular classes or interfaces, use instanceof:
for (Object o : listeners) {
if (o instanceof X) {
X x = (X)o;
}
}
However this isn't very good at all. You really want to leverage the inheritance and polymorphism of the language. My first thought is that your list should container only Listeners or subtypes e.g.
listeners = new ArrayList<Listener>();
and then you don't require the cast. Everything you pull out from the list will be a Listener (or subtype) and typed as such:
for (Listener l : listeners) {
// listener type functionality here...
}
The Visitor pattern is an option here too. You could pass your visitor object into each listener, and each listener would decide what to do based on its type. The advantage is that as you add subtypes you have to add the appropriate methods - there's no danger of omitting a type from a sequence of class declarations.
Visitor v = new OnlyInterestedInOneTypeOfListener();
for (Listener l : listeners) {
l.useVisitor(v); // different subclasses will call different methods
// on the visitor. Some may be no-ops for different visitor
// implementations
}
(as an aside, I note that you want to discover entries that implement a particular method. This is called duck-typing, and Java doesn't support it. Other languages such as Scala do)
You can use Guava's Iterables.filter() method. It will iterate only on the subtype you want.
for (YourType filteredElement : Iterables.filter(listeners, YourType.class)) {
doSomething(filteredElement);
}
Your ListenerManager should either return a java Iterator, or a filtered Collection (or List). Don't rebuild a iterator concept on your own. Especially having a begin and next on your manager class will introduce unnecessary states there.
With Java 8, your ListenerManager can easily be writte as:
public class ListenerManager {
private final List<Object> listeners = new ArrayList<Object>();
public <T> Collection<T> listenersOf(Class<T> type) {
return listeners.stream()
.filter(type::isInstance)
.map(type::cast)
.collect(Collectors.toList());
}
public void add(Object listener) {
listeners.add(listener);
}
}
If you use a Java version prior to 8, use a good-old for-each instead:
public <T> Collection<T> listenersOf(Class<T> type) {
List<T> result = new ArrayList<T>();
for (Object l : listeners) {
if (type.isInstance(l)) result.add(type.cast(l));
}
return result;
}
This is only a rough (not compilable) way I would do it
public interface Listener{
public boolean canHandle(Event ev);
public void handle(Event ev);
}
public class OnRenderListener implements Listener {
public boolean canHandle(Event ev){
return ev instanceOf OnRenderEvent; // or look for the classname
}
public void handle(Event ev);
}
public class KeyPressListener implements Listener {
public boolean canHandle(Event ev){
return ev instanceOf KeyPressEvent; // or look for the classname
}
public void handle(Event ev){
keyPressed(((KeyPressEvent)ev).getKey());
}
keyPressed(int key){....}
}
public class Event{}
public class KeyPressEvent extends Event{
int key;
}
public class OnRenderEvent extends Event{
//other stuff
}
//Loop to fire an event
for(Listener lis : listeners){
if(lis.canHandle(currentEvent){
lis.handle(currentEvent);
}
}

Class magic - sorting objects by type automatically

I want to create a kind of in-memory database into which I can put objects of any type that extends EntityProxy. I want to index every object according to its type and id number (which every EntityProxy has - something simple like creating a HashMap for each type.
I could implement this manually with something like
public void put(Object o)
{
if (o instanceof Car)
carIndex.put(o.getId(), o);
else if (o instanceof Bus)
busIndex.put(o.getId(), o);
...
}
But of course I don't want to. I want something more like
public void <T extends EntityProxy> put(T o)
{
indexMap.get(o.class).put(o.getId(), o);
}
I just don't quit have the generics vocabulary to do this. I don't know what the question mark means in template definitions, really - will something like
HashMap<Class<?>, HashMap<Long, EntityProxy>> indexMap
work?
That map is OK; if you really need to add a tiny bit of constraint, just try:
Map<Class<? extends EntityProxy>, HashMap<Long, EntityProxy>> indexMap;
This would make sure the key class can only be an EntityProxy.class or subclass.
You can think of the question mark as some "anything", but anonymous. So <?> means really anything -- any Object, <? extends EntityProxy> means anything that fulfils this condition (passes the "instanceof EntityProxy" test).
The type safety here is less than desired, as you can still put anything as key and anything in that map. I mean, you can legally put this in the map:
indexMap.put(EntityProxy1.class, new HashMap<Long, EntityProxy2>());
(assuming EntityProxy1 and EntityProxy2 are both subclasses of EntityProxy) since there's no correlation between the key and the value. To enforce that, the put() method of the map would need to be declared like this:
<T extends EntityProxy> put(Class<T> key, HashMap<Long, T> value);
T is pretty much like ? but the main difference is that it provides you with a name that you can refer to it in that context.
So, if I said that ? stands for "anything", I would say T stands for "something", as you can refer to that something once you declare it.
But you would need a custom data structure for this, as java.util.Map does not provide this kind of constraint. If you're using it as shown in your code sample, I don't think you really need these enforcements.
Note that in this example I used List. You could easily replace this with your Collection class of choice and adapt accordingly.
public interface Classifiable {
String classification();
}
public abstract class Automobile implements Classifiable {
// String classification defined in child classes
}
public class Car extends Automobile {
public String classification() { return "Car"; }
}
public class Bus extends Automobile {
public String classification() { return "Bus"; }
}
public class AutoMap {
Map<String,List<Automobile>> theMap = new Map<String,List<Automobile>>();
public AutoMap() { }
public void add(Automobile a) {
String type = a.classification();
List<Automobile> list = theMap.get(type);
if(list == null) {
list = new LinkedList<Automobile>();
theMap.put(type,list);
}
list.add(a);
}
public List<Automobile> getAutosOfType(String type){
return theMap.get(type);
}
}
public static void main(String[] args) {
List<Automobile> autos = getRandomAutos(); // defined somewhere? :)
AutoMap theAutomap = new AutoMap();
}
If you don't mind using the class name, it's as simple as:
public void <T extends EntityProxy> put(T o)
{
HashMap map = indexMap.get(o.getClass().getName());
if (map == null)
{
map = new HashMap();
indexMap.put(o.getClass().getName(), map);
}
map.put(o.getId(), o);
}
This code will create the required sub-hashmaps as you go along.
If you use getClass().getName() you get names on the form com.mypackage.Bus. If you're willing to handle name collisions and only want the simple name (in this case "Bus"), use getClass().getSimpleName() instead.
Try:
Map<Class<?>, Map<Long, EntityProxy>> indexMap = new HashMap<Class<?>, Map<Long, EntityProxy>>();
and
public void put(EntityProxy entityProxy){ // generics don't add anything here
...
(I didn't test it)

Categories

Resources