StringBuilder loop: Local variable may not have been initialized - java

I have the following method that normalises a given XML tag name:
public static String normaliseTagName(String tagName) {
// Return a given empty tag name.
if (tagName.length() == 0) {
return tagName;
}
// Replace invalid start.
if (isInvalidXMLStart(tagName.charAt(0))) {
tagName = XML_REPLACEMENT + tagName;
}
// Replace invalid characters.
StringBuilder normalised;
boolean invalidFound = false;
for (int i = 0; i < tagName.length(); i++) {
if (isInvalidXMLChar(tagName.charAt(i))) {
if (!invalidFound) {
normalised = new StringBuilder(tagName.substring(0, i));
invalidFound = true;
}
normalised.append(XML_REPLACEMENT); // COMPILER ERROR
} else if (invalidFound) {
normalised.append(tagName.charAt(i)); // COMPILER ERROR
}
}
return invalidFound ? normalised.toString() : tagName; // COMPILER ERROR
}
I don't want to initialise the StringBuilder normalised before I'm sure to use it. In other words, I want to only initialise it when an invalid XML character is found.
I get The local variable normalised may not have been initialized errors where indicated, and I'm puzzled as to why the compiler is telling me that when normalised is clearly never used uninitialised.
Am I missing something or is the compiler unable to determine the initialisation path of the StringBuilder normalised in this situation?
If this compilation error cannot be avoided, how can I modify this code so that I initialise the StringBuilder only when I need it?
Thanks!

You need to explicitly initialize your local variable:
StringBuilder normalised = null;
... or ...
StringBuilder normalised = new StringBuilder();
... before referencing it.
Some of the pathways in your code reference normalised prior to its initialization:
normalised.append(...
Local variables are not automatically initialized as would, instance fields.

Related

How to get Path variable in spring filter or java

I want to get {testId : 111} from /v1/testId/111 example URL.
I know that it is very simple to get path variable if using the request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) method.
But, filters are executed before Servlets.
Therefore, request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) method is not available.
(ref. How to get Path Variables in Spring Filter?)
Is there any way to retrieve Path Variable within the filter?
Or, Is there any way to retrieve Path Variable without request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) method?
The String of /v1/testId/111 is actually available and I intend to extract 111 from it.
You are looking for lastIndexOf, a method of String.
String foo = "/v1/testId/111";
String theValue = foo.substring(foo.lastIndexOf("/") + 1);
lastIndexOf returns the numerical position of the last slash in this case and getting the substring from the next numerical position will effectively return everything you have after the last slash.
EDIT
If you have more instances, like /v1/testId/111/userId/222, then you could split your String, like
String string = "/v1/testId/111/userId/222";
String[] parts = string.split("/");
for (int index = 0; index < parts.length; index++) {
if (isNumeric(parts(index))) {
//Do something with these values as you please
String entityName = parts[index - 1];
String entityValue = parts[index];
}
}
isNumeric is implemented as such:
public static boolean isNumeric(String strNum) {
if ((strNum == null) || (strNum.equals(""))) {
return false;
}
try {
double d = Double.parseDouble(strNum);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
Courtesy to https://www.baeldung.com/java-check-string-number

Java - "local variable is not used"

I have this problem where I initialize a variable outside of a forloop. And then inside of the forloop try to update the value of this variable but everytime I "local variable not used". I tried a simple example (below) and the problem is still there. Ret is highlighted in my compiler and the error message is displayed. I don't understand why I can't access variables inside my loops anymore. Is this possibly due to me missing a bracket somewhere in my methods somewhere else in the class?
public static String test(String input) {
String ret = "";
for(int i=0;i<5; i++) {
ret += "m";
}
return "";
}
I was wondering if someone could help me with this. I would really appreciate it. Thanks!
You get this error message because you are building the ret variable but you are not using it. For example if you use the variable in an if statement you will not get the error anymore.
public static String test(String input) {
String ret = "";
for(int i=0;i<5; i++) {
ret += "m";
}
if (ret.equals("mmmmm")){
ret +="";
}
return "";
}
I suspect your IDE or compiler is noticing that you build up text in the local var ret but you never use that text. That built-up text is discarded, and you return an empty string. Your tools are alerting you to this nonsense.
Also, you make no use of the argument passed to your static method, more nonsense.

dumping or printing the name of a variable

This question mentions xpaths but it is really not specific to xpaths and really concerns any Java Strings.
I am using Java 8 and have about 40 Strings (public static final String in the class). An example is below:
private static final String employeeID_x = "//input[#id = 'id']";
private static final String employeeName = "//input[#id = 'EmployeeName']";
and there are some more complicated ones like
private static final String age_x = "//div[#id = 'Employee']/div[2]/span[1]";
etc. There are 40 of these. I want to verify all the xpaths so I made an array like
private static final String[] arr = {employeeID_x, employeeName_x, age_x, .....};
then to verify
for (String xp: arr) {
List<WebElement> eles = driver.findElement(By.xpath(xp));
if (eles.size() == 0) {
System.out.println(xp + " does not exist");
}
}
you get the idea. This works, but the error message is
"//div[#id = 'Employee']/div[2]/span[1] does not exist". I guess this is ok but I would rather have it say "age_x does not exist".
I don't know how to print the variable name. I have tried using Class and getFields() but that does not seem to work.
What I have to do is duplicate the array and put each element in quotes like this:
private static final String[] names= {"employeeID_x", "employeeName_x", "age_x", .....};
and then get the number of entries and use
for (int i = 0; i < arr.length; i++) {
String xp = arr[i];
String name = names[i];
List<WebElement> eles = driver.findElements(By.xpath(xp));
if (eles.size() == 0) {
System.out.println(name + " does not exist");
}
}
but as you can see this can get to be a pain. Is there anyway to get the name from xp? Maybe no, as I am afraid when it creates the array it substitutes the value of each string?
And as you can see, this is not specific to xpaths.
I don't know how to print the variable name.
With your current array, you can't (reasonably*) unless you can infer the variable name from the string. This line:
private static final String[] arr = {employeeID_x, employeeName_x, age_x, .....};
...copies the value of employeeID_x, etc., into the array. There is no ongoing link between that value and the variable it came from, just as in this code:
a = b;
...there is no ongoing link between a and b.
Your parallel arrays solution works but as you've said isn't ideal. Using a Map may be slightly better:
private static final Map<String, String> map = new HashMap<>();
static {
map.put("employeeID_x", employeeID_x);
map.put("employeeName_x", "employeeName_x);
// ...
}
Then loop through the map's entries, which give you both the name and value. This still has some repetition (e.g., in each put call you have to type the variable name twice), but it's much better from a maintenance perspective: Dramatically harder to get the two out of sync.
Another option is to use reflection: Your array would be of the names of the variables, and then you'd get the variable's value by using Class#getDeclaredField to get a Field instance for it, then get the value via Field#get. E.g., your array would be:
private static final String[] arr = new String[] { "employeeID_x", "employeeName" /*, ...*/ };
...then:
for (String name : names) {
Field f = YourClass.class.getDeclaredField(name);
String value = (String)f.get(null);
// ...test `value` here, report `name` if there's a problem
}
* "reasonably" - You could have the error code compare the string to every one of your fields and report the match, e.g.
if (theString.equals(employeeID_x)) {
theVariableName = "employeeID_x";
} else if (theString.equals(employeeName_x)) {
theVariableName = "employeeName_x";
} else if (...) {
// ...
...but...blech. :-) (And it assumes that two of these never have the same value.)

String concatenation - Boolean hard-coded Vs Boolean Concatenation with String

I need a advice (both in java & .net) for the following piece of code.
public void method(bool value)
{
String someString;
//some code
if (value)
{
//some code
...
someString = "one" + value;
}
else
{
//some code
...
someString = "two" + value;
}
}
Which one is advisable and why? either code like above or code like
someString = "onetrue";
someString = "twofalse";
After compilation and optimization by JDK, method will look like:
public static String method(boolean value) {
String someString;
if (value) {
StringBuilder sb = new StringBuilder();
sb.append("one");
sb.append(value);
someString = sb.toString();
} else {
StringBuilder sb = new StringBuilder();
sb.append("two");
sb.append(value);
someString = sb.toString();
}
return someString;
}
If this code is invoked very frequently, it could bring a performance impact, compared to the second version. In each case a new StringBuilder is constructed and three methods are invoked on it. And boolean should be converted to an object before calling append. While in the second version we just return constant. Everything depends on how often this code is called.
Neither will make any difference it's purely style.
Since you have // some other code I'd just stick with the first. If you only had one line in each branch then either is ok.
At a high level they both are the same but if you look down at lower levels, I would advise to using the method:
someString = "onetrue";
someString = "twofalse";
This is because when you do "one" + value, the value is actually a bool and the toString() method of the bool object will be called to add to the string. Basically just adding another step opposed to just specifying what to add to the string.

Why does this code throw an exception?

import java.util.Scanner;
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan=new Scanner(System.in);
int i,j;
int count = 0;
int test=scan.nextInt();
String[] con=new String[test];
while(test>0)
{i=scan.nextInt();
j=scan.nextInt();
for(int k=i;k<=j;k++)
if(prime(k))
//***********the line below where i am getting nullpointer exception
con[count].concat(k+"\n");
test--;count++;}
for( i=0;i<con.length;i++)
System.out.printf("%s\n",con[i]);
}
private static boolean prime(int k) {
// TODO Auto-generated method stub
if(k==2)
return true;
if(k%2==0)
return false;
for(int l=3;l<=Math.sqrt(k);l=l+2)
if(k%l==0)
return false;
return true;
}
}
please somebody help me that how to get rid from this exception.
String[] con=new String[test]; creates a new String array with test elements, and assigns it to con. However, this does not create any String objects at all - you have simply created an array where all elements are null. You must ensure that con[count] actually refers to a String before calling concat() on it; you can either do this by checking if it is null and assigning "" to it before calling concat(), or you can have a separate loop that puts an empty string into each element of con.
By the way: concat() does not modify the String you call it on; it creates a new String and returns it, but you don't do anything with the return value, so it gets thrown away. You should use += instead (which also creates a new String, but it will assign the new String to the array element).
You are not initializing each element of con[]
new String[] gives you an array of null string references. You have to set them to the empty string if you want your code to work.
When you do
String[] con=new String[test];
you create a new String-array of length test. The elements in this array, however, start out being null. Therefore, you cannot call concat on them before initializing them to a string.
This means, you should initialize the string to the empty string, "", before doing calling concat on it.
In addition, strings are immutable, so concat produces a new String, rather than modifying the existing one, so you need to save the result.
This means, you all in all want something like:
while(test>0) {
i=scan.nextInt();
j=scan.nextInt();
con[count] = ""; // Initialize con[count]
for(int k=i;k<=j;k++) {
if(prime(k)) {
con[count] = con[count].concat(k+"\n");
}
}
test--;
count++;
}
Since you'r getting NullPointerException here,
con[count].concat(k+"\n");
it means that the value of con[count] is null and you are trying to call .concat( ) on the null instance.
Here, con[] is not initialized, so it takes null by default. You need to initialize the elements of con[] array i.e say to "" and then try calling the concat method.
It looks like conc[count] is null, if that's where you're getting a NullPointerException.
You should initialize it with a value.

Categories

Resources