How to use the value of a String as a variable name - java

My question is suppose there is a String variable like String abc="Shini";.
So is it possible to use "Shini" as new variable name by some automatic means not by explicit typing.
String abc = "Shini";
String Shini = "somevale";

Variables must be declared at compile time, so no it is not possibile at runtime
Best thing it comes to my mind is to use it as a map key
String abc = "Shini";
Map<String, String> myMap = new Hashmap<>();
myMap.put(abc, "something");
Then myMap.get("Shini") will give "something".

Yes. You can use.
class Foo {
private int lorem;
private int ipsum;
public Foo(){}
public setAttribute(String attr, int val) throws NoSuchFieldException, IllegalAccessException {
Field field = getClass().getDeclaredField(attr);
field.setInt(this, val);
}
public static void main(String [] args) {
Foo f = new Foo();
f.setAttribute("lorem", 1);
f.setAttribute("ipsum", 2);
}
}
I did not compile this code. Please check if this can have minor mistakes.

Related

should I use strategy pattern, If I have hundreds of actions

I have a class doing translate job. But it have hundreds of specific translate methods! The action code determine which method will be used! I want to use strategy pattern, but it will create hundreds of sub class! I want to name the methods end of action code and use reflection to do the translate, but I'm concern abort the execution performances. It will be called very frequently! What design pattern or patterns should I use to solve this problem!
code like this:
public class Test003_Translate {
private static final String PREFIX = "translate";
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Test003_Translate translate = new Test003_Translate();
Map<String, String> map = new HashMap<>();
map.put("key001", "001");
map.put("key002", "002");
map.put("key003", "003");
translate.doTranslate(map, "key001");
}
private void doTranslate(Map<String, String> map, String key) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String actionCode = map.get(key);
Method method = Test003_Translate.class.getMethod(PREFIX + actionCode, String.class);
String arg = "arg: ";
Object s = method.invoke(this, arg);
}
public String translate001(String input){
return input + "001";
}
public String translate002(String input){
return input + "002";
}
public String translate003(String input){
return input + "003";
}
}
You could use an EnumMap (smaller and faster then a HashMap), like this:
enum Key {
KEY_001,
....
}
EnumMap<Key, Runnable> enumMap = new EnumMap<>(Key.class);
enumMap.put(Key.KEY_001, YourClass::translate001);
....
And usage:
enumMap.get(someKey).run();

Java indeterminate number of arguments of indeterminate type

My company has an application server that receives sets of instructions in their own bespoke XTML syntax. As this is limited, there's a special "drop to Java" command that sends arguments to a JVM (1.6.0_39). Arguments are passed as "in" only, or "in/out", where the special "in/out" variables are a library of mutables for use with this platform.
Previously the only way to receive external configuration was to use a different special command to read from an XTML file. For reasons not worth delving into, this method of configuration is difficult to scale, so I'm working on a way to do this with Java.
The syntax for this configuration was two-tuples of (String,T) where String was the property name in the XTML file, and T was the in/out mutable that the application server would assign the property value to.
I'm attempting to make this transition as seamless as possible, and not have to do annoying string parsing in the application server.
I already have a function
public String[] get(String ... keys)
That retrieves the values from the application servers' keys, but What I really need is a function
public static void get(T ... args)
that accepts the two-tuples. However, note it needs to be static in order to be called from the application server, and my understanding is that T can't be used in a static context.
I'm at a loss for how to approach this problem in a way that doesn't require (at least) two steps, and there is no way to loop over the arguments in the application server.
I know I'm working within a tight set of constraints here, so if the answer is "you have to some messed up stuff", that's fine - I'd just like any insight into another way.
-- edit --
Editing a more specific example.
The configuration is a set of key-value pairs, and can be in a database or a file. The get function is:
public JSONObject get(String ... keys) throws ClassNotFoundException, SQLException, KeyNotFoundException, FileNotFoundException, IOException {
JSONObject response = new JSONObject();
if(this.isDatabase) {
for(int i=0;i<keys.length;i++){
PreparedStatement statement = this.prepare("SELECT value FROM "+this.databaseSchema+"."+this.settingsTableName+" WHERE key = ? LIMIT 1");
statement.setString(1, keys[i]);
ResultSet results = statement.executeQuery();
boolean found = false;
while(results.next()){
String value = results.getString("value");
value = value.replace("\"","");
response.put(keys[i], value);
found = true;
}
if(!found){
throw new KeyNotFoundException(keys[i]);
}
}
} else if (this.isFile) {
boolean[] found = new boolean[keys.length];
BufferedReader br = new BufferedReader(new FileReader(this.settingsFile));
String line;
while((line = br.readLine()) != null ){
String key;
String value;
for(int i=0;i<line.length();i++){
if(line.charAt(i) == '='){
key = line.substring(0,i);
value = line.substring(i+1,line.length());
if(indexOfString(keys,key) != -1){
value = value.replace("\"","");
found[indexOfString(keys,key)] = true;
response.put(key,value);
if(allFound(found)==-1){
return response;
}
}
break;
}
}
}
if(allFound(found)!=-1){
throw new KeyNotFoundException(keys[allFound(found)]);
}
}
return response;
If I had my way, it would look like ...
// ConfigurationReader.java
public class ConfigurationReader{
public ConfigurationReader( ... ){}
public static JSONObject get(String key){
// Get the key
}
}
// ConfigurationInterface.java
public static void get(T ... args){
ConfigurationReader cfgReader = new ConfigurationReader( ... );
for(var i=0;i<args.length;i+=2){
in = args[i];
out = args[i+1];
out = cfgReader.get(in);
}
}
You can use generic types in a static context. Your question is somewhat vague/unclear about how you intend to do this, but consider the example below:
public class Example {
public static void main(String[] args) {
Type t1 = new Type("foo");
Type t2 = new Type("bar");
Type t3 = new Type("baz");
Printer.<Type> printNames(t1, t2, t3);
}
public static class Printer {
#SafeVarargs
public static <T extends Type> void printNames(T... objs) {
for (T obj : objs) {
System.out.println(obj);
}
}
}
public static class Type {
private final String name;
public Type(String name) {
this.name = name;
}
#Override
public final String toString() {
return name;
}
}
}
Printer.<Type> printNames(t1, t2, t3) makes a static reference to the printNames method, parameterized with the Type generic type.
Note that this is type-safe. Attempting to pass an object of a different type into that parameterized method will fail at compile-time (assuming the type is known to be different at that point):
Example.java:8: error: method printNames in class Printer cannot be applied to given types;
Printer.<Type> printNames(t1, t2, t3, "test");
^
required: T[]
found: Type,Type,Type,String
reason: varargs mismatch; String cannot be converted to Type
where T is a type-variable:
T extends Type declared in method <T>printNames(T...)
Edit
Based on your comment, the issue isn't that you're trying use a generic type for your method argument (in the Java-sense of the word generic, anyway); you're simply looking for any non-specific, parent class that both String and your custom type inherit from. There's only one such class: Object.
I'd strongly recommend reconsidering your design if you have any flexibility, since this will make for poor API design. However you can have your method accept an arbitrary number of arbitrarily-typed objects using Object... objs.
For example:
public class Example {
public static void main(String[] args) {
Printer.printNames("a", "b", new Type("foo"), new Type("bar"));
}
public static class Printer {
public static void printNames(Object... objs) {
for (Object obj : objs) {
if (obj instanceof String) {
System.out.println(((String) obj).toUpperCase());
}
else if (obj instanceof Type) {
System.out.println(obj);
}
}
}
}
public static class Type {
private final String name;
public Type(String name) { this.name = name; }
public final String toString() { return name; }
}
}
Based on #nbrooks work, I found a solution. I made a temporary MutableString (to be replaced by the classes provided by the library).
public static class MutableString {
public String value;
public MutableString(){}
}
// One for every mutable type
public static void Pair(String key, MutableString mutable, ApplicationConfiguration appConfig) throws Exception{
mutable.value = appConfig.get(key).toString();
}
public static void Retrieve(Object ... args) throws Exception {
ApplicationConfiguration appConfig = new ApplicationConfiguration( ##args## );
for(int i=0;i<args.length;i+=2){
if(args[i+1].getClass().equals(new MutableString().getClass())){
ApplicationConfiguration.Pair( (String) args[i], (MutableString) args[i+1], appConfig);
} // One for every mutable type
}
}

Reflection to access values that are nested classes

I know it is bad code design, but as a temporary hack...
I need to access a private map where the values are initializations of a static nested class. In the following example, I want to access each value of myMap from a different package.
package belongs.to.someone.else
public class SOExample {
private Map<String, NestedClass> myMap;
static class NestedClass {
final int data;
NestedClass(final int data) {
this.data = data;
}
}
public void populateMyMap(){
for(int i=0; i<100; i++){
this.myMap.put(Integer.toString(i), new NestedClass(i));
}
}
}
But I seem to run into a chicken and egg problem when trying to set the SOExample.myMap field to accessible. I get "cannot be accessed from outside of package" error for the SOExample.NestedClass values in the last statement.
package belongs.to.me
public class SOExampleMyPackage {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
SOExample example = new SOExample();
example.populateMyMap();
// Make the example.myMap field accessible
Field f = example.getClass().getDeclaredField("myMap");
f.setAccessible(true);
// Next line throws error
Map<String, SOExample.NestedClass> myMapHere = (Map<String, SOExample.NestedClass>) f.get(example);
}
}
I appreciate any ideas about how to solve this problem.
You get compile time error because nested class is not accessible.
The only thing you can do is to avoid using references of this class:
Field f = example.getClass().getDeclaredField("myMap");
f.setAccessible(true);
Map map = (Map) f.get(example);
Object obj = map.get("1");
You can access fields and invoke methods on the obj instance with reflection.
#AdamSkywalker supplied the correct approach. I am posting the final working example just for completeness.
public class SOExampleMyPackage {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
SOExample example = new SOExample();
example.populateMyMap();
// Make the example.myMap field accessible
Field f = example.getClass().getDeclaredField("myMap");
f.setAccessible(true);
/////
//SOLUTION start
/////
Map<String, Object> myMapHere = (Map<String, Object>) f.get(example);
// Loop through entries and reflect out the values
Map<String, Integer> finalMap = new HashMap<String, Integer>();
for (String k: myMapHere.keySet()){
Field f2 = myMapHere.get(k).getClass().getDeclaredField("data");
f2.setAccessible(true);
finalMap.put(k, (Integer) f2.get(myMapHere.get(k)));
}
/////
//SOLUTION end
/////
// Test it all
for (String k: finalMap.keySet()){
System.out.println("Key: " + k + " Value: " + finalMap.get(k));
}
}
}

How to check if variable name contains string and then output string variable content

So I have these 4 variables
private final String PROG_DEPT = "PROGRAMMING/ENGINEERING";
private final String DES_DEPT = "DESIGN/WRITING";
private final String ART_DEPT = "VISUAL ARTS";
private final String SOUND_DEPT = "AUDIO";
What I want to be able to do is to get a string and compare it to the variable and then out put what the variable contains if it equals it.
For example if my string equals "ART_DEPT" then it check if there is a variable called ART_DEPT and then output "VISUAL ARTS"
I was thinking of putting it in a 2D String array or a list but I'm not really sure as to how to do what I want to do
The data type you're looking for is Map<String, String>.
Map<String, String> departmentNames = new HashMap<String, String>();
departmentNames.put("PROG_DEPT", "PROGRAMMING/ENGINEERING");
departmentNames.put("DES_DEPT", "DESIGN/WRITING");
//...etc...
//...
String dept = "PROG_DEPT";
String deptName = departmentNames.get(dept);
System.out.println(deptName); //outputs "PROGRAMMING/ENGINEERING"
A Map binds a unique key to a value. In this case both have the type String. You add bindings using put(key, value) and get the binding for a key using get(key).
I would go with an enum:
package com.stackoverflow.so18327373;
public class App {
public static void main(final String[] args) {
final String in = "DES_DEPT";
try {
final Departement departement = Departement.valueOf(in);
System.out.println(departement.getLabel());
} catch (final IllegalArgumentException ex) {
// in was not a known departement
System.err.println("Bad value: " + in);
}
}
public static enum Departement {
PROG_DEPT("PROGRAMMING/ENGINEERING"),
DES_DEPT("DESIGN/WRITING"),
ART_DEPT("VISUAL ARTS"),
SOUND_DEPT("AUDIO");
private final String label;
private Departement(final String label) {
this.label = label;
}
public String getLabel() {
return this.label;
}
}
}
then use valueOf()
You probably want to use some kind of Map, such as a HashMap<String,String>. I suggest you read the Javadocs for the Map interface and the HashMap class.
What you need to use is a Map.
private final Map<String,String> myMap= new HashMap<String,String>() ;
{
myMap.put("PROG_DEPT","PROGRAMMING/ENGINEERING");
myMap.put("DES_DEPT","DESIGN/WRITING");
myMap.put("ART_DEPT","VISUAL ARTS");
myMap.put("SOUND_DEPT","AUDIO");
}
Then use it in the following way:
String input= "ART_DEPT" ;
System.out.println( myMap.get(input) );
Try this
List<String> list=new ArrayList<>();
list.add("private final String PROG_DEPT = \"PROGRAMMING/ENGINEERING\";");
list.add("private final String DES_DEPT = \"DESIGN/WRITING\";");
list.add("private final String ART_DEPT = \"VISUAL ARTS\";");
list.add("private final String SOUND_DEPT = \"AUDIO\";");
String search="ART_DEPT";
for (String i:list){
if(i.contains(search)){
System.out.println(i.split("=")[1].replaceAll(";",""));
}
}
Live Demo here. You can do this using Map but to do that you have to create a map from these Strings.
Sounds like you are looking for reflection (or if you want to use a different data type instead of looking up a variable in a class then a Map<String, String>). Looks like the Map approach is well covered, so only because this is interesting to me, here is the reflection approach (not that this is not the best way to solve this problem, but since you asked for checking if a variable exists and then getting it's value)
import java.lang.reflect.Field;
public class SOQuestion {
private final String PROG_DEPT = "PROGRAMMING/ENGINEERING";
private final String DES_DEPT = "DESIGN/WRITING";
private final String ART_DEPT = "VISUAL ARTS";
private final String SOUND_DEPT = "AUDIO";
public static void main(String ... args) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
System.out.println(reflectValue("ART_DEPT", SOQuestion.class));
System.out.println(reflectValue("COMP_DEPT", SOQuestion.class));
}
public static String reflectValue(String varible, Class thing) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
Field[] fs = thing.getDeclaredFields();
for(int i = 0; i < fs.length; i++) {
if(fs[i].getName().equals(varible)) {
fs[i].setAccessible(true);
return (String) fs[i].get(thing.newInstance());
}
}
return null;
}
}
The first request to print "ATR_DEPT" will print VISUAL ARTS and the second request to the nonexistent "COMP_DEPT" will return null;
private String getStaticFieldValue(String fieldName){
String value = null;
try {
Field field = getClass().getDeclaredField(fieldName);
if (Modifier.isStatic(field.getModifiers())){
value = field.get(null).toString();
}
}
catch (Exception e) {
return null;
}
return value;
}
you have few options as mentioned above :
using a Map , the disadvantage of using a map for this case is that you will have to maintain it, it means that every time you will need to add/remove/edit one of your final static fields, you will have to edit the map as well.
using reflection as mentioned in this post, which is my favorite solution (the above code snippet)
Use the concept of Map
import java.util.HashMap;
import java.util.Map;
public class MajorMap {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<String, String> deptMap = new HashMap<String, String>();
deptMap.put("PROG_DEPT", "PROGRAMMING/ENGINEERING");
deptMap.put("DES_DEPT","DESIGN/WRITING");
deptMap.put("ART_DEPT","VISUAL ARTS");
deptMap.put("SOUND_DEPT","AUDIO");
System.out.println("ART_DEPT----->>"+deptMap.get("ART_DEPT"));
}
}

How would I iterate through a list of [[tokens]] and replace them with textbox input?

Here is the basic code i'm trying to make work:
Field fields[] = SalesLetter.class.getDeclaredFields();
String fieldName;
for (int j = 0, m = fields.length; j < m; j++) {
fieldName = fields[j].getName(); //example fieldname [[headline]]
templateHTML = templateHTML.replace(fieldName, Letter.fieldName());
}
I believe I'm going about it wrong by trying to getDeclaredFields (which isn't even syntactically correct). When I finished my title, it came up with a few other stackoverflow questions which I read before writing this. They were:
Best way to replace tokens in a large text template
Replacing tokens in a string from an array
It gave me the idea of reading all legal [[tokens]] from a text file, putting them into a hash (err I mean map, this is java :D), then creating an object reference with the same name as that token.
I can't figure out how I would do such a thing in java specifically, or if that would work. Please assist.
Thanks in advance,
Cody Goodman
Note: I'm trying to make everything as flexible as possible, so maybe in the future I could add things such as "[[tokenname]]:this is token name, you need to really think about what the customer wants to come up with a good token name" in a text file, then those fields are generated on my form, and everything works :)
In order to read values from non-static fields of a type, you'll need a reference to an instance of the type:
public class ReflectFields {
static class Letter {
public int baz = 100;
}
static class SalesLetter extends Letter {
public String foo = "bar";
}
public static void main(String[] args) throws Exception {
// TODO: better exception handling, etc.
SalesLetter instance = new SalesLetter();
for (Field field : instance.getClass().getFields()) {
System.out.format("%s = %s%n", field.getName(), field.get(instance));
}
}
}
You'll also have to watch for private fields, etc. In general, this approach should be avoided as it breaks encapsulation by looking at class internals.
Consider using the JavaBean API.
public class BeanHelper {
private final Object bean;
private final Map<String, Method> getters = new TreeMap<String, Method>();
public BeanHelper(Object bean) {
this.bean = bean;
for (PropertyDescriptor pd : Introspector.getBeanInfo(bean.getClass(),
Object.class).getPropertyDescriptors()) {
getters.put(pd.getName(), pd.getReadMethod());
}
}
public Set<String> getProperties() { return getters.keySet(); }
public Object get(String propertyName) {
return getters.get(propertyName).invoke(bean);
}
public static void main(String[] args) {
BeanHelper helper = new BeanHelper(new MyBean());
for (String prop : helper.getProperties()) {
System.out.format("%s = %s%n", prop, helper.get(prop));
}
}
public static class MyBean {
private final String foo = "bar";
private final boolean baz = true;
public String getFoo() { return foo; }
public boolean isBaz() { return baz; }
}
}
Exception handling has been omitted for brevity, so you'll need to add some try/catch blocks (I suggest wrapping the caught exceptions in IllegalStateExceptions).
What about using a template engine like Freemarker, Velocity or StringTemplate:
replace [[ by ${ and ]] by }
create a model from a properties file containing the replacements
process templateHTML
Here an example with Freemarker (without Exception handling)
Configuration config = new Configuration();
StringTemplateLoader loader = new StringTemplateLoader();
config.setTeplateLoader(loader);
Map model = Properites.load(new FileInputStream("tokens.properties"));
loader.putTemplate("html.ftl", templateHTML);
Template template = config.getTemplate("html.ftl");
Writer out = new StringWriter();
template.process(root, out);
String result = out.toString();
StringTemplate may be more simple (replace [[ and ]] by $), but I am not fimilar with it:
Map model = Properites.load(new FileInputStream("tokens.properties"));
StringTemplate template = new StringTemplate(templateHTML);
template.setAttributes(model);
String result = template.toString();
The tokens.properties file looks like:
tokenname:this is token name

Categories