views:

133

answers:

6

Hello,

I am trying to construct method which returns a boolean:

public boolean isStringValid(String s){
 boolean isValid;
 String temp = null;  
 // only combinations of 'A','B','C' are allowed
 for (int i = 0; i < s.length(); i++)
 {
  temp = s.substring(i, i+1);
  if (temp.equals("A")|temp.equals("B")|temp.equals("C")){
   isValid= true;
  }else{
   isValid= false;
  }
 } 
 return isValid;
}

But I get a compiler error saying "the local variable isValid may not have been initialized".

What I am trying to do is take a string and examine its every letter, if any letter other than A, B or C is found in the string, the isStringValid method should return a false. Only after every letter is checked and found to be either A,B or C can the method return true.

I guess I am having trouble figuring out the scope of the local variables. What is the appropriate way for the method to return from within the if/else blocks? If that is not possible, what would you recommend is the best way to design this?

Thank you in avdance Kindest regards

+2  A: 

Perhaps the for may actually not loop. so isValid is not set.

Macarse
+10  A: 

What happens if you get an empty string as argument?

The compiler needs to be sure you're always returning something. Initialize your isValid variable with false, this way if the method gets an empty string it would just return the default value.

boolean isValid = false;

In Java you can't return a variable that may not be initialized, just be sure in all possible flows the variable is set with any value.

UPDATE: This will solve your question but I suggest you to take a look to the answers below because your method's logic isn't correct

victor hugo
it would be good to point out that this pertains to local variables only. you can declare and not initialize instance variables and the compiler will not complain when your code attempts to use them.
akf
+2  A: 

The method is wrong (besides the compiler error, which Victor explained). If the last letter is C and everything else is D it will return true. Also, you should use char, and you need two bars (||) for logical or. Try:

public boolean isStringValid(String s){             
            // only combinations of 'A','B','C' are allowed
            for (int i = 0; i < s.length(); i++)
            {
                    char tempChar = s.charAt(i);
                    if (!(tempChar == 'A' 
                       || tempChar == 'B' 
                       || tempChar == 'C'))
                        return false;
            }       
            return true;
}

If you want to return false for empty strings, do that up in the beginning:

if(s.length() == 0)
  return false;
Matthew Flaschen
char is not an object, how are you calling equals on it?
Tom
You're right, Tom. That's what I get for testing in bsh. Fixed now.
Matthew Flaschen
A: 

The variable isValid is a local variable. In the Java Language spec:

A local variable (§14.4, §14.13) must be explicitly given a value before it is used, by either initialization (§14.4) or assignment (§15.26), in a way that can be verified by the compiler using the rules for definite assignment.

See section 4.5.5 Initial Values of Variables in the Java Language Specification:

http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html

Initialise the variable to false to start off with and then only set it to true in the correct part of your method, i.e. here:

if (temp.equals("A")|temp.equals("B")|temp.equals("C")){
   isValid = true;
}

Remove the else statement and let the method return as normal.

Jon
A: 

I agree with the answers that state that you should initialize the isValid boolean variable.

However, you could do what you want with a regular expression

/*
* returns false if s contains a character different from 'a' 'b' or 'c' 
*/
public boolean isStringValid(String s){
     return !Pattern.matches("($^|[^abc]+)",s);
}

[abc] means that you are checking if s contains the 'a','b' or 'c' character

[^abc] means that you are checking if s contains a character that´s none of 'a','b' or 'c'.

[^abc]+ means that you are checking if s contains at least one character that´s none of 'a','b' or 'c'.

$^ Means empty strings

Tom
in fact, you don't need the "+", since you are just testing if the pattern matches (which already implies "one or more times")
newacct
@Tom: wrong regex. "[^abc]+" means a sequence of one or more characters that are not 'a', 'b' or 'c'. Since you are using matches(), the whole text must match the regex. Try with "axa": it returns false despite it "contains at least one character that´s none of 'a','b' or 'c'".CORRECT: return Pattern.matches("[ABC]*", s); // true as long as the String does not contain any character that is not 'A', 'B' or 'C'
Carlos Heuberger
Thanks Tom and Carols. However Pattern.matches("[ABC]*", s); returns true for an empty String. Would there be a way for regex pattern to include this? i.e. If string is empty, return false. I tried all the proposed solutions and they work. I like this one because of its brevity. Thanks again
denchr
@denchr> Try with Pattern.matches("[^abc]+",s). The '*' means 0 or more.
Tom
A: 

Note that your loop will only return true or false depending on the last char in your string. What you want to do is something like

public boolean isStringValid(String s) {
  for (char c : s.toCharArray()) {
    if (!('A' == c || 'B' == c || 'C' == c)) { 
      return false;
    }
  }       
  return true;
}
Jorn