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.)
Related
So, I have this problem:
#!/usr/bin/env groovy
package com.fsfs.fdfs.fsf.utils
class GlobalVars {
// TEST-DEV
static String MY_URL1 = "https://myurl.com"
static String MY_URL2 = "https://:6443"
static String MYURLS_TEST = "${MY_URL1} ${MY_URL2}"
}
So I want to iterate over my URLS depending on the environment.
For example: in this ENV is TEST, but could be DEV, PROD and so on
for( Name in GlobalVars."MYURLS_${ENV}".split(/\s+/)) {
}
I'm not sure how to achieve this.
Basically, I want to iterate over a variable with a dynamic name.
The variable contains at least 2 strings
You could do something like this...
class GlobalVars {
// TEST-DEV
static String MY_URL1 = "https://myurl.com"
static String MY_URL2 = "https://:6443"
static String MYURLS_TEST = "${MY_URL1} ${MY_URL2}"
}
String ENV = 'TEST'
for( name in GlobalVars."MYURLS_${ENV}".split(/\s+/)) {
println name
}
You can look into CharacterIterator methods current() to get the current character and next() to move forward by one position. StringCharacterIterator provides the implementation of CharacterIterator.
or for a simpler task can
Create a while loop that would check each index of the string or a for loop like this
for (int i = 0; i < str.length(); i++) {
// Print current character
System.out.print(str.charAt(i) + " ");
}
Iterating Strings works out of the box in Groovy:
"bla".each{println it}
.each{} closure will go over all characters of the string.
Same can be achieved with a more classical for-loop:
for(c in "foo") println c
Either way should work.
I'm not sure what would be the benefit of making a space separated list of values just to parse it again. Seems easier with a map of lists.
class GlobalVars {
// TEST-DEV
static String MY_URL1 = 'https://myurl.com'
static String MY_URL2 = 'https://:6443'
static Map MY_URLS = [
'TEST': [
MY_URL1,
MY_URL2,
],
]
}
String ENV = 'TEST'
GlobalVars.MY_URLS[ENV].each {
println it
}
No regex, no dynamically generated property names. If you want to avoid typos in the environment names you can put them into an enum.
So for example I have the following variables:
Var1, Var2, Var3, Var4, Var5 - a total of 5 variables.
All with unique data and I want to loop though them using a for loop.
//String Var1 = something, Var2 = something etc..
for (int i = 1; i <= 5; i++)
{
Var(i) = "something else";
}
//i.e I change Var(1), Var(2) etc.. to something else respectively.
To clarify further, ultimately I want to apply this method to iterate through multiple components in my program. I have a large number of components with styled names(e.g. label1, label2, label3 etc..) and want to change the value of these components without having to individually set their value.
You can do it with reflection, if the variables are defined as members of a class. For method parameters or local variables it is not possible. Something similar to this:
Class currentClass = getClass();
Field[] fields = currentClass.getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
If you intend to change the value it becomes a bit more complicated as you also have to consider the type of the variable. E.g. you can assign a String to a variable of type Object but not the other way around.
I would suggest to go for an array if data type of variables are same.
You can try something like that
String[] Var = {"something","something2","something else"};
for (String var : Var)
{
System.out.println(var);
}
As long as all the variables use the same type, you can use an Array to store all of them. Then you can use a for loop to iterate through the array. Something like this:
String[] V = {"var1","var2","var3","var4","var5"};
int arraylength = V.length;
for(int i = 0; i<arraylength; i++){
System.out.println(V[i]);
}
You can't loop through (local) variables. You can use an array or a List and then loop through its elements:
for (Object item : myListOfObjects) {
// do the processing
}
Using Java 8 Arrays it is as simple as:
Arrays.stream(varArray).forEach(System.out::println);
Usage:
public class LoopVariables {
public static void main(String[] args) {
String[] varArray = new String[]{"Var1", "Var2", "Var3", "Var4", "Var5"};
Arrays.stream(varArray).forEach(System.out::println);
}
}
Try This piece of Code.
public class Main {
public static void main(String[] args) {
Insan i1[]=new Insan[5];
i1[0].name="Ali";
i1[0].age=19;
i1[1].name="Pakize";
i1[1].age=29;
i1[2].name="Kojiro Hyuga";
i1[2].age=30;
i1[3].name="Optimus Prime";
i1[3].age=40;
for (int ib=0; ib < 4; ib++) {
System.out.println("Name: " + i1[ib].name + " Age: "+i1[ib].age);
}
}
}
I have inherited a Java program which I need to change. In one part of the code, I see I have created over 1000 String variables such as:
String field01
String field02
...
String field1000
I want to make a for loop to set all of the mentioned variables to "", but I am having issues with building a correct format for the for loop.
How do I create field+(i) in the for loop to set field01 to "" and the rest?
A for loop... Well, you could make this an array, but there's not really any way to make this into a for loop without an array.
Here's an example with one:
String[] test = new String[1000];
for (int number; numer < 1000; number++){
test[number] = "";
}
You have to use Reflection for doing the same.
class Test {
String field1
String field2
...
String field1000
}
public class FieldTest {
public static void main(String args[]) {
Test t = new Test();
Class cls = t.getClass();
for(int i=0 ; i<=1000; i++){
Field f1 = cls.getField("field"+i);
f1.set(t, "");
}
}
}
You can't really do this in Java. An alternative is to make a String array where the index of the array is the number of the variable that you want. So field01 would be stored in your string array at index 1.
First, create an array. Second, use Arrays.fill:
String[] fields = new String[1000];
Arrays.fill(fields, "");
Later you can access or modify individual variables by indices like fields[index].
Creating 1000 variables with similar names is not how people program in Java.
I know it is not the exact answer, but may help you.or you will need to use reflection.
Map<String, String> container = new HashMap<String, String>();
for (int i = 0; i <1000; i++) {
container.put("field"+ i, "\"\" ");
}
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[] ;
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>.