Just like this question, when debugging an application, I want to let the application pause at a breakpoint only when the current call stack has a certain method. However, I'm using Netbeans.
In Java the current call stack could be obtained in several ways, like
Thread.currentThread().getStackTrace()
which returns an array of stack trace elements.
Is it possible to iterate through the array (or converted list), check the method names and return a boolean in just one line?
Or, if I need to write a method which checks the array and returns the boolean based on existence of interested method, where should I put it?
For my specific requirement, using lambda and stream in Java 8:
Arrays.asList(Thread.currentThread().getStackTrace())
.stream()
.anyMatch(e -> e.getMethodName().contains("fetchByABC"))
You can add a private method testing conditions on the stack and call it from the conditional breakpoint. Here is a proof of concept:
public class DebugStack {
private int x = 0;
private void m1(){
x++;
m2();
}
private void m2(){
x+=3;
}
private boolean insideMethod(String methodName){
for (StackTraceElement stackTrace : Thread.currentThread().getStackTrace()) {
if (stackTrace.getMethodName().equals(methodName)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
DebugStack dbg = new DebugStack();
dbg.m1();
dbg.m2();
}
}
If you put a conditional breakpoint inside m2() with this.insideMethod("m1") as a condition the application will pause at the breakpoint only when m2() is called from within m1().
Related
I am learning recursion and below is one example that I am tracing through to better understand it
public static void main(String []args) {
new TestRecursion().strRecur("abc");
}
public void strRecur(String s) {
if(s.length() < 6) {
System.out.println(s);
strRecur(s+"*");
}
}
Below is what I have understood so far.
- In the first call to strRecur("abc"), the method gets added to execution stack. It prints "abc" before pausing due to a recursive call with parameter "abc*".
The second call with "abc*", pushes method strRecur(abc*) to the stack and prints "abc*" to console.
The third call with "abc**", pushes method strRecur(abc**) to the stack and prints "abc**" to console.
The fourth call with "abc***", pushes method strRecur(abc***) to the stack. Since the base condition is met, the method completes (without printing anything) and pops out of the stack.
The third call with "abc**" is completed and popped out. Since there is no pending code to execute nothing happens.
The second call with "abc*" is completed and popped out. Since there is no pending code to execute nothing happens.
The initial call with "abc" is completed and popped out. Since there is no pending code to execute nothing happens.
Prints following to the console -
abc
abc*
abc**
I think I understand what is happening here. Now, I want to try a slight variation of this code. Instead of callingstrRecur(s+"*"), I would like to do return strRecur(s+"*")
public class TestRecursion {
public static void main(String []args) {
new TestRecursion().strRecur("abc");
}
public String strRecur(String s) {
if(s.length() < 6) {
System.out.println(s);
return strRecur(s+"*");
}
return "Outside If";
}
}
My expectation was that, once strRecur(abc***) pops out, it's output (abc***) would be returned to the next strRecur() on the stack, so I would see abc**** printed in the console. Same for other recursive calls as well.
However, the output in this case is exactly the same as when there is no return statement. My understanding (which of course is not correct) stems from the recursive factorial implementation, where we do something like
return n * fact(n-1);
Here fact(n-1) is resolved with the returned value of n, once the previous method on the stack completes. Why doesn't return behave in the same way in this example?
The output of both methods is produced by the println statements within the recursive method, which is why it is identical in both methods.
The value returned by the second method is not printed anywhere, which is why you don't see it displayed.
If you would print the result of the second method, you will see it is "Outside If", since that's the output of the last recursive call, which is then returned by all the other method calls.
If you want the output to be abc***, you should
return s;
instead of
return "Outside If";
The full code would be:
public static void main(String[] args) {
System.out.println(new TestRecursion().strRecur("abc"));
}
public String strRecur(String s) {
if(s.length() < 6) {
return strRecur(s+"*");
}
return s;
}
Here is how to make it return the value instead of printing it:
public static void main(String[] args) {
String result = StrRecur("abc");
System.out.print(result);
}
public static String StrRecur(String s) {
if(s.length() < 6) {
return s + "\n" + StrRecur(s+"*");
}
return "";
}
This does the same, but the side effect happens only in main.
Assignment: Write a JUnit test assuming you have an array of int values and you only want the JUnit test to fail if any of the values are less than 20.
I know it only asks for the JUnit assuming the other methods are already created. But I want to create them anyway. However I do not know how to go about it. This is my code so far:
package ArrayJU;
public class ArrayJUTest {
public static void main(String[] args){
ArrayJUTest array = new ArrayJUTest();
int arr[] = {23,25,50,68,3};
System.out.println(array.arrayLessThan(arr));
}
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element>20){
return true;
}
else{
return false;
}
}
}
}
For the arrayLessThan Eclipse is telling me that I need to return a boolean, however I wouldn't know how to iterate through the array without a for loop. And if I return a true or a false outside the for loop it will defeat the purpose of what I'm trying to do with the if/else statements. How do I go about this? Your help will be greatly appreciated.
JUnit Test:
package ArrayJU;
import static org.junit.Assert.*;
import org.junit.Test;
public class JUnitArrayTest {
#Test
public void JUnitArTest(){
int[] arr = {32,52,89,12};
ArrayJUTest arra = new ArrayJUTest();
boolean poop = arra.arrayLessThan(arr);
assertEquals(false, poop);
}
}
Eclipse (really the java compiler) is complaining because after your for loop, your method doesn't return a boolean. The compiler doesn't figure out that the method never gets that far because it will always return during its very first iteration. Which is a problem anyway, since your method will never look beyond the first array element.
The typical way to code a loop like this is something along these lines:
public boolean arrayLessThan(int[] array) {
for (int element: array) {
if (element < 20) {
return false;
}
}
return true;
}
But beyond this, you're missing the point of JUnit. It's a framework, and you need to write your tests as methods of test classes that are written in a very specific manner required by that framework. You don't write your own main function - the framework provides one that looks through your code to find all your test classes and the tests implemented in each class, and then runs those tests for you.
You should google for documents / tutorials / examples of JUnit and then try again.
This question seems to be more about "why does this not compile and what the method return for an empty set" than "how do I write a JUnit test". I would recommend reading up on some JUnit tutorials (like this tutorial from mkyong) to get an understanding of them. I'll try to answer what I think is the first question.
The first thing is to note about the correctness of your loop based on your description. The loop will currently always return a value based on the first value of the array:
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element>20){
return true;
}
else{
return false;
}
}
}
Based on your description, it should only return false if any item matches your predicate (an item is less than 20). You are also getting a compiler error because it does not return anything for an empty array (0 elements). This would be one way to change it:
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element < 20){
return false;
}
}
return true;
}
And if I return a true or a false outside the for loop it will defeat
the purpose of what I'm trying to do with the if/else statements
Well, not really. It depends on how you want to model the 0-element array case. The best way to model it would be to return true because you cannot point to an element that does not satisfy your condition. This is known as vacuous truth.
You can read a good explanation for Java 8 streams with anyMatch and allMatch and vacuous truth in this question/answer.
I'm confused, there are two issues...
The first is that this isn't a junit test.
They look like this:
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
class HypotheticalClassTest {
private HypotheticalClass hypClass;
#Before
public void setup() {
hypClass = new HypotheticalClass();
}
#Test
public void ensureNoNumsLessThanTwenty() {
int[] result = hypClass.hypotheticalMethod();
// Some assertions. Check out the org.junit.Assert class.
}
}
Second, is you method arrayLessThan
Let's go through it step by step:
public boolean arrayLessThan(int array[]){
for (int element : array) { // For each int in array...
if(element>20){ // If element is greater than 20
return true; // Return true (returning stops the loop,
// do you want to stop on the
// first element greater than
// 20?)
} //
else{ // otherwise
return false; // Return false
}
} // Assuming there are no elements in the
// array (length 0) then this is where it
// comes. There's no return here, there
// needs to be, then it will stop
// complaining.
}
Looking at it now we see it doesn't compile because there is no return statement for the case of an empty array. Also we see it only checks the first element! Look up what continue does, it will fix the issue of only checking the first element, or write your condition differently.
I have recently started experimenting with the return statement, and I have a small doubt relating to it- When I have a method which calls another method, will the return statement of that method which I am calling be displayed?
Let be give an example to make it clearer-
/** Program to test return statment */
public class Test
{
public static void main(int a)
{
EvenOrOdd(a);
}
private static boolean EvenOrOdd(int a)
{//I can declare as public and run directly but then what is the point in calling the method?
if(a%2==0)
{
System.out.println("The output is true.");//Displays
return true;//Does not display(As in that window does not pop up with the result.)
}
else
{
System.out.println("The output is false.");//Displays
return false;//Does not display
}
}
}
If I were to simply remove the main method(or even make the second method public and run that directly), my return statement is displayed however if I attempt to call the method and run the program my return statement isn't displayed.
So is this just a problem I am facing or is it a general rule in Java that the return statement doesn't work when you call another method(which has a return statement)?
If it is the latter, then I apologise, I was not aware of this.
Thanks...
***UPDATE***
It seems that nobody has understood what I exactly mean. I will give another example-
Please run this program-:
/** Program to test Return statment;simple program to return sum of two digits */
public class Return_Test
{
public static int main(int a,int b)
{
return a+b;//What I am lloking for is that box in which this is displayed.
}
}
A return statement only returns the value ,does not Display it
If you don’t catch the return value , how can it be displayed? add something like this and try
,
public class Test
{
public static void main(int a)
{
boolean temp=EvenOrOdd(a);
if(temp)
System.out.println("Output is True");
else
System.out.println("Output False(not even )");
//Or you can directly call the method as' System.out.println(EvenOrOdd));'
}
private static boolean EvenOrOdd(int a)
{//I can declare as public and run directly but then what is the point in calling the method?
if(a%2==0)
{
System.out.println("The output is true.");//Displays
return true;//Does not display
}
else
{
System.out.println("The output is false.");//Displays
return false;//Does not display
}
}
}
And Please try learning some good Naming Conventions , Classes are Named like this ,
FirstSecond,TestException(Each Word Starts with a Capital Letter) etc , methods start with a small letter , isPrime() , isEven(),
What a lot of other responders don't know is that when you run a method in BlueJ, it executes the method, and if the the return value of the method is non-void, it is shown in a popup dialog by invoking toString. That's what the questioner means by the value being displayed.
The answer to the user's original question is that by surrounding the method with a void return, it "hides" the result. So this code:
public void callMe1(int a)
{
EvenOrOdd(a);
}
will not display the return. But if you adjust the return type and actually return the value of the inner call:
public int callMe2(int a)
{
return EvenOrOdd(a);
}
Then BlueJ will display the returned value. The display aspect is down to BlueJ, but the rules for whether or not the value gets returned are the same as in Java; void means no return.
Within the body of the method, you use the return statement to return the value. It will not print anything on its own.
Changes done - System.out.println(EvenOrOdd(5));
public class Test {
public static void main(String[] args) {
System.out.println(EvenOrOdd(5));
}
private static boolean EvenOrOdd(int a) {// I can declare as public and run directly but then what is the point in
// calling the method?
if (a % 2 == 0) {
System.out.println("The output is true.");// Displays
return true;// Does not display
} else {
System.out.println("The output is false.");// Displays
return false;// Does not display
}
}
}
Output
The output is false.
false
You never actually display the return result from the method...
The name of the method is consuming EvenOrOdd returning true or false is ambigious, may isEven would be better...
You could try something like...
System.out.println(a + " is even = " + EvenOrOdd(a));
You should also avoid using multiple return statements within a single method, it can quickly become confusing as to how the method actually works, in your case, you can reduce the over complexity at the same time, for example...
private static boolean isEven(int a)
{
boolean isEven = false;
if(a%2==0)
{
System.out.println("The output is true.");//Displays
isEven = true;//Does not display
}
return isEven;
}
first change your main signature from main(int a) to main(String [] args) otherwise you will get following runtime exception :
Error: Main method not found in class yourpackagename.Test, please define the main method as:
public static void main(String[] args)
well you didn't print the value return from function :
in your main do this:
System.out.println(EvenOrOdd(5));
Is there a way to identify whether the following method executed completely or returned halfway through(i.e at line no 3)
static int a=0;
static void test(){
if(a>10){
return;
}
a++;
}
The method was invoked by another method.(a might have been changed by it)
I cannot change the method declaration. I am dealing with an object I created from a java file created by someone else. I am not allowed to change the original file
Your method does almost nothing and no there is no way in this example you gave to know if the method returned before complete execution but if you willing to change the function to a boolean type you can return true at complete execution and false at incomplete.
static boolean test()
{
if(a>10)
return false;
a++;
return true;
}
Run the code under debugger like jdb and set the breakpoint on the internal return statement. If the program stops at this breakpoint, this obviously means that it would return through that statement.
To make things more automated, you could try to launch the debugger and control the debugger from a Java program through Runtime. This would make the approach applicable for more use cases, while not for all.
You could use
void test(int a) {
if (a > 10) {
return;
}
a++;
System.out.println("test executed completely!");
}
Or if you want to use the information programmatically
private boolean executedCompletely;
void test(int a) {
executedCompletely = false;
if (a > 10) {
return;
}
a++;
executedCompletely = true;
}
When you use your test method, you can check whether it ran completely this way:
int initialA = a;
test();
int finalA = a;
if (finalA != initialA) {
//a has been changed, therefore the method ran completely
} else {
//a has not been changed, therefore it was not incremented, therefore the method did not run completely
}
I am new to Java and encountered a program with a 'while' loop that had the condition being an object reference/call. I traced the code thoroughly and did not see any terminating conditions for the object (it would make sense if the object in the while loop condition had a termination condition that the 'while' loop implementation caused).
NOTE: this involves 'inner'/'nested' classes, so I am not even entirely sure that that is the reason this works. How can a loop be satisfied by this manner of syntax? I will try to frame my question in the pseudocode below:
class DemoClass {
demoClassfoo() {
InnerClassdemo object2 = this.new InnerDemoClass;
// Here is where my confusion is. I always thought that the
// while loop had to terminate with a logical statement being
// satisfied: like it is calling an object?
while(object2.innerClassfoo()) {
IMPLEMENTATIONS;
}
}
class InnerDemoClass {
innerDemoClassfoo() {
IMPLEMENTATION;
}
}
public static void main(String[] args) {
DemoClass object = new DemoClass();
}
}
This works since the method innerClassfoo returns a booleanvalue, thus satisfying the while condition. By the way, the code should look like this:
class InnerDemoClass{
boolean innerDemoClassfoo(){
//implementation goes here
//make sure to ALWAYS return the value
boolean result = ...
return result;
}
}