I have an assignment and i got a library including an interface class. [InfoItem]
I implement this class [Item].
Now i am required to write a method watchProgram(InfoItem item) [other class, importing InfoItem], which (as shown) requires an
InfoItem.
The passed parameter item has a variable 'Recorded' [boolean] which i want to edit using a method changeRecorded() that i defined in the implementation of InfoItem.
I cannot edit the interface and i get an error message that the method is not found [cannot find symbol]..
Any hints, suggestions, solutions?
Thanks!!
-Samuel-
In the method watchProgram, all Java knows is that the argument is an InfoItem. That argument may or may not be an Item, and thus it may or may not have that method changeRecorded. Since Java can't guarantee that the object has that method, it can't insert the code to call the method when the class is compiled. As far as the Java compiler is concerned, the method changeRecorded doesn't exist in the argument item.
Usually when you run into a situation like this, it's a sign that you shouldn't really be calling that changeRecorded method in the first place. Think very carefully about why you think you need it and how you could change your own code to work without using it. For instance, if someone were to call your watchProgram method with some other implementation of InfoItem that doesn't have a changeRecorded method, what should watchProgram do?
If, after some careful thought, you decide that it really is necessary for you to call the changeRecorded method when the passed-in argument is an instance of Item, you can use a cast to do so:
watchProgram(InfoItem item) {
// do stuff
if (item instanceof Item) { // thanks to ruslan for if statement
Item castedItem = (Item)item;
castedItem.changeRecorded();
}
// do stuff
}
But as I said, this sort of thing should be used sparingly. The whole point of object-oriented programming (specifically, polymorphism) is to make it so you don't have to do this.
You may try next trick, that could be an option for you:
if (item instanceof Item) {
Item myItem = (Item) item;
myItem.changeRecorded();
}
Use this code inside of yours watchProgram() method.
Here we check whether parameter item is of type of Item class and if it's then convert to this type and call Item.changeRecorded() method.
if (item instanceof Item) {
((Item)item).changeRecorded();
}
However be aware that this is not good practice if it can be avoided. I would look to see if there is way to do what you want using only the methods defined in the interface, possibly by making the change a side effect of some other method.
If what you are doing is recording the fact that something has been done to InfoItem you might also consider recording the fact elsewhere than in the object.
Related
How does inheritance work in relation to a for-each loop? Imagine I have two classes: SubClass and SuperClass, and I have the following ArrayList.
/**
* Containes both SuperClass and SubClass instances.
*/
ArrayList<SuperClass> superClasses = new ArrayList<SuperClass>();
Is it possible to iterate over superClasses in such a way as to only select subClasses.
The following:
for(SubClass subClass : superClasses){
// Do Foo
}
does not do this.
The following is the only thing that I could get to work:
for(SuperClass superClass : superClasses){
if(superClass instanceof SubClass){
// Do Foo
}
}
However I do not want to use instanceof unless absolutely necessary, as I keep reading everywhere (StackOverflow, Oracle Tutorials etc) that one can almost always find a better solution that increases encapsulation. Is there a more elegant way of doing this?
Well you could write a helper method to hide the instanceof test... Guava has a method like this, for example, in Iterables.filter, which you could use like this:
for (SubClass subclass : Iterables.filter(superclasses, SubClass.class)) {
...
}
It's only moving the instanceof check though really - it's not getting rid of it. Fundamentally you need that check, because something's got to do the filtering.
The first approach (for (SubClass subClass : superClasses)) cannot work as the compiler cannot ensure that there are only objects of tyoe SubClass in there.
In Java (without external libraries) it is not possible to preselect on the Class. Therefore the instanceof is the normal way to do this.
instanceof would work absolutely fine in this situation. But if you really do have reasons for not using it you could always give the superclass some variable, Boolean skipMe = true, and change that to false in the subclass if you wanted.
But I suggest using instanceof
I recommend to manage a separate List which only contains instances of SubClass, if possible.
I've a huge project with many classes. I've a very specific class; let's name it SuperFoo. I need to find all calls to the method equals() with argument of type Superfoo. Hope it's clear.
So, one more time... in thousands of java files (or bytecode?) I'd like to find all calls to the method java.lang.Object.equals(Object arg) but the argument to this call must be of type SuperFoo. For example:
public void doItWith(SuperFoo foo) {
if (otherFoo.equals(foo)){
// do something
}
...
}
I checked out Browse-by-query, analyzing bytecode and just Java Search in Eclipse and in my opinion none of this works.
A programmatic approach would be to use Aspect Oriented Programming (i.e. AspectJ). You would define a pointcut to capture the method call of interest
pointcut equals(Superfoo o) = call(boolean *.equals(Object)) && args(o);
and then use advice to select each occurrence and query the joinpoint object to get the static information i.e. where it appears in your code.
before(Superfoo o) : equals(o) {
System.out.println("An occurence at "+thisJoinPoint.getSourceLocation());
}
So, you are trying to find out the references of
public boolean equals(Object o)
overridden in SuperFoo. If you have access to the source code, this could be done in eclipse. If you go for Call Hierarchy, eclipse returns back all the occurrence of Object's equals() method. So, you need try the following:
Open SuperFoor. Select the equals method. Right Click. References --> Project. In the resulting search window, on the extreme right, click on the triangle. Select "references to override". That's it. The results returned initially will be filtered and it will mostly contain references of equals overridden in SuperFoo.
Hope this helps.
I'm currently working on a program where I will be dynamically loading classes at runtime and am building a library of functions to support it. One of these functions is a method to easily search a given jar file for a given class name and create a new instance from the given set of initialization arguments.
The issue is arguments. I know how to find a constructor for a class for a set of class types, however, trying to find a constructor that accepts a list of arguments is harder. My first thought was to iterate through the arguments and call getClass() on each, but what about null arguments which may well be a valid thing for some constructors?
Is there any sensible way to find the correct constructor for a given set of arguments?
NOTE: standard Java only, this is a joint project so Java derived languages and 3rd party libraries are not available.
Did you go through Reflection API tutorial?? It has the implementation for exactly what you want..
After you pass the Reflection API Tutorial, you can use single method for your problem
private final boolean checkConstructor(Class<?> type, Class<?>... parameterTypes) {
try {
forName.getConstructor(parameterTypes);
return true;
}catch(NoSuchMethodException e) {
}
return false;
}
What you have to remember that order of the paraemterTypes is important.
You should not allo to sytiation where you call for a constructor not knowing the parametersTypes. Same rule apply to code style that you should not use null in the constructors.
getClass() is a right approach. You have to iterate over all accessible constructors and choose most specific one acting according to the spirit of Choosing the Constructor and its Arguments, including throwing exeptions if 0 or >1 constructors found, and boxing/unboxing as in Determine Method Signature. You cannot implement that algorithms literally because of nulls, but should keep as close as possible.
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.
I want to do some authorization-checks for domain objects. This includes checks if someone is allowed to instantiate an object (depending of it's type - this check is done externally so no need to solve this).
All our domain objects implement one specific interface (directly or indirectly)
What I need is an advice which runs after the instantiation of a domain object and is able to use the created instance (needed for the determination of the permission). (Additionally the advice may not execute when the constructor is called out of hibernate)
I want to implement this using AspectJ (which is working yet for methods) ideally using only static analysis as there are no a runtime dependent changes
Now I am trying to create an #AfterReturning adivce which intercepts constructor calls. But I do not get the pointcut working.
What I tried:
#Pointcut("within(a.b.c.DomainObject+) && execution(*.new(..))")
#Pointcut("execution(a.b.c.DomainObject+.new(..))")
But both does not work.
Does anyone know how I can achieve this?
Regards Michael
Here are some examples that helped me figure out how to do something similar. http://www.eclipse.org/aspectj/sample-code.html
Also, here is something that I have in my project--for testing purposes--to add a listener after an object is created:
pointcut init(JComponent j):
this(j) &&
initialization(*.new());
after(JComponent j) returning: init(j) {
if(j instanceof JButton && !(j instanceof AccessibleButton))
System.out.println(j.toString() + thisJoinPointStaticPart.getSourceLocation());
j.addFocusListener(new VisualFocusListener());
}
EDIT:
The above will execute every time a constructor is called, whether it is the one called or called by this() or super()--probably not what you want. I have just figured out another way to get at the object returned from the constructor.
after() returning(JComponent j): call(*.new(..)) {
//do something with j
}
That reads in English almost like it does in code: "after returning a JComponent from a constructor, do something". I have *.new(..) because I don't care which constructor is called or what parameters it takes as long as it gives me a JComponent. You can further limit that by saying Foo.new(..) or Foo.new(int).