How will I be able to retrieve the value of a variable which has a dynamic name
For Example I have list of constants
public class Constant{
public static final String S_R = "Standard(240)";
public static final String S_W = "Standard(180)";
public static final String L_R = "Large(360)";
public static final String L_W = "Large(280)";
}
Based on database I build a variable name
String varName = "S" + "_" +"R"; // This can be S_R , S_W , L_R or L_W
String varVal = // How do i get value of S_R
Use a normal HashMap with variable names as strings against their values. Or use a EnumMap with enums as key and your value as values. AFAIK, that's the closest you can get when using Java. Sure, you can mess around with reflection but IMO the map approach is much more logical.
You can use a Map<String, String> and locate the value by its key.
Even better, you can have an enum:
public enum Foo {
S_R("Standard", 240),
S_W("Standard", 180),...;
private String type;
private String duration;
// constructor and getters
}
And then call Foo.valueOf(name)
(You can also do this via reflection - Constants.class.getField(fieldName) and then call field.get(null) (null for static). But that's not really a good approach.)
If you really must do this (and it's unlikely), you would have to use the Java "reflection" APIs.
Related
This question already has answers here:
Java: Getter and setter faster than direct access?
(3 answers)
Closed last year.
I have the below class with around 200 variables.
public class BaseDataDTO {
private CSVRecord rawData;
private List<InquiriesDataDTO> inquiriesData;
private ListTradesDataDTO> tradesData;
private List<CollectionsDataDTO> collectionsData;
private Long applicantId;
//cvv attributes
public String adg001;
private String adg002;
private String adg003;
private String adg004;
private String apg05;
-
-
private String apg199;
}
From a different class, I would like to access the instance variables through the variable names, is it possible to do? I need to do this since I need compare some another response with the instance variable of that class through a Map key. How can I achieve some thing to the effect of the text in bold below?
I do not want to use getter methods here since it is in a for loop for 200 times.
BaseDataDTO baseData = CSVParser.parseBaseData(fileName);
Map<String, String> attributes = fileLoader.withName("attributes.json").jsonToObject(Map.class);
for (String key : attributes.keySet()) {
String responseValue = response.getModelScores().get(0).getScoringInput().get("function_input").get(key).asText();
String expValue = baseData.get(key));
AssertEquals(responseValue, expValue);
}
Create a BaseDataDTO from your Map and check for equality via equals.
Never ever access object fields by their name string, unless you are writing low level libraries like parsers.
Accessing fields by name is done via Reflection:
String expValue = (String) BaseDataDTO.class.getDeclaredField(key).get(baseData)
Note that stuff like this is at least an order of magnitude slower than using a getter.
I have one java class like below:
public class Location
{
public String city;
public String state;
public String country;
public enum type{Beach,Forest,Hills,Desert};
}
as above type member is enum type and i want to assign multiple enum values to type proprties like one Location object has more then one type properties like it has Hills as well as Forest.
then how should i have to do it?
where to declare enum and how to assign to enum values to one object.
Is it possible to assign to enum values one object without using array?
You need a Collection to store a variable number of values. Since you don't want to have duplicates use a Set. For enums exist java.util.EnumSet which has a compact and efficient way to store multiple values:
public class Location
{
public enum Type {Beach,Forest,Hills,Desert};
public String city;
public String state;
public String country;
public EnumSet<Type> types = EnumSet.noneOf(Type.class); // start with empty set
}
You can store them in class variables:
private final Terrain first = Terrain.BEACH;
private final Terrain second = Terrain.DESERT;
Similarly, you can store them in a collection of terrains if that is more appropriate:
private final Set<Terrain> terrains = new HashSet<>(Arrays.asList(Terrain.BEACH, Terrain.DESERT));
Or use an EnumSet:
private final EnumSet<Terrain> terrains = EnumSet.of(Terrain.BEACH, Terrain.DESERT);
On a side note, it is more conventional to declare enumerations in their own file, I have assumed that it will be called Terrain. Also, constants (thus also enum values) are usually written in capital letters.
I have one Java constant file which contains around 1000 records and all are String type only
e.g.
public static String PF_EMPLOYER = "PF-Employer";
public static String ESI_EMPLOYER = "ESI-Employer";
public static String TOTAL_CTC = "Total CTC";
public static String INCENTIVE = "Incentive";
public static String PF_EMPLOYEE = "PF-Employee";
public static String ESI_EMPLOYEE = "ESI-Employee";
==and so on could be more than 1000=======
I just want all this String values in static ArrayList or HashMap where Integer in HashMap will be 0,1,2,3....1000.
I am stuck to find out any Effective way to complete this task, Even if Spring is providing any solution I am also ready to go with it.
Its not possible for me to Move Constant file content in any Properties file.
Note that I am using JDK 7 not possible to go for JDK 8.
If I correctly understand your requirement, the only natural way of doing what you want should be using reflection. If you class name was ConstClass it could be something like :
HashMap<String, String> map = new HashMap<>();
for (Field field: ConstClass.class.getFields()) {
if (String.class.isAssignableFrom(field.getType())) {
int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers)) {
map.put(field.getName(), (String) field.get(ConstClass.class));
}
}
}
That you get in map all fields containing static String.
I'm looking for a tool which will allow me use command-line-style (preferably POSIX) strings to initialize an object' properties and attributes.
For example, you'd provide it with String input formatted like so:
String input = "--firstName=John --MiddleName=\"Louis Victor\" --lastName=Smith";
... and it would setFirstName("John"), setMiddleName("Louis Victor") and setLastName("Smith") on a given object. (which could be a JavaBean)
Please note that the input is a single String, not an array String[] as is the case with many popular CLI argument "parsers".
This is all similar to args4j but I couldn't get that to work... and I'm hoping to avoid using #annotations.
Does anyone have code/libraries/tools which could accomplish this?
For your use case, forget regular CLI parsers, you need a custom-tailored solution. If you really have such a simple argument syntax (parameters always begin with --, no occurrences of -- in the parameter values), you can use a simple Guava-based solution like this class:
Parse the String Arguments
public class ArgParser{
// split on (optional whitespace) + "--"
private final Splitter paramSplitter = Splitter.on(
Pattern.compile("\\s*\\-{2}")).omitEmptyStrings();
// find key=value (with optional double quotes around value)
private final Pattern keyValuePattern = Pattern
.compile("(.+?)=\"?(.*?)\"?$");
public Map<String, String> getParamValues(final String posixString){
final Map<String, String> paramValues = Maps.newLinkedHashMap();
Matcher matcher;
for(final String param : paramSplitter.split(posixString)){
matcher = keyValuePattern.matcher(param);
if(!matcher.find()){
throw new IllegalArgumentException("Bad parameter: " + param);
}
paramValues.put(matcher.group(1), matcher.group(2));
}
return paramValues;
}
}
Usage
final String input =
"--firstName=John --middleName=\"Louis Victor\" --lastName=Smith";
System.out.println(new ArgParser().getParamValues(input));
Output
{firstName=John, middleName=Louis Victor, lastName=Smith}
Now you can take the map and use it with a Bean library like commons-beanutils (I prefer the Spring BeanWrapper personally, but that only makes sense if you use Spring anyway)
Define the Bean Class
Any way, I'll use this value holder class:
public class Name{
private String firstName;
private String middleName;
private String lastName;
#Override
public String toString(){
return Objects
.toStringHelper(this)
.add("first name", firstName)
.add("middle name", middleName)
.add("last name", lastName)
.toString();
}
// + getters & setters
}
Set the Bean Properties
Now we'll use BeanUtils.populate(Object, Map) to apply the parameter values, like this:
final String input =
"--firstName=John --middleName=\"Louis Victor\" --lastName=Smith";
final Map<String, String> paramValues =
new ArgParser().getParamValues(input);
final Name name = new Name();
BeanUtils.populate(name, paramValues);
System.out.println(name);
Output:
Name{first name=John, middle name=Louis Victor, last name=Smith}
Caveat: Supported Property Types
BeanUtils.populate() supports setting the following property types:
... String, boolean, int, long, float, and double.
In addition, array setters for these
types (or the corresponding primitive
types) can also be identified.
Source: BeanUtilsBean.populate(Object, Map)
If you need parameter conversion beyond that, you should probably look into using the Spring BeanWrapper after all, it's extremely powerful, has many built-in property editors and you can add custom property editors. Just change the code like this:
final Name name = new Name();
final BeanWrapper wrapper = new BeanWrapperImpl(name);
wrapper.setPropertyValues(paramValues);
Reference:
BeanWrapper
PropertyAccessor.setPropertyValues(Map)
If I understand correctly, you are looking for a Java library to parse POSIX-style command line parameters. I used JSAP some time ago and it was really cool (it was using XML configuration back then).
This
-firstName John -lastName Smith
is no POSIX, you mean
--firstName John --lastName Smith
This may be the reason, why you can't get it working.
Update:
As I look at the example, it doesn't look like it could be the reason.
I have an abstract class as follows. I want to get all the values of member variables.
public abstract class PARAMS {
public static final String NAME1 = "VAL1";
public static final String NAME2 = "VAL2";
public static final String NAME3 = "VAL3";
}
The values are retrieved using reflection as follows.
Field[] fields = PARAMS.class.getFields();
for (Field field : fields) {
String name = field.getName() ;
String value = (String) field.get(name);
}
This is the first time I am experimenting with reflection. Is this a correct way to achieve the goal? I would like to know what are the pitfalls in using reflection in this case.
You code iterates over both static and private fields. So you should check that you iterate over static fields only.
for (Field field : PARAMS.class.getFields()) {
if (Modifiered.isStatic(field.getModifiers())) continue;
String name = field.getName() ;
String value = (String) field.get(PARAMS.class);
}
NB: as Jon mentioned, for static field access the instance parameter is ignored. However, I prefer passing in the class instead of null since this is a better documentation of the indent.
It is however even better practice to annotate your fields with an annotation so that you only get those fields that you really want no other static fields added by other programmers (or even the Java language behind the scenes). If you do so, your code would look like
for (Field field : PARAMS.class.getFields()) {
if (!field.isAnnotationsPresent(YourAnnotation.class)) continue;
String name = field.getName() ;
String value = (String) field.get(PARAMS.class);
}
It's not quite correct - the argument to get should ideally be null for the sake of readability: the point of that argument is to give it a target for when you're retrieving instance fields.
So your code can be just:
Field[] fields = PARAMS.class.getFields();
for (Field field : fields) {
String name = field.getName() ;
String value = (String) field.get(null);
}
Now, this should work... but what are you going to do with these values? Is there any reason why you want to do this rather than creating an immutable Map<String, String> which is exposed directly?
Reflection is fine where it's necessary, but you haven't given enough information to determine whether it's actually necessary in this case.
another problem, getFields return all accessible fields (static or not) of this class and all its superclasses. Not a problem for the specific code you posted, since the only superclass is Object which has no public field.
I would at least test if the field is declared in the correct class - getDeclaringClass() - and if it has the correct return type - getType().
Using an Annotation, as Adrian suggested, is best IMHO.