Returns inside ifs confuse Java - java

I have these two methods and Java can't find the "return" in getNumEmails(). All of them are in the same class, which only has static methods
private static int posSymbol=0;
private static int cont=0;
private static String text=null;
private static int getPosSymbol(){
posSymbol=text.indexOf('#',posSymbol);//if there is no symbol, returns -1
return posSymbol;
}
//Main calls this method
public static int getNumEmails(String completeText){
text=completeText;
while(posSymbol!=(-1)){
posSymbol=getPosSymbol();
if(posSymbol!=(-1)){
cont++;
posSymbol++;
}//close if
else{
return cont; //It seems that it doesn't reach the return always
}//close else
}//close while
}//close method
I know that the solution is simple, to delete the "else" and put the return cont; after the while. But I want to know why Java thinks that getNumEmails() could end without returning anything.

I suppose this is about the compiler complaining This method must return a result of type int.
While compilers can sometimes determine if a function will reach the return statement, this is not always the case. It is mathematically impossible to statically determine the dynamic behaviour of a program.
This is called the "Halting Problem" in computer science; it is impossible to determine, in the general case if a program will or will not terminate.
So even though you can determine that the method will always reach one of your return statements, the compiler may not be able to do so.

It can find the return in the else clause. The problem is you need to have a return for all execution paths, even the one when posSymbol is equal to -1, since when posSymbol is equal to -1 you never enter the while loop.
Hence you need a return after the while statement.

Simply add a return 0; after the "//close while".

Not an answer, but here's a much safer version of the method with no static variables.
//Main calls this method
public static int getNumEmails(String completeText)
{
int posSymbol=0, count=0;
while(posSymbol!=(-1))
{
posSymbol=completeText.indexOf('#',posSymbol); //if there is no symbol, returns -1
if(posSymbol!=(-1))
{
++count;
++posSymbol;
}//close if
}//close while
return count;
}//close method

The Java compiler is not able statically (at compile-time) verify that the while loop gets executed at all (posSymbol could be -1 upon the first invocation). Hence the error.
In general it's not a good idea to keep looping state in member variables. What if more than one Thread executes your method (e.g. in a Webserver)? In the long run it's easier to track down bugs if your code does not modify global state:
public static int getNumEmails(String completeText) {
int count = 0;
Matcher m = Pattern.compile("#").matcher(completeText);
while (m.find()) {
count++;
}
return count;
}

Related

Why Return inside While Loop comes out of the Outer For Loop in Java

I am trying to solve a question which says: Write a function to find the longest common prefix string amongst an array of strings.
Input:
["baab","bacb","b","cbc"]
Inside while loop, if i use break it returns an empty string which is correct answer:
""
But if i use break, it returns:
"ba"
Below is my code:
class Solution {
public String longestCommonPrefix(String[] strs) {
String first=strs[0];
for(int i=1;i<=strs.length-1;i++){
char[] c1 = first.toCharArray();
char[] c2 = strs[i].toCharArray();
int index=0;
first="";
int len=0;
if(c1.length<c2.length)
len=c1.length;
else
len=c2.length;
if(len==0){
return first;
}
while(index<=len-1){
if(c1[index]==c2[index]){
first=first+c1[index];
}else{
**return first;**
}
index++;
}
}
return first;
}
}
As per my understanding, when we return inside a while loop(which is the inner loop here), it should come out of that particular loop and not from the outer for loop, similar to break.
Please help me understand why it is coming out of the for loop here.
As per my understanding, when we return inside a while loop(which is the inner loop here), it should come out of that particular loop and not from the outer for loop, similar to break.
That is a wrong assumption: according to the docs, the method returns when it reaches the return statement:
A method returns to the code that invoked it when it
completes all the statements in the method,
reaches a return statement, or
throws an exception (covered later),
whichever occurs first.
To break out of inner loops, see this question: How do I break out of nested loops in Java?

Java - How to identify whether a method executed completely or Returned

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
}

Is there any way I can return a value from a loop and continue from where I left off?

Is there any way I can return a value from a loop and continuing from where I left off ?
In the following snippet, I want to return the current value of currVm. But I am unable to do so.
In the innermost loop of the snippet :
while(c <= currVm) {
allocatedVm(currVm);
c++;
}
a function named allocatedVm is called. I want to return the value of currVm and start again from where I left off. Is there any way out ?
#Override
public int getNextAvailableVm() {
Set<String> dataCenters = confMap.keySet();
for (String dataCenter : dataCenters) {
LinkedList<DepConfAttr> list = confMap.get(dataCenter);
Collections.sort(list, new MemoryComparator());
int size = list.size() - 1;
int count = 0;
while(size >= 0) {
DepConfAttr dca = (DepConfAttr)list.get(count);
int currVm = dca.getVmCount();
int c = 0;
while(c <= currVm) {
allocatedVm(currVm); // RETURN currVm
c++;
}
count++;
size--;
}
}
}
The best approach would probably be to write a method returning an Iterable<Integer>. That's not as easy in Java as it is in languages which support generator functions (e.g. C# and Python) but it's still feasible. If the code is short, you can get away with a pair of (nested) anonymous inner classes:
public Iterable<Integer> foo() {
return new Iterable<Integer>() {
#Override public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
// Implement hasNext, next and remove here
};
}
};
}
In your case I'd be tempted to break it into a separate non-anonymous class though, just for simplicity.
Anyway, the point of using Iterable is that an Iterator naturally has state - that's its purpose, basically. So it's a good fit for your requirements.
Another rather simpler approach would be to return all of the elements in one go, and make the caller perform the allocation on demand. Obviously that doesn't work well if there could be a huge number of elements, but it would be easier to understand.
not sure i understand what you need, but:
if you wish to notify the caller of the method that you've got a value during the running of the method, but don't wish to exit the method just yet, you can use listeners.
just create an interface as a parameter to your function, and have a function inside that will have the object as a parameter.
example:
interface IGotValueListener
{
public void onGotValue(MyClass obj);
}
public int getNextAvailableVm(IGotValueListener listener)
{
...
if(listener!=null)
listener.onGotValue(...);
}
now , for calling the method, you do:
int finalResult=getNextAvailableVm(new IGotValueListener ()
{
... //implement onGotValue
};
You can return from anywhere in your method , by just putting the return keyword. If you want to put a functionality to resume ur method from different places then u need to factor ur method in that way. You can use labels and if statements, set some static variables to mark the last execution place. If your application is not multi-threaded then u need not to worry with the use of static variable synchronization. Also if your method is too big and becoming hard to follow/read, then think about breaking it into smaller ones.

Return int as boolean

I am a beginner so please bear with me. I decompiled the source code of a professional application. When I copied the source code into eclipse, an error came up with the following code( the error is with the return type):
public boolean method(){
...
...
for(int i = 0; ; i = 1){
return i;
}
How can I change the code to keep it correct but keep the functionality?
You can cast i as a boolean, or change return i; to return i != 0;, which will be true for all non-zero values of i, and false if i == 0.
As a side note, I really see no reason to wrap a return in a for loop. In this case, you might as well just replace both of those lines with return 0; (or return false;, to match the method signature).
Change the return type from boolean to int.
As you can see, your method is returning i which is declared as an int in the for loop, so the return type of your method has to be the same as the type of the variable it returns.

Why is this code giving an "unreachable code" error?

I can't seem to find a way to fix this problem. All i'm doing is declaring an integer and it's telling me that the code is unreachable.
private class myStack{
Object [] myStack = new Object[50];
private void push(Object a){
int count = 50;
while(count>0){
myStack[count]=myStack[count-1];
count--;
}
myStack[0]=a;
}
private Object pop(){
return myStack[0];
int count2 = 0; //Unreachable Code
}
}
Once you return from a method, you return to the method that called the method in the first place. Any statements you place after a return would be meaningless, as that is code that you can't reach without seriously violating the program counter (may not be possible in Java).
Quoting a comment on the question by Jim H.:
You returned from the pop() method. Anything after that is unreachable.
Unreachable code results in compiler error in Java.
In your program the line
int count2 = 0;
will never be reached since it is after the return statement.
Place this line above the return statement to work.
The simple explanation in plain English would be the following:
private Object pop(){
return myStack[0];
int count2 = 0; //Unreachable Code
}
method private Object pop(){} is looking for a return type Object and you just gave that return type by writing return myStack[0]; .So your method does not necessarily reach int count2 = 0; because it assumed that the method already reached its goal.
The last statement in the function should be a return statement.
Linting tools would flag it since it messes with the allocation of new memory after the counter scope ends.
Declare before return myStack[0] that fixes

Categories

Resources