Can I print out the name of the variable? - java

I have created a no. of constant variables, more than 1000, those constants are unique integer.
public static final FOO 335343
public static final BAR 234234
public static final BEZ 122424
....
....
....
Is there a way to print out the FOO, BAR and BEZ, the variable of the names in Java?
I am not familiar with java reflection. I don't know if that helps.
if ( FOO == 335343)
---> output "FOO"
if ( BAR == 234234 )
---> ouptut "BAR"
....
Actually asking this question behind is that I want to write log into the file
say
System.out.println("This time the output is " + FOO);
and the actual output is
This time the output is 335323
I want to know which variable comes from 335323.
Is there any other way apart from putting those variable and its associate constant into hashMap?
Thanks

There are some 'special case' that u can have workaround for this (which is told by other), but the most important question is: why would you want to do this (printing out variable name)?
From my experience, 99.9% of similar questions (how to print variable name? how to get variable depends on user inputting variable name? etc) is in fact raised by beginner of programming and they simply have made incorrect assumptions and designs. The goal they are trying to achieve normally can be done by more appropriate design.
Edit
Honestly I still do not think what you are trying to do is the way to go, but at least I think the following is a workable answer:
It is more or less a combination of previous answer:
(Haven't try to compile but at least it give u an idea)
class Constants {
public static final int FOO = 123;
public static final int BAR = 456;
private static Map<Integer, String> constantNames = null;
public static String getConstantName(int constVal) {
if (constantNames == null) {
Map<Integer, String> cNames = new HashMap<Integer, String>()
for (Field field : MyClass.class.getDeclaredFields()){
if ((field.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) != 0) {
&& int.class == field.getType()){
// only record final static int fields
cNames.put((Integer)field.get(null), field.getName());
}
}
constNames = cNames;
}
return constantNames.get(constVal);
}
}
assuming you want to get a constant name, just do:
Constants.getConstantName(123); // return "FOO"

As I noted in my comment to the original post, I have a strong suspicion that the best solution for your current problem is to solve it in a completely different way. You seem to want to associate an int with a String, and one way to do this is to use a Map such as a HashMap. For e.g.,
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
Map<Integer, String> myMap = new HashMap<Integer, String>();
myMap.put(335343, "FOO");
myMap.put(234234, "BAR");
myMap.put(122424, "BEZ");
int[] tests = {335343, 234234, 122424, 101010};
for (int i : tests) {
// note that null is returned if the key isn't in the map
System.out.printf("%d corresponds to %s%n", i, myMap.get(i));
}
}
}
Edit 1:
Per your recent comments and update to your original question, I take it that you have many numbers and their associated Strings involved in this program and that your need is to find the String associated with the number. If so, then you need to think re-design, that the numbers and their strings should not be hard-coded into your program but rather be part of the program's data, perhaps in a text file with one column being the numbers and the next column (separated by a space perhaps), the associated text. This way you could read in the data and use it easily in a HashMap, or data base, or really any way that you desire. This will give your project much greater flexibility and robustness.

You can use something like:
for (Field field : MyClass.class.getDeclaredFields()){
if (field.getType().toString().equals("int")){
int val = (Integer)field.get(MyClass.this);
switch (val){
case 335343:
case 234234:
System.out.println(field.getName());
}
}
}
Remember to change MyClass for your class name and that at least one instance should exist to get the value of the field. So, if you are planning on testing the code in a main method, you should change MyClass.this to something like new Myclass().
Another thing to remember is that the fields are attributes and not method variables (so it won't work if you are using this to access variables declared inside a method).

You can use enum.
If these numbers just need to be unique, you can say
public enum Yourname {
FOO, BAR, BEZ
}
and refer to the name as Yourname.FOO and the value as Yourname.FOO.ordinal(). You can use enums for if-blocks, switch-statements.
If you want to have the numbers you gave in the question, so if FOO needs to be 335343, you can create numbered enums. Have a look at is-it-possible-to-assign-numeric-value-to-an-enum-in-java and number-for-each-enum-item.

I would suggest that you print out the line number, not the variable name. That should give you enough to determine where the message is coming from. Here's more info on how to do that:
How can we print line numbers to the log in java

I had a similar problem with a long list of int variables that I had to print the name of each variable and its value (main goal was to create a text file that was going to be imported in an Excel file).
Unfortunately I'm quite new in Java programming, so the only solution that I found (probably wrong) is to use two different arrays: one String array for the String name and another Int array for the corresponding values.
For example:
int varName01, varName02, ....
String[] listNames = new String {"varName01", "varName02", .....
int[] listValues = new int {varName01, varName02, .....
for (int i=0; i<listValues.length;i++)
{
print String.format("%s %d", listNames[i], listValues[i]);
}
Probably this is not the correct way to do it, so any opinion from some Java expert would be more than welcome. Thanks!

Related

How to get an object using a string in Java

I've been trying to make my code more efficient, and I'm stuck on an issue where I have to repeat myself a lot to create 40+ objects (which results in 40+ functions with basically the same code, just different objects and different values). I am wondering if there is a way to make something like this in Java:
public void createObject(String objectName) {
getObject(objectName).setType(ymlFile.getString(objectName + ".type"));
// getObject(objectName) would be the object which has the same name as the value of the string objectName
}
Currently I have to have basically this code (with more variables) for over 40 objects, so I was wondering if it is possible to be able to retrieve the object by using the value in the string called objectName, thus meaning that I only have to call the method 40 times, instead of having the big block of code 40 times.
Thanks.
EDIT:
No, this isn't to do with YAML (not really anyway, just showing some of the code). My main issue is I need to be able to retrieve objects by using values of a string.
As for examples of the repetitive code, it's basically this:
public void createObject1() {
object1.setType(type1);
}
public void createObject2() {
object2.setType(type2);
}
// etc. for about 40 objects. basically i want to be able to change that to this:
public void createObject(String objectName) {
objectName.setType("value"); // so basically, retrieve the object that has the same name as the value of objectName
}
This looks like a case of the XY problem to me.
You probably just want to use two arrays to keep track of all objects and types, especially since it's really bad practice to name variables something1, something2 and so on.
So replace your object and type variables with:
YourClass[] objects = new YourClass[40];
Type types = new Type[40];
and replace your creatObject() methdod with:
public void createObject(int index) {
objects[index].setType(types[index]);
}
which you could even loop over like this:
// This condition is overkill since both arrays should have the same size,
// but if you plan on doing something different than that, this should work.
for(int i = 0; i < objects.length && i < types.length; i++)
createObject(i);
If you really want to use strings though, you could do the same thing with a Map<String, YourClass> and a Map<String, Type>.

int vs Integer vs a user made class to achieve effective pass by reference behavior in Java

Let's say you have a class of object with three
integer fields that you want to possibly change, all in the same way, with one method.
Let's keep it simple and say all that the method does is add 1 to the parameter passed to it.
That is to say, the desired behavior is that by the time the method has completed, the relevant field has increased by 1.
This is impossible to achieve in Java using the primitive type "int" for those fields.
I know about how Java is "always" pass by value, and not pass by reference,
- and - i've heard whisperings on the internet that this is one reason that the Integer class exists, along with other object "wrapper" classes
for ordinarily primitive types such as int and double.
Sending an object as an argument to a method should, in theory, provide a way to [effectively, if not technically] pass by reference, since the value that is passed, is supposedly the value of the reference to the object.
Very tricky. BUT - and this is where my annoyance comes in - I've tried achieving this very simple task by passing an Integer argument instead of an
int, and the desired behavior was still not accomplished. 1 was not added to the relevant field.
And yet, when I made my very own object, which consisted of just one field, an int value, and passed an instance of this object as an argument
to an appropriate method which would simply add 1 to the passed parameter, the desired behavior was in fact accomplished. 1 was added to the relevant field.
So the questions orbiting around this query are - Is it really going to be necessary to craft my own homemade class just to carry a simple integer value
every time I want to achieve this desired behavior? Can the existing tool provided by Java, Integer, really not perform this simple task?
Instead of having one nice, neat method to handle all three of the hypothetical integer fields i mentioned in the beginning, I felt compelled (in a separate, similar project that ultimately provoked this line of thinking) to make a separate method corresponding to each of the three fields, with essentially the same exact code in each one. This seems very inefficient.
It may not seem like a big deal, on the surface, to write three similar methods instead of one, but to clarify why this dismays me - imagine instead of an object with three integer fields as I stated, there are say, i don't know, four thousand. It would be so much better to write just one thing to perform the same kind of behavior, instead of copying and pasting (and changing whatever little bits necessary) four thousand times.
So I suppose the ultimate question is,
Why doesn't Integer function in a reasonable way? What's the point of wrapping a primitive in an Object at all, if it doesn't even help perform something this simple? Am I missing something simple about how to get Integer to function in the desired way? (Hopefully so) The answer seems close yet infuriatingly out of reach since "RInteger" produces the desired behavior, yet "Integer" doesn't.
The entire source code I used while trying to figure out how to construct this painstaking question is below.
package r9mp;
import javax.swing.SwingUtilities;
public class RefTest2 {
//[main m]
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new RefTest2();
}
});
}
//[fields]
int i;
Integer I;
RInteger RI;
//[constr]
public RefTest2(){
intTest();
IntegerTest();
RIntegerTest();
display();
}
//[methods]
private void intTest(){
i = 100;
intMethod(i);
}
private void IntegerTest(){
I = 100; //boxing? auto?
IntegerMethod(I);
I = 100; //just in case.
IntegerMethod2(I);
}
private void RIntegerTest(){
RI = new RInteger(100);
RIntegerMethod(RI);
}
private void intMethod(int ipar){
ipar = ipar + 1;//no change. expected.
}
private void IntegerMethod(Integer IPar){
IPar = IPar + 1;//no change. frustrating.
pln("From inside IntegerMethod: IPar = " + IPar );
pln("From inside IntegerMethod: I = " + I );
}
private void IntegerMethod2(Integer IPar){
IPar = new Integer(IPar+1);//still no change. there are no set methods for Integer, or I'd try them.
}
private void RIntegerMethod(RInteger riPar){
riPar.value = riPar.value + 1;
}
private void display(){
pln(
"Display... \n" +
"i: " + i + "\n" +
"I: " + I + "\n" +
"RI: " + RI + "\n" +
"--------"
);
}
private void pln(){
pln("");
}
private void pln(String s){
System.out.println(s);
}
//[internal class]
private class RInteger{
int value;
public RInteger(int v){
value = v;
}
public String toString(){
return ""+value;
}
}
}
And, here is the output...
How about one method for primitives and their wrappers?
private int incInteger(int value)
{
return value + 1;
}
and call for it:
int intVal = 100;
intVal = incInteger(intVal);
Integer integerVal = 200;
integerVal = incInteger(integerVal);
First of all, you need to read up on immutability to find out why it is a very good thing to have. There even exist entire languages (functional, mostly) that capitalize on it.
Once you have read about that, then read Eric Lippert's series of articles on immutability. Start here: https://blogs.msdn.microsoft.com/ericlippert/2007/11/13/immutability-in-c-part-one-kinds-of-immutability/ Mind = blown.
But to give you a quick hint as to why primitive wrappers like Integer are immutable, let me just say that these classes are often used as keys in Hash Maps, and a key must be immutable, so that its hashCode will never change, otherwise the hash map will fail with very difficult to track down behaviour. Mutable keys in hashmaps are nasty bugs.
You can achieve what you want with a class of your own devise which plays the role of a reference, or by simply passing an array and modifying the element at array[0].
My personal preferences are as follows:
I would try to do as much as possible with return values.
When return values are inapplicable, (as the case is with invokeLater,) then inner/nested/anonymous classes that have access to the fields of the enclosing class are my next preference.
When that's not an option either, then special classes crafted precisely for the application at hand are my next option. (MyMutableNumberWrapper.)
And when I just want something quick and dirty, then general-purpose classes like Ref<T> (or even single-element arrays) would be my final option.

Interpreting Text Files and using Strings as Variables

public void readFile()
{
while(fileReader.hasNext())
{
String blankClarification1 = fileReader.next();//Why Java Why?!
Carthage_Independent_Status = Integer.parseInt(fileReader.next());
String blankClarification2 = fileReader.next();
Carthage_Stability = Integer.parseInt(fileReader.next());
String blankClarification3 = fileReader.next();
Carthage_Ruler_Name = fileReader.next();
Basic text file interpretation. However it is inefficient and time consuming my question is this? is there a way to take the name of a variable from a text file and its value then make them equivalent in such a way that the variable does not have to be specifically named in the interpretation(but rather declared earlier) and the reader takes the variable name and sets it equivalent to the value next to it?
Below is the text file
Carthage_Independent_Status 0
Carthage_Stability 100
Carthage_Ruler_Name Dido
Of course there is more in it however is it possible to have something like this?
String Variable = fileReader.next();
String Value = fileReader.next();
Variable = Value;
Is there a way to program this in such a way that it sees Variable not as a string, but as a variable and thus saves time and effort? I have seen some threads regarding turning a string into a variable by mapping it, yet nothing I have tried has had the desired effect. I believe there is such a method in PHP, but then again this is Java. If any clarification of the question is needed I'll be happy to oblige I'm just naturally bad at articulating myself.
Question: is there a way to take the name of a variable from a text file and its value then make them equivalent in such a way that the variable does not have to be specifically named in the interpretation(but rather declared earlier) and the reader takes the variable name and sets it equivalent to the value next to it?`
Yes, you can use Map<String, String>
Question: Is there a way to program this in such a way that it sees Variable not as a string, but as a variable and thus saves time and effort?
1.If your variables are basically primitive types or String, you can have some util methods. Like
class Configuration {
Map<String, String> properties; // load your files into this map at first
public String get(String key) { // if the value is string type
return properties.get(key);
}
public float getFloat(String key) { // if the value is float type
if (properties.containsKey(key)) {
return Float.parseFloat(properties.get(key));
} else {
return DEFAULT_VALUE; // the default value of the key "key"
}
}
public int getInt(String key) { // if the value is int type
}
}
There's an in production example, take a look at hadoop-common's Configuration.java
If you want to save variables of more complicated types into file, and read variables from file, you need serialization/deserialization toolkits. gson library would be a good start. You pre-define your Configuration class, and just save your configuration as json file, and load your Configuration class from file.

How to access a struct via an ArrayList in Java

I have following lines of code:
private ArrayList<wordClass>[] words;
and
public class wordClass {
public String wordValue = null;
public int val = 0;
public boolean used = false;
}
Is there anyway I can access wordValue, val, and used via words? Like words[5].val? I know I can do that if they are just in an array of wordClass, but I want a dynamic array to make it easier to add and subtract from the array.
And yes, I know the values should be private. Just don't want to write getters and setters yet.
Thanks.
Do you really want an Array of an ArrayList?
It doesn't seem correct.
In Arrays, you use [] to access (words[0]).
In ArrayLists, you should use words.get(0).
The way you have coded, you should use: words[0].get(0).val to get the very first value.
But I recommend you to review your words definition.
ArrayList Documentation: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
Regards,
Bruno
Your code is a bit off for a dynamic array (Java has immutable arrays), so you need an ArrayList. Also, Java uses Capital Letters for class names (please follow the convention) -
// like this, changing wordClass to WordClass. Also, using the diamond operator
private ArrayList<WordClass> words = new ArrayList<>();
To access your WordClass fields you can use something like -
for (WordClass wc : words) {
if (wc.used) {
System.out.println(wc.wordValue + " = " + wc.val);
}
}
Note, you still need to create WordClass instances and place them into the words List.
Write wrapper classes for each value. e.g. What you call "getters".
Then call:
words[1].getWordValue() ==> None
Voila

Use enums for array indexes in Java

While reading Effective Java I came across the suggestion to "use enums instead of int constants". In a current project I am doing something similar to that below:
int COL_NAME = 0;
int COL_SURNAME = 1;
table[COL_NAME] = "JONES"
How would I use enums instead to achieve this? Due to the interface I'm forced to use, I must use an int for my index. The example above is just an example. I'm actually using an API that takes an int for index values.
Applying one usefull pattern together with an anti-pattern often fails ;-)
In your case using an array for not-really array-like data provides a problem when you want to replace int constants with enum values.
A clean(er) solution would be something like an EnumMap with the enum values as keys.
Alternatively you could use table[COL_NAME.ordinal()] if you absolutely must.
If some API forces you to pass around int values but you have control over the actual values (i.e. you could pass your own constants), then you could switch to using enum values in your code and convert to/from enum only at the places where your code interfaces with the API. The reverse operation of enumValue.ordinal() is EnumClass.values()[ordinal]).
It sounds like you are trying to use a EnumMap. This is a Map which wraps an array of values.
enum Column {
NAME, SURNAME
}
Map<Column, String> table = new EnumMap<Column, String>(Column.class);
table.put(Column.NAME, "JONES");
String name = table.get(Column.NAME);
This would much simpler if you used a POJO.
classPerson {
String name;
String surname;
}
Person person = new Person();
person.name = "JONES";
String name = person.name;
Depends on the requirements. You could use Enum.ordinal() to convert an enum to an int.
Note that it's not possible to pass an Enum directly as the index.
Edit:
Another possibility would be to use a Map<YourEnum, String> map and then use map.get(EnumValue).
Since you have to use that table and thus can't actually use an EnumMap, I personally think the best solution would be to stick with what you have. In an enum, the ordinal values of the elements are not supposed to have any intrinsic meaning, while in your case they do, since they are used as indices into the table.
The problem you have is not that you are not using enums, it's that you need magic values to extract column data out of a table. In this case, using integer constants is the right tool for the job, unless if you can tackle the underlying problem of that table.
Now you could tackle it by wrapping the table in your own class that accesses it, and use enums in and out that class. But this introduces more code, another layer of indirection and doesn't actually solve any problems for you, except that an enum is a bit easier to maintain than a list of int values (greatly offset by you having to maintain the wrapper you now wrote).
You could consider this work if you are writing a public API that other people will use, since it will avoid having them depend on some magic values that might change over time (tight coupling which will break things). If you are, then a wrapper which uses an EnumMap internally is likely the way to go.
Otherwise, leave it as is.
Depending on the values of your array, you might be looking at an object instead. For examples if your array looks something like this
person[FIRST_NAME] = "Jim Bob"
person[SURNAME] = "Jones"
person[ADDRESS] = "123 ABC St"
person[CITY] = "Pleasantville"
...
Then what you really want is something like this
Person jimBob = new Person("Jim Bob", "Jones");
jimBob.setAddress("123 ABC St", "Pleasantville", "SC");
....
See Refactoring: Replace Array with Object
I have also run into this problem, and having come from the C++ world I wasn't expecting to run into this.
The beauty of enum is that can create a series of related constants with unique values where the actual value is irrelevant. Their use makes code easier to read and guards against variables being set to invalid enum values (especially in Java), but in a situation like this it is a major pain. While you might have "enum Pets { CAT, BIRD, DOG }" and don't really care what value CAT, BIRD, and DOG actually represent, it's so nice and clean to write:
myPets[CAT] = "Dexter";
myPets[BIRD] = "Polly";
MyPets[DOG] = "Boo-Rooh";
In my situation I ended up writing a conversion function where you pass in an enum value and I return a constant. I hate doing this with a passion, but it's the only clean way I know to maintain the convenience and error checking of enum.
private int getPetsValue(Pets inPet) {
int value = 0;
switch (inPet) {
case CAT: value = 0; break;
case BIRD: value = 1; break;
case DOG: value = 2; break;
default:
assert(false);
value = 0;
break;
}
return value;
}
You can define an enum with a constructor like so:
public enum ArrayIndex {
COL_NAME(0), COL_SURNAME(1);
private int index;
private ArrayIndex(int index) {
this.index = index;
}
public int getIndex() {
return this.index;
}
};
And then use it like this:
public static void main (String args[]) {
System.out.println("index of COL_NAME is " + ArrayIndex.COL_NAME.getIndex());
}

Categories