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.
Related
I have a class and it has multiple subclasses which each implement their own methods. Some of these subclasses have common method which I need to call. Is there a way in java to know if the object has a method (without using instanceof)?
This probably points to a design flaw, but you could always use reflection to check if a method exists:
public static boolean hasMethod(Object obj, String methodName) {
return Arrays.stream(obj.getClass().getMethods())
.anyMatch(m -> m.getName().equals(methodName));
}
This, of course, could be refined to include the method's signature too, but the basic idea remains the same.
I'm trying to get the hang of Java. Unit testing is pretty important to me and so recently I've started to use JUnit. It was tough to begin with but I'm getting the hang of it. All of my tests have worked up to this point, with the exception of comparing two objects of the same class (I haven't tried testing a function that creates an object of a different class). Basically, when I have a method within a class that creates a new instance of the class, and I try to test the method, I get a weird error.
"expected:runnersLog.MTLog#433c675d but was runnersLog.MTLog#3f91beef"
I have tried researching this problem, but haven't found anything of much help. Here's the link to my classes on github. The method I am trying to test is the mt() method, and the test class is ILogTest.
This is not the only case where I am having this problem. With any class that has a method that returns a new object of the same class, I am getting this exact same 3f91beef error (even when the object is more complicated - with arguments)
assertEquals will use Object#equals for each object being compared. Looks like your class ILogTest doesn't override equals method, so calling Object#equals will just compare the references by itself, and since they're different object references, the result will be false.
You have two options:
Override public boolean equals(Object o) in ILogTest.
Use assertEquals on the relevant fields that implement equals method e.g. String, Integer, Long, etc. This one requires more code but is useful when you cannot modify the class(es) being asserted.
You need to overrride equals, the equals method in the superclass Object checks for references if both references point to the same object equals is true if not false, so you need to write down an equals method that will check your objects content and check if the values are the same, it is also recommended that you override your hashCode method too.
An example could be:
Custom a= new Custom("");
Custom b= a;
//b would be equal a. because they reference the same object.
Custom c= new Custom("");
//c would not be equal to a, although the value is the same.
to learn more you could check:
Why do I need to override the equals and hashCode methods in Java?
If you are using a modern IDE for development (like Eclipse, IntelliJ etc), they can generate these methods for you. Check that out for two reasons: 1) to save time 2) To prevent possible bugs.
In eclipse IDE, you can do so by selecting source -> generate hashCode() and equals().
One more thing, when you implement of of these two, you have to implement the other one as well.
I am using Eclipse Build id: 20120614-1722.
I have an object class called "TOY1" and a function toString() within it. I previously know that when I call the
System.out.println(TOY1);
It should return the address. However, and for some reason it is returning the toString() declared for my object without me specifying the #Override notation.
Is it safe to keep it that way? Or is this a new feature implemented in the specific build I have.
Thanks
EDIT
As asked this is part of my code:
public class TOY1 {
//irrelevant declarations
public String toString() {
String data;
data="Manufacturer=";
data+=manufact;
data+="DOP:";
data+=date_of_production;
return data;
}
}
When declaring TOY1_instance of TOY1 and then printing out using the System.out.printIn(TOY1_instance)
I am getting the actual data as opposed to some junk address.
My question is where did I override it no warning was shown and no extension overrides this class.
System.out.println(obj); is calling obj.toString() internally. It happens that the default implementation of toString(), if you don't override it, returns some address-like value.
You can omit #Override annotation, but it's safer to use it. It becomes especially useful when you think you are overriding while you aren't because of tiny difference in signature. E.g.:
#Override
public String tostring() //...
won't compile. Even more common mistake is wrong equals():
#Override
public boolean equals(TOY1 obj) //...
Do you see why? Without #Override it's very easy to miss such a tremendous bug.
#Override annotation is just optional,
code works the same with and without it.
But it's a matter of good taste, to use it. It clearly shows what's going on - that you redefine method from super-class or implement method from interface.
And as Tamasz mentioned - it's impossible to annotate with #Override method that actually isn't overriding anything. So it can save you sometimes.
It would always run the closest toString() instance method even if #Override is not specified. To be on the safer side, or to compile quickly and effeciently, you should include #Override at the top
#Override annotation is just for compilers, and JVM does not care about it.
See definition of Override annotation here:
#Target(value=METHOD)
#Retention(value=SOURCE)
public #interface Override
As you can see in the declaration, it is only retained in the source and not in the class file.
OK let me get it clear. So, your over-ridden function is still called but the issue is why is it called even when #override is not used? If that is the case, then this annotation is simply for the compiler to check whether you have actually overriden the function or not. It should not affect the logic of program as such. Also, please post code if you want specific answer.
Actually, System.out.println() can deal with several types of parameters, and one of them is reference to a String.
Please refer this URL
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.
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.