toString blocking my main - java

I've nearly got this Java program working 100% as intended, but my toString method is causing the whole system to break down... apparently. Here are the two pieces of code which seem to be clashing.
public class Main
{
public static void main()
{
Ground ground = new Ground();
ground.play();
}
}
that's the main function. fairly basic stuff. here's the play function:
public void play()
{
int i = 0;
System.out.println(Ground.toString());
while(i < 100 && isChestUnlocked() == false)
{
turn();
System.out.println(Ground.toString());
++i;
}
System.out.print("You unlocked the treasure!");
}
When I try to use it like this, bluej spits the dummy at me and claims that toString can't be referenced in a static context. How can I fix this? It feels like one of those "two characters are wrong" questions, and it's driving me nuts.
EDIT: If I change the Ground.toStrings to ground.toStrings, it claims it can't find the variable ground.
EDIT EDIT: Though I could swear it didn't work before, apparently this.toStrings works now. Thanks to ratchet for that!

remove the Ground or replace with this.
public void play()
{
int i = 0;
System.out.println(this.toString());
while(i < 100 && isChestUnlocked() == false)
{
turn();
System.out.println(this.toString());
++i;
}
System.out.print("You unlocked the treasure!");
}
Ground means the class while this is the current object the method is running on.
In fact just doing System.out.println(this); will work just as well. The println(Object) overload of System.out will invoke toString on the passed in object.

System.out.println(Ground.toString());
This calls toString() on the class rather than the object, which would require a static toString() which likely does not exist.
You need to change all instances of Ground.toString() to this.toString() or simply toString(), referring to the instance rather than the class.

Related

How do I fix this stack overflow error in my code below?

I am trying to find the square of a number using the scanner method but keep getting a
stackflow error. I am new to programming will be glad if someone helps me out.
My code is as below
import java.util.Scanner;
interface Number {
int findSqr(int i); // Returns the square of n
}
//a class A which implements the interface Number.
class A implements Number {
public int findSqr(int i) {
return findSqr(i);
}
}
public class Question5_1{
public static void main (String[] args){
A a = new A(); // an object of class A
// Reading a number from the keyboard
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.print(a.findSqr(i));
}
}
Fix the line which invokes the function recursively return findSqr(i) with return i * i as follows --
public int findSqr(int i) {
return i * i;
}
What you did there is an infinite recursion. The bit where it says
public int findScr(int i) {
return findSqr(i)
}
essentially calls the very same method an infinite number of times in the return statement.
What happens is, that you execute the method, and it tries to return an integer. What you wrote though is a return statement that "returns" another call of the same method, so it gets executed again. Then the whole thing starts over again, so you get a StackOverflow.
Since there is no other code present, I have no idea what you are actually trying to do, but the return findSqr(i) line is what causes the problem.
Initially, recursion may be a rather complicated subject to really wrap you head around, I suggest you either avoid it for now (although it enables you to solve many problems in a really elegant way) or try to understand it a bit better maybe. I'd suggest the Wikipedia article about recursion, although it gets complicated quite fast, or any other tutorial on it, just look it up on Google.

Is there any javadoc tag like "must avoid"?

I am writing a method that is a little overpowered and I want to throw a warning to my user telling him to "better know what you're doing", just like the way #deprecated behaves. I can write this one the method name, but I wonder if there is a more elegant way of doing this.
public class Divison {
public Divison() {
}
private int up;
private int down;
public int eval() {
return ((int) up/down);
}
public void setVars(int up, int down) {
this.up = up;
if (up%down == 0) {
this.down = down;
} else {
throw new ArithmeticException("the values must be divisible");
}
}
public void betterKnowWhatYouDoingSetVars(int up, int down) {
this.up = up;
this.down = down;
}
}
Allowing the outer world to break your invariants is never a good idea, as your class becomes useless: since I can't rely on its internal state being consistent, it's just a bag of values unrelated to each other. To write correct programs, I would need to replicate all your validation logic inline before every usage of that class.
By the way, your example implementation can get in an inconsistent state even without the betterKnowWhatYoureDoing... method, and I'm not even mentioning multi-threading.
You can prevent that by simply making the class immutable and doing that check in the constructor.
I think you should thoroughly re-evaluate your design before going this route.
If you must provide such functionality (I can hardly imagine any reason why), at least make it package-private (instead of public and documented as "dangerous").
Also, those who really know what they're doing are probably never going to call that method anyway, so it's a bit pointless... :)

Testing with JUnit a void method

I have the following code, and I dont know how to test it.
I was trying to access the count contD++, and if i have 3 negatives.
I cant test it with something like this assertEquals(contD,3)
public void listarD() {
int contD = 0;
for(int i=0; i< clientes.length; i++) {
if(clientes[i].getSaldo() < 0) {
System.out.println(
"Cliente: " + clientes[i].getNombre() +
". Saldo: " + clientes[i].getSaldo());
contD++;
}
}
if (contD == 0) {
System.out.println("No hay descubiertos :D");
}
else {
System.out.println("TOTAL DESCUBIERTOS: " + contadorDescubiertos + " clientes");
}
}
Correct way would be to extract a method that calculates your contD value and test it.
public void listarD() {
int contD = calculateContD();
if (contD == 0) {
...
}
}
And then you can test this calculateContD() method.
A well designed method should be easy to test, the fact that you cannot test your method is an evidence of a design flaw.
Some suggestions:
Make the result of the method verifiable (That could imply that it's
no longer void).
Leave the output on a permanent storage, like disk
or database.
There is one way you could theoretically test this: one can change the object behind System.out.
So, theoretically, you could put a "special" OutputStream into System.out; run your void method; and then check that the messages you would expect ... show up in that stream of yours.
But that simply makes no (t much) sense: you see, in the real world, you rarely do print to system.out. In the real world, your methods either
do return a value
make calls on other objects
change some internal state of the enclosing object/class
Thus: in the real world, you write tests that care about such kind of events.
So, as you figured yourself; the real answer is to change the behavior of your void method; by returning the value it computed already!
In general, a function that can only be verified by human eyes is not a good design. Callers would never know what happened after they call your function. Either a return value or an exception for denoting the result is better than nothing.

AspectJ creates plenty of methods on pointcut

I am new to AOP (using AspectJ / ajc) and have searched / googled the internet high and low searching for an answer to my puzzle. Hopefully, someone here might have it.
As I was given to understand by the documentation, AspectJ is suppose to inject code. From my experience, however, it seems like it is mostly adding code (and simply makes an exchange of method calls).
For example, if I have the method:
private static int foo() {
System.out.println("Hello world");
return 1;
}
And I define the following around advice for it (with a dummy random in order to manipulate proceed() vs. some other return value):
pointcut foo() : call(int com.mytest.aspects.HelloWorld.foo(..));
int around() : foo() {
System.out.println("around()");
if (System.currentTimeMillis() % 2 == 0)
return proceed();
return 0;
}
I get the following after decompiling using jd-gui:
private static final int foo_aroundBody0()
{
return foo();
}
public static void main(String[] args)
{
foo_aroundBody1$advice(HelloAspect.aspectOf(), null);
}
private static final int foo_aroundBody1$advice(HelloAspect ajc$aspectInstance, AroundClosure ajc$aroundClosure)
{
System.out.println("around()");
if (System.currentTimeMillis() % 2L == 0L)
{
AroundClosure localAroundClosure = ajc$aroundClosure;return foo_aroundBody0();
}
return 0;
}
private static int foo()
{
System.out.println("Hello world");
return 1;
}
If that right? Am I perhaps doing something wrong?
I tried using ajc with my android application, but thanks to some jars and SDKs, I got to the dreaded "too many methods" problem.
I am using call pointcuts for most of the time, however it seems that these extra methods are added for each call, even if done within the same class and method, thus increasing my code size and method count significantly.
Any help understanding if this is correct and how it works will be greatly appreciated!
Your understanding is about correct. If you want to avoid too many methods being created, use execution() pointcuts instead of call() wherever possible, because then only one synthetic method per callee will be created, not per caller. I.e. if one method is called from 25 different places, only one additional method will be created instead of 25.
Furthermore you can avoid overhead by limiting the weaving scope of your aspects to the really needed joinpoints. Most aspects I see weave into way too many places. Also, if before() or after() is sufficient, avoid around().

Is while(boolean method); a bad practice? (Example)

I really like the mechanism and style of this code, but Im kinda unaware if this coding style is appropriate or a bad practice.
public class Test
{
private static int counter;
private final static ArrayList<Object> _objects = new ArrayList<>();
public static void main(String[] args)
{
//iterate till you find a valid object randomly
while (!doStuffIfValid(_objects.get(Rnd.get(_objects.size()))));
}
public static boolean doStuffIfValid(Object obj)
{
if (++counter > 30)
return true; //dont try more than 30 times
// if condition
// {
// //do stuff then exit the caller loop
// return true;
// }
return false;
}
}
Well,
The answer to that lies within the boolean method. If that method is bloated, and resource heavy; then no.
Also, if you're randomly checking objects, it may be a better idea to instead: eliminate the objects you know aren't valid from a list, then randomly select from that list.
This way the pseudo-randomizer doesn't (by chance) select invalid objects to validate over, and over again; and waste time/resources.
Cheers.
There is nothing wrong with using a boolean method as a condition for a while-loop. However, stuffing loop functionality in the loop header is, generally, a bad practice. It leads to a code which is difficult to understand, debug (breakpoints become inconvenient) and maintain.

Categories