Regarding String array declaration - java

I have the below String assignment statement
String items[] = line.split("\",\"",15);
String fileNamet = items[1].replaceAll("\"","").trim();
I need to introduce a new if statement
if (valid) {
String items[] = line.split("\",\"",15);
} else {
String items[] = line.split("\",\"",16);
}
String fileNamet = items[1].replaceAll("\"","").trim();
Now items becomes local to the if loop and is giving me compilation errors. How can I declare the items array outside the if loop?

This is the kinds of scenarios where the ternary operator excels at (JLS 15.25 Conditional Operator ?:)
String[] items = line.split("\",\"", (valid ? 15 : 16));
No code is repeated, and once you get used to it, it reads much better.
That said, you can also pull out the declaration outside of the if if that's what you're more comfortable with.
String[] items;
if (valid) {
items = line.split("\",\"",15);
} else {
items = line.split("\",\"",16);
}

Declare it outside:
String items[];
if (valid) {
items = line.split("\",\"",15);
} else {
items = line.split("\",\"",16);
}
String fileNamet = items[1].replaceAll("\"","").trim();

Related

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.)

Minimise if else conditions in method

I have the following class.
public enum EnumService
{
ONE, TWO, THREE, FOUR,.............HUNDRED;
//Values till HUNDRED
public static EnumService returnMockService(String request)
{
//some string match
if(request.matches("/abc*")){
return ONE;
}
//some other string is match
else if(request.matches("/bcd*"))
return TWO;
else if(request.matches("/decf*"))
return THREE;
//many else if conditions
else if(request.matches("/wxyz*"))
return HUNDRED;
return null;
}
}
The code is not standard with more if else statements.
I want to minimize the number of if calls in above method yet maintaining the return type as EnumService
Any better option to do this.
It would be great if some can help me in making it clean.
First: no need to else if you return.
Second: you can optimize it a LOT if you use this string as a parameter in the enum:
public enum EnumService
{
ONE("abc*"),
// etc
private static final Map<Pattern, EnumService> MAPPING
= new HashMap<>();
static {
for (final EnumService svc: values())
MAPPING.put(svc.pattern, svc);
}
private final Pattern pattern;
EnumService(final String s)
{
pattern = Pattern.compile(s);
}
public static EnumService returnMockService(String request)
{
for (final Map.Entry<Pattern, EnumService> entry: MAPPING.entrySet())
if (entry.getKey().matcher(request).matches())
return entry.getValue();
return null;
}
}
I would put the strings that you're matching along with the EnumService value they should map to into an array of simple objects, then loop through the array.
E.g.:
ArrayEntry[] entries = new ArrayEntry[] {
new ArrayEntry("/abc*", EnumService.ONE),
// ...and so on...
};
and then:
for (ArrayEntry entry : entries) {
if (request.matches(entry.str)) {
return entry.value;
}
}
return null;
...where ArrayEntry is just a simple class with those two properties (str and value).
If you don't want to have ArrayEntry, you can use a Map:
Map<String,EnumService> entries = new HashMap<String,EnumService>();
entries.put("/abc*", EnumService.ONE);
//...and so on...
and then
for (Map.Entry<String,EnumService> entry : entries.entrySet()) {
if (request.matches(entry.getKey())) {
return entry.getValue();
}
}
return null;
Or you can do it with parallel arrays instead:
String[] strings = new String[] { "/abc*", /*...and so on...*/ };
EnumService[] values = new EnumService[] { EnumService.ONE, /*...and so on...*/ };
and then
int n;
for (n = 0; n < strings.length; ++n) {
if (request.matches(strings[n])) {
return values[n];
}
}
return null;
But parallel arrays tend to be a bit of a maintenance issue.
You can go for design patterns, best for these kind of things are state pattern. State Pattern is to solve this kind of issues and make the code more compatible & flexible. Look over this http://www.javacodegeeks.com/2013/08/state-design-pattern-in-java-example-tutorial.html
Have a look at the below link.
Why can't I switch on a String?
As stated there, if you are using jdk 7, just use switch on the strings. If not, create an enum of /abc*,/bcd*,etc. and use them in switch.
Hope this helps.
Or you could always, store them in an array and loop through them. That would be much easier but costs an extra array.
If there is no logic to map /abc to ONE and /bcd to TWO etc, then maybe you need to load these into an array or map, then simply get the index of the array where it matches.
myMap.put("abc", ONE);
myMap.put("bcd", TWO);

String array cannot be resolved as variable

Is it possible in Java to redefine value after it already been defined(Like in JavaScript)? Take a look at my sample code, I am trying to redefine String array.
public String[] checkIfLengEnglish (){
String language = Locale.getDefault().getDisplayLanguage() ;
String LG = Locale.getDefault().getLanguage();
if(LG.contains("en")){
String language[] = {"English"}; // Redefining
}
else {
String Language[] = {"English/"+ Language,Language,"English"}; // Redefining
}
return Language[];
}
you re-define Language in your code with multiple types at multiple scopes (once at the method level, twice in the if-block/else-block). Don't do that.
You don't need to add the [] to reference an array variable, don't do that.
Since you declare the array inside the if-block, it only exists inside the if-block. To fix this, you need to declare it outside:
String[] languages;
if( LG.contains("en")){
languages = new String[] {"English"};
}else {
languages = new String[] {"English/"+ Language,Language,"English"};
}
return languages;
Since you no longer use initalization (which can only happen when you declare a variable) but assignment, you need to use the "long form" for specifying the array values, which includes new String[].
Also note that as a general guideline, method and variable names should start with a lower-case letter and class/interface/enum names should start with a capital letter. That's not technically required, but following this guideline will make your code easier to understand for others.
just reframing your code & variables for better understanding purpose
public String[] CheckIfLengEnglish (){
String displayLanguage = Locale.getDefault().getDisplayLanguage() ;
String LG = Locale.getDefault().getLanguage();
String arrayLanguages[];
if( LG.contains("en")){
arrayLanguages = {"English"};
}else {
arrayLanguages = {"English/"+ Language,Language,"English"};
}
return arrayLanguages ;
}
Language[] is defined inside your if/else statement. You should try putting it above that like
String[] array = new String[];
if(true){
array = {"English"};
}
return array;
// dummy example
String[] Language=new String[];
if
{
Language={"English"}
}
else {
String Language[] = {"English/"+ Language,Language,"English"};
}
return Language[] ;

NullPointerException while indexing variable String parameters

I'm new to the idea of using an ellipsis. I'm almost certain my error is caused by improperly declaring or initializing "String[] authors", but I don't know how to do this an still have my setAuthors method work.
import java.util.*;
public class Book {
private String[] authors; //I'm guessing this line should end with "= new String..."
//but not sure how to w/o specifying an array dimension
private int authorsSize;
//Receives variable # of String parameters and indices them into String[] "authors"
public void setAuthors(String... authors) {
authorsSize = authors.length;
for(int i=0;i<authorsSize;i++)
this.authors[i] = authors[i];
}
//getAuthors method:
public String getAuthors(){
String s = "";
authorsSize = authors.length;
for(int i=0;i<authorsSize;i++)
s = s+authors[i] + ", ";
printAuthors = s;
return s;
}
The simplest approach would just be to clone the array:
public void setAuthors(String... authors){
this.authors = (String[]) authors.clone();
}
After all, you're overwriting the previous data anyway, and you can't know the size before the method call. You don't need the authorsSize variable at this point - you've got the authors array which knows its own length.
(If you were able to use immutable collections, you wouldn't even need to bother cloning, of course.)
EDIT: As noted in comments, this method will throw an exception if you pass in a null reference. You shouldn't automatically decide that this is a situation you should "handle" - it's entirely legitimate to document that the parameter must not be null. I would suggest documenting the behaviour around nullity either way.
Indeed, if you do this you might also want to initialize your instance field like this:
private String[] authors = new String[0];
That way you always know you'll have a non-null reference in that field, so you can use it with impunity. I would prefer this over having to check for null on every use.
you never initialized authors your array .
you need to initialize it before you use it .
String[] authors = new String[size];
//but not sure how to w/o specifying an array dimension
The best way is to use an List implementing classes as they are dynamic Arrays. i.e., you dont need to specify the size.
List<String> authors = new ArrayList<String>();
You have to currect your setAuthors method as described below
public void setAuthors(String... authors) {
if (authors != null && authors.length > 0) {
authorsSize = authors.length;
authors = new String[authorsSize];
for (int i = 0; i < authorsSize; i++)
this.authors[i] = authors[i];
}else{
this.authors = null;
}
}
Because the declaration of "private String[] authors" is before that of "public void setAuthors(String... authors)", you can not use the format like "String[] authors = new String[authorsSize]". This will make the size of authors always be 0.
The better way is to use the dynamic initialization:
List authors = new ArrayList();
Then use this.authors.add(authors[i]) to pass parameters.
you could also adjust your code like so:
import java.util.*;
public class Book{
private String[] authors;
private int authorsSize;
public void setAuthors(String... authors){
//check for null, you could also set this.authors = new String[] if you prefer.
if(authors == null){
this.authors = null;
}else{
authorsSize = authors.length;
//also add this line...
this.authors = new String[authorsSize];
for(int i=0;i<authorsSize;i++)
this.authors[i] = authors[i];
}
}
public String getAuthors(){
if(authors == null){
return ""; //could also return null here if you would prefer
}
StringBuilder s = new StringBuilder();
authorsSize = authors.length;
for(int i=0;i<authorsSize;i++){
if(i > 0)
s.append(",");
s.append(authors[i]);
}
//printAuthors = s;
return s.toString();
}
}

Variable might not have been initialized when dealing with array

In a method I created I am trying to create is meant to return an array of user inputted strings. The issue that I am having it the compiler is saying that userData may not be initialized at userData[i]=tempData; and at return userData;. I am unsure why this error is occuring, and would like some feedback.
public String[] getStringObj() {
int i = 0;
String tempData;
String[] userData;
Boolean exitLoop = false;
System.out.println("Please list your values below, separating each item using the return key. To exit the input process please type in ! as your item.");
do {
tempData = IO.readString();
if (tempData.equals("!")) {
exitLoop=true;
} else {
userData[i] = tempData;
i++;
}
} while (exitLoop == false);
return userData;
}
In the interests of improving code quality:
You don't need that exitLoop flag; just do
while(true) {
String input = IO.readString();
if(input.equals("!")) {
break;
}
/* rest of code */
}
Since you seem like you want to just add stuff to an array without bounds, use an ArrayList instead of an array (added bonus, this gets rid of i too):
List<String> userData = new ArrayList<String>();
...
userData.add(line);
If you do these two things, your code will be much more concise and easy to follow.
Your userData is not initilaized and you are attempting to use it here userData[i]=tempData; before initialization.
Initialize it as
String[] userData = new String[20];
//20 is the size of array that I specified, you can specify yours
Also in your while condition you can have while(!exitLoop) instead of while(exitLoop==false)
You didn't initialize the String[]. Just do String[] userData = new String[length]. If you are unsure of the length, you may just want to use an ArrayList<String>.

Categories

Resources