I'm trying to make a collection of observables and then add an observable into that collection.
Right now in this code, it's saying = new Observable<ArrayList<DMRegistration>>(); has protected access in rx.Observable and will not instantiate.
Also with dmRegistrations.add(dmRegistration); it complaining about add saying that it cannot resolve method 'add(rx.Observable)'
I'm very new with observables and have Googled around but have found nothing that provided information leading to a possible solution. Am I approaching this the wrong way?
#Override
public Observable<Collection<DMRegistration>>getAllRegistrations() throws DMException{
try{
Observable<Collection<DMRegistration>> dmRegistrations = new Observable<ArrayList<DMRegistration>>();
Observable<DMRegistration> dmRegistration = execute(get(baseUrl + "registrations"), DMRegistration.class);
dmRegistrations.add(dmRegistration);
return dmRegistrations;
}catch(RestException e){
throw new DMException(e);
}
}
Well, if the Observable constructor has protected access, then you can't use it unless you're working in the Observable class or a subclass of Observable. So if you want to make this work with minimal changes you'll have to either make this class a subclass of Observable or make the constructor public, but depending on your situation that may or may not be possible.
The reason the compiler is complaining about being unable to resolve add(rx.Observable) is because it means exactly what it says. It can't find a method matching that combination of name/parameter in the Observable class. Could be because the way you have Observable parameterized, as it appears that add() is looking for a different type than you want to put in.
I'm making a bit of a guess here as to the structure of Observable, but the type of element that you're trying to add doesn't seem to match the type of element that dmRegistrations takes. You declared that dmRegistrations is Observable<Collection<DMRegistration>>, which (I assume) means that you're observing Collection<DMRegistration>. You're trying to add an object of type Observable<DMRegistration>, which isn't what add() is looking for, unless Observable implements Collection.
Related
I have this code
public class TupleSpace implements aTupleSpace {
private Collection<aTuple> theSpace;
public TupleSpace() {
theSpace
}
public void out(aTuple v) {
theSpace.add(v);}
the .add causes an error, I think its either because .add is not defined for a generic collection type? or because im not properly understanding the line:
private Collection<aTuple> theSpace;
i have to keep this line the same but can make any changes to the out method or the rest of the class
I just want to be able to add things to a collection and search the collection for them
A Collection is just an Interface.
It defines what you can do with theSpace and is somewhat independent of what theSpace actually is. It may be a List or a Map or something entirely different.
Collection.add(E e) is indeed a method that is common to all Collections. Still the actual implementation might differ.
However, private Collection<aTuple> theSpace; is just declaring the variable.
It will be set to null when you create an instance of TupleSpace.
This is the reason for the NullPointerException that is thrown when you try to use theSpace.
Hence, you will need to create a concrete Collection instance and assign it to theSpace before you can use it (e.g. add objects).
There are plenty of Collection types that come ready to use with the SDK.
Choose one that fits your use case. Here is an example, using an ArrayList:
// ...
public TupleSpace() {
this.theSpace = new ArrayList<aTuple>();
}
// ...
In the generic class Class<T> the method getConstructors() has a return type with unknown generic type parameter instead of T. The reason for this is explainend in the javadoc.
Note that while this method returns an array of Constructor<T> objects (that is an array of constructors from this class), the return type of this method is Constructor<?>[] and not Constructor<T>[] as might be expected. This less informative return type is necessary since after being returned from this method, the array could be modified to hold Constructor objects for different classes, which would violate the type guarantees of Constructor<T>[].
A colleague of mine and I have tried to understand that explanation. In our understanding they are basically saying that it is of unknown generic type, because some caller could put other Constructor objects into that array. Did we get that right? And if so, why would someone design an API this way. Wouldn't it be better to use the specific type and trust the programmer to use the array correctly? To us it sounds a little like "We are making a worse API because the programmer using it might try something stupid". Where lies our fallacy?
The point that was mentioned by Ashu Pachauri in the comment (namely, that the array is returned for backward compatibility) is certainly valid. And in general, arrays and generics don't play together very well. (For evidence, look for all the stackoverflow questions related to "Generic Arrays"...)
Additionally, there is a rule that an API should be easy to use and hard to misuse. In this case, this is related to the Principle of least astonishment: Someone obtaining the constructors with this method could perform a perfectly legal sequence of operations on the returned array, and in the end, receive an unexpected ClassCastException. So one could say that the fact that a Constructor<?>[] array is returned aims at a "fail-fast" behavior.
An illustrative example:
import java.lang.reflect.Constructor;
public class GetConstructorsReturnType
{
public static void main(String[] args) throws Exception
{
// This causes a warning, due to the cast, but imagine
// this was possible
Constructor<DerivedA> constructorsA[] =
(Constructor<DerivedA>[])DerivedA.class.getConstructors();
// The following lines are valid due to the subtype
// relationship, but would not be valid if constructorsA
// was declared as "Constructor<?>"
Constructor<? extends Base> constructors[] = constructorsA;
constructors[0] = DerivedB.class.getConstructor();
// This causes a ClassCastException (and would also not
// be possible constructorsA was declared as "Constructor<?>"
DerivedA instance = constructorsA[0].newInstance();
}
}
class Base
{
}
class DerivedA extends Base
{
public DerivedA()
{
}
}
class DerivedB extends Base
{
public DerivedB()
{
}
}
It's the exact same reason why you are not allowed to do new Constructor<T>[], but you are allowed to do new Constructor<?>[]. You can apply your same argument and say "Wouldn't it be better to use the allow the specific type and trust the programmer to use the array correctly?" Well, Java decided no. (You can imagine that inside the getConstrucotrs method, they need to create an array of Constructor, and they cannot do new Constructor<T>[] but they can do new Constructor<?>[].)
Of course, you can make an unchecked cast of the Constructor<?>[] to the Constructor<T>[], but that will give you a warning in your code, in which case you would take responsibility for making sure it's safe. But if the getConstructors method this this unchecked cast in their code, you as the caller would never be warned about the unsafeness.
Sorry about the strange topic name, could not find one that fitted well.
To my problem, i want to create something dynamic in Java, it is a very simple class that can take an event and throw it along, sadly have the system i am using be made so each event must have it own method where the event is the argument of the method, but the good news is that we can add as many event listener classes as we want! I wan my program to be able to dynamic add and remove the methods that are being listened to, by add and remove the listen classes.
I am not good with Java but have a fair deal expirence with C#, so i attacked my problem as i would there and created this class.
public class TESPluginDynListener<T> implements Listener {
TESPlugin plugin;
public TESPluginDynListener(TESPlugin plugin){
this.plugin = plugin;
}
#EventHandler(ignoreCancelled=false, priority = EventPriority.LOW)
public void onDynEvent(T event){
if(event instanceof Event)
plugin.onEvent((Event)event);
}
}
This seems to work fine, but my problem is, that the event i have to register do i get as a String, example "some.package.someEvent", and i have no idea how to translate that into the Type T so i can add the listener class.
So how can i create an instance my class TESPluginDynListener where T is translated from a String? I am not interested in doing a lot of if else, as i want this to be as dynamic as possible!
Here is an idea of what i am trying to do
String eventClass = "some.package.someEvent";
TESPluginDynListener listener = new TESPluginDynListener<Type.FromName(eventClass)>(this);
eventhandeler.RegisterListener(listener);
It sounds like you're looking for Class.forName and Class.newInstance.
On the other hand, bear in mind that type erasure in generics means you don't really need to know T in order to build a TESPluginDynListener... you probably want to take Class<T> in the constructor for TESPluginDynListener and use Class.isInstance rather than instanceof within onDynEvent.
Am having some arguments say (String a, Treeset b, Set c)
and I try to get the class by arguments[i].getClass(); of the above arguments..
is Iit possible to get the class of the interface <Set>.
For example:
Class[] argumentTypes = new Class [arguments.length];
for (int i = 0 ; i < arguments.length ; i++)
{
argumentTypes[i] = arguments[i].getClass();
}
The code you've given will find the classes of the arguments (i.e. the values provided to the method) - but those can never be interfaces; they'll always be concrete implementations. (You can never pass "just a set" - always a reference to an object which is an instance of an implementation of the interface, or a null reference.)
It sounds like you want the types of the parameters - which you'd get via reflection if you absolutely had to, finding the Method and then getting the parameters from that with getParameterTypes. But given that you're within the method, you already know the parameter types, because they're at the top of the method... I'm not sure the best way of finding "the currently executing" method, if that's what you're after.
If you're just trying to get the class associated with Set, you can use Set.class of course. But again, it's not really clear what you're trying to do.
EDIT: Okay, judging from your comment, there are some logical problems with what you're trying to do. Going from the values of arguments to which method would be invoked is impossible in the general case, because you've lost information. Consider this, for example:
void foo(String x) {}
void foo(Object y) {}
foo("hello"); // Calls first method
foo((Object) "hello"); // Calls second method
Here the argument values are the same - but the expressions have a different type.
You can find all methods which would be valid for the argument values - modulo generic information lost by type erasure - using Class.isAssignableFrom. Does that help you enough?
Note that you'll also need to think carefully about how you handle null argument values, which would obviously be valid for any reference type parameter...
You can use http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getInterfaces()
You will get the class what the caller provided.
I mean,in below class you will get HashSet.
Set set=new HashSet();
System.out.println(set.getClass());
You can do this in two ways given below
Set s = new //any class that implements it for example HashSet or TreeSet etc.;
s.getClass().getName(); //This will return the name of the subclass which is refered by s.
or if in other way can do it
Set s = null;
s.getClass();//This causes NullPointer Exception
There are many questions about the issue of combining generics with varargs. This would require generic arrays which don't exist when actual code tries to instantiate them. Moreover, there's a good amount of documentation on the compiler-vagueness of warnings from varargs methods with non-reifiable parameters. Because of type erasure this creates potential heap pollution, hence the warning (in Java 6 at the caller). However, my question is not about these problems themselves. I think I understand that some things aren't possible. What I'd like to know is the way to elegantly workaround these problems in my complex case.
Links for related topics:
Is it possible to solve the "A generic array of T is created for a varargs parameter" compiler warning? where some call this situation a "bad feature" bug.
http://docs.oracle.com/javase/tutorial/java/generics/non-reifiable-varargs-type.html
My case
I have a BookItemSearchAddTask that extends from the Android AsyncTask but somewhere along its inheritance hierarchy has been made generic, more abstract at higher levels:
At a higher level it's SearchAddTask, which contains the method start() to execute the task, called from a client that knows that it passes a BookItem product in.
public abstract class SearchAddTask<ProductToAdd extends Product & NamedProduct>
extends AddTask<ProductToAdd, ProductToAdd> {
public void start(ViewActivity context, ProductToAdd product) throws SpecificAddTaskDomainException, TaskExistsException, TaskUnavailableException {
super.start(context, product);
//more stuff ...
execute(product);
}
}
A level lower it's an ItemSearchAddTask. Here the method doInBackground is implemented, as required by the AsyncTask API. It can still use generics.
public abstract class ItemSearchAddTask extends SearchAddTask<I> {
public I doInBackground(I... params) {
I product = params[0];
//do stuff ...
return product;
}
}
Finally BookItemSearchAddTask is ItemSearchAddTask<BookItem>. A BookItem therefore is an Item, is a Product. The "I" is linked to the class in which this nested task class, ItemSearchAddTask, finds itself:
public abstract class ItemSearchAddWindow<I extends Item & ImageRepresentedProduct & NamedProduct> extends ViewActivity implements View.OnClickListener,
AdapterView.OnItemClickListener {}
The problem
Now, when I run this code I get the following error:
Caused by: java.lang.ClassCastException: [Lnet.lp.collectionista.domain.Product;
at net.lp.collectionista.ui.activities.items.book.ItemSearchAddWindow$ItemSearchAddTask.doInBackground(ItemSearchAddWindow.java:1)
Note the "[L".
I also get compile time warnings at "execute(product);": "Type safety: A generic array of ProductToAdd is created for a varargs parameter"
The cause
To my understanding, the JVM finds that in the doInBackground vararg it gets a Product[] passed in, rather than the Item[] (I[]) it expects. Apart from the generic arrays, which are hard to think about, I think what's going on is the case of the lion cage at http://docs.oracle.com/javase/tutorial/java/generics/subtyping.html. Not by my code, but because the generated generic array of ProductToAdd (which basically extends Product) was created for the varargs param.
I checked that if I pass no argument to execute, that it works. Also using "execute((ProductToAdd[])new MusicCDItem[]{new MusicCDItem()});" worked mostly (don't ask, a MusicCDItem is an Item, just like a BookItem is).
A solution?
However in start() I can't know that I need to pass in a BookItem. I only know about "I". Since that is a generic, I can't create the generic array that is required to pass as the varargs param. I think what is complex about my case is the different levels of using generics, as well as the parallel hierarchies.
How do I work around this feature gap? I considered:
Removing generics. A bit drastic.
Holding on the varargs param everywhere in all the generics bits of code (i.e. change the method signature of start()), until we reach the client code, and only there do I pass one product element only, and that element is of a real type, BookItem. I will get the same warning there but the compiler will be able to generate the correct generic array.
Duplicating the AsyncTask code and changing doInBackground to not use a varargs param because I currently may not need one. I prefer not to do this so I get the benefits when AsyncTask is updated in the future.
Perhaps some reflection code in start(). Ugly.
Is there anything shorter and more local?
Either this, or there is some really stupid typo in my code.
You noted that you get an "Unchecked generic array" warning in SearchAddTask.start() when it calls execute(). However, the actual warning is slightly misleading. What it says is A generic array of ProductToAdd is created for a varargs parameter, but what it really means is, ProductToAdd is a type variable and at run-time I can't create an array of those, so I'll just have to use my best guess.
If you step through into execute() in the debugger, you'll see that the array that was created for the P... declaration is a Product[1] -- exactly what you'd expect from the class cast exception you got. At run time, this is the best the JVM can do, because it's the closest un-erased ancestor of ProductToAdd.
Unfortunately, in ItemSearchAddTask, the JVM's also done the best it can, which is convert the I... declaration into an Item[] (the closest un-erased ancestor of I); thus the ClassCastException when execute() tries to call doInBackground().
The least awful way I can think of offhand to get around this is to sidestep Java's type erasure by keeping ProductToAdd's concrete class around at run time and creating the args array (of the correct type) yourself:
abstract class SearchAddTask<ProductToAdd extends Product & NamedProduct>
extends AddTask<ProductToAdd, ProductToAdd> {
private final Class<ProductToAdd> productClass;
SearchAddTask(Class<ProductToAdd> productClass) {
this.productClass = productClass;
}
public void start(ViewActivity context, ProductToAdd product) {
super.start(context, product);
ProductToAdd[] argsArray = (ProductToAdd[]) Array.newInstance( productClass, 1 );
argsArray[0] = product;
execute( argsArray );
}
}
It does mean you have to ensure that BookItem.class gets passed in, probably when you create the AddWindow<BookItem>, but it keeps the ugliness contained.