I have some String variables:
private String cur, last, avg, vol, shop;
I have method which accept String and gives me some result:
public void SomeMethod(String somestring)
{
//Here some action with `string`
System.out.print(result)
}
So i want to put result into one of String variables, but this variable must be named as value of somestring in my method. Some method which compare somestring with existent variables names. Is such a thing even possible?
You're talking about variable variable name. They're a native feature in PHP, but not in Java, however you can achieve similar functionality using a HashMap, or using Reflection. I'm going to show you the HashMap option, because frankly Reflection is the work of Satan.
Example
Now the way to implement this is like this:
public void someMethod(String name, String value)
{
values.put(name, value);
}
And you can retrieve them with
public void getValue(String name)
{
return values.get(name);
}
I won't write the code for you, because it's a simple transformation to get this to work in your use case.
A hint because I'm feeling nice
You can replace all of your String variables with a Map implementation. Then simply add the values to the Map, as and when the need arises.
Related
I would like to call an object through the use of a generated string.
As you can see, name is being generated correctly.
Also, the method for getting the object works fine.
However I can not use name to reference the object even though that is the name of the object.
Why is that? How can I solve this?
public class FrameTest{
public static void main(String[] args) {
ObjectMethod first_object = new ObjectMethod(); //instanciate object
first_object.setCost(2.5);
String object = "first";
String one = "object";
String name = object + "_" + one;
System.out.println(name);
System.out.println(first_object.getCost());
System.out.println(name.getCost()); //this line does not work
}
}
public class ObjectMethod{
public double value;
public void setCost(double cost) {
value = cost;
}
public double getCost() {
return value;
}
}
The closest I can think of to what you're describing, short of using Reflection (if you're asking this question, you're not ready for Reflection) is to have a map of strings to objects.
Map<String,Runnable> options = new HashMap<>();
options.add("getCost", new CostGetter(...));
options.add("getDescription", new DescriptionGetter(...));
String command = getCommandFromUi();
options.get(command).run();
It could be Callable rather than Runnable. It could be an interface of your own. In Java 8 it could be Supplier and you could pass lambdas:
options.add("getCost", () -> currentUser.price());
Have a look at the Command and Strategy patterns in any book about design patterns.
You have to understand: Java isn't ruby or python or some other dynamic language.
There is no magic connection that allows you to turn a reference to a String into something else.
In other words: the fact that you put "object_one" into a string object doesn't allow you to treat that String like some actual variable object_one.
The one feature of Java that goes into that direction is reflection. But that is really an advanced topic; and before you look into that, you should understand the real basics of Java. So, better start here.
What I mean is: as the answer by "slim" points out: you could use a Map in order to implement some sort of "call by name" functionality. But the point is: that is "not how you do things in Java". Java is a statically compiled language; and there is no sense in using Java when one then tries to break out of that system and do things that rely on flat string parsing at runtime.
This will not work as you wish, because you are trying to call getCost() on String name object.
name - is just a string, but not the object of ObjectMethod class.
You cannot invoke name.getCost() and type of name is String, and string donot have getCost() method. Hence, your code fails here.
String name = object + "_" + one;
In above code, you are assigning name field with value "object_first". That means, field name is type of String with value "object_first". So, name is in no way related to ObjectMethod class, and hence name.getCost() make no sense.
Basically, what you are trying to accomplish
"I would like to call an object through the use of a generated string"
is not possible unless you use reflection.
java is a Strong typed language
that means you have to define a variable and also specify the variable type before you use it and (emphasis mine)
Certain operations may be allowable only to that type*
just because you do:
String objectName;
Object comboValue = departingStop.getSelectedItem();
Object combo2Value = finalStop.getSelectedItem();
objectName = comboValue + "_" + combo2Value;
dosn't mean that now objectName mutated from string into a ComboBox...
imagine how terrible this could be:
Car tata = new Car();
Robot kuka = new Robot();
String foo = tata.getName() + kuka.getName();
now what is foo? a transformer?? NO,
is still a String...
since that is a string you just can not do
foo.drive(), because is not a car, neither foo.weld(); because is not a robot
In eclipse you can easily create getters and setters for your classes' fields.
Before:
package main;
public class TestClass {
private String someString;
private boolean someBoolean;
}
After creating the getters (as we don't care for setters in this question):
package main;
public class TestClass {
private String someString;
private boolean someBoolean;
/**
* #return the someString
*/
public String getSomeString() {
return someString;
}
/**
* #return the someBoolean
*/
public boolean isSomeBoolean() {
return someBoolean;
}
}
But if you do not initialize the String value getSomeString() will return null, meaning that if I want to work with the String in the calling object, I have to always check if for null first.
To avoid this I found some solutions:
Initialize the Strings immediately at their declaration: private String someString = "";
Reflections
return someString == null ? someString : "";
Using java.util.Optional
there are probably many more ways...
While writing this question I figured out that probably for the simple String case the first method should work best: I can easily initialize the Strings to whatever I like and am done.
The reflection approach linked above seemed okay, but a bit messy to handle
exceptions where a String should not be initialized with the empty string.
The null check is okay but now with Java 8 the last method, employing java.util.Optional feels like the right way to do that. I would do it like this:
public String getSomeString() {
return Optional.ofNullable(someString).orElse("");
}
Is it possible to get eclipse's code templates into creating getters like this one for Strings (or all non-primitive types) only?
The standard template used (see Project -> Properties -> Java Code Style -> Code Templates -> Code -> Getter body) is:
return ${field};
I can replace it with
return java.util.Optional.ofNullable(${field}).orElse("");
which helps for Strings - but for all other types it obviously fails.
So I tried
${:import(java.util.Optional)}
return Optional.ofNullable(${field}).orElse(new ${return_type}());
which is not allowed, because Variable 'return_type' is not known. and additionally the ${:import(java.util.Optional)} is not solved as the help makes you believe (I assume it is because Code Templates are just a stricter subset of Templates, more or less). The first makes sense - if ${return_type} is a primitive, this is likely to fail.
Is there a way to make it happen that eclipse generates such custom getters for me? This answer allows to create such getter for one field, but that would mean I had to do it for each field individually. Is it possible to also just have it done by Source -> Generate getters/setters (or any other similar method)?
Or do you think it's best to initialize such objects at their declaration anyway?
I'm sure this question has allready been answered somewhere, but I' ve searched for half an hour now and I'm running out of keywords, because I have absolutly no idea how to do this.
I have a constructor for a class like this
public MyClass (String name)
{}
what I want is to define Strings so that only those Strings can be entered.
I assume it has something to do with static final strings, but there is quite a lot to be found to those and I dont know how to narrow down the search. Please tell me how that thing I want to do is called, so that I can search for it.
Edit:
Example to what I want:
I want to somehow define a number of Strings. (Or do somethig else that has the same effect, as I said I dont know how to do it)
String one = "ExampleOne";
String two = "ExampleTwo";
so that when I call the constuctor
MyClass myClass = new MyClass("somethingElse");
the constructor wont take it. Or even better eclipse allready showing my what options I have like it does whit "Color. "
Yes you have right you can not override String class because it is final so simply you can create your own StringWrapper class that wraps string.
public class StringWrapper{
private String content;
public StringWrapper(String c){
content = c;
}
//all your methods and fields there, for example delegated methods
public String toString(){
return content.toString();
}
}
But Enum could be also used in your case then you define your Enum values
public enum Color {
WHITE, BLACK, RED, YELLOW, BLUE; //; is required here.
#Override public String toString() {
//only capitalize the first letter
String s = super.toString();
return s.substring(0, 1) + s.substring(1).toLowerCase();
}
}
public myClass (Color color)
{}
There are two ways you can acheive this, either use a enum as constructor parameter. The enum itself contains only the allowed values, which is what I would do, keep everythign nice an oop and you can add logic to enums at a later date.
Or alternatively you can just check if the constuctor paramters value is valid, by performing a comparison and throwing an exception if not in allowed values. Have a predfined list and then, myList.contains(myString) - throw exception if false.
What I want is to define String so that only those Strings can be entered
I think that what you are after are Enums.
Enums will allow you to define a range of values which you can then use. In the example I have linked, the developer can restrict the type of input that he/she will receive to the days of the week.
You can check it in constructor's body at runtime, or if you want to compile-time checks, then you can use enum type argument (enum is a predefined set of constants).
From what I understand it seems like you want to limit what the String can be.
You would do this by putting conditional statements inside the constructor to weed out any Strings you don't want to be entered that would either notify the user that it is an invalid string or throw an exception, and the remainder of the constructor would only be executed in an else statement once it has passed all the tests making sure it is a valid String
My enum is like this currently:
public enum Manufacturers {
Honda,
GM,
Toyota,
Ferrari
}
I need to create a Hashmap so I plan on doing this, is this correct?
Manufacturers mfg = Manufacturers.Honda;
mfg.ordinal() // save as key
i.e. I will store the key using the enumInstance.ordinal()
Also, I need to be able to parse a string which will be the ordinal value of the enumeration, and get an enum back:
Manufacturers mfg = Manufacturers.valueOf(mfgOrdinalValueAsString);
The above gave me an error (the string was "1"). Is this the correct way? I guess I should have a try/catch in there right?
The .valueOf would actually be expecting the String "GM" (for 1).
As for storing your enum values in a map, use EnumMap which is designed specifically for this - and will be fast at it, too.
If you really wanted to reference a value by its ordinal, use something like Manufacturers.values()[1].
A suggestion: better use name() to get the name of the enum as a String, and whenever you need to get back the original Enum from it, use the valueOf() method - since valueOf() expects the name, not the ordinal, as a parameter. For example:
enum Example {ONE, TWO};
String name = Example.ONE.name();
Example e = Example.valueOf(Example.class, name); // e has value ONE
If you definitely need to use the ordinal, the ordinal() method will return an index which you can use to retrieve the respective Enum from the array returned by the values() method. Like this:
int ordinal = Example.ONE.ordinal();
Example e = Example.values()[ordinal]; // e has value ONE
As has already been pointed out, consider using EnumMap, as stated in the documentation, it is
A specialized Map implementation for use with enum type keys. All of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. Enum maps are represented internally as arrays. This representation is extremely compact and efficient.
EDIT
If you need to associate a different code to each element of the enum (other than its automatically assigned ordinal), you can always add it as an attribute to the enum, together with getters and setters, like this:
public enum Manufacturers {
Honda(10),
GM(20),
Toyota(30),
Ferrari(40);
private int code;
Manufacturers(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
For example:
Manufacturers m = Manufacturers.Honda;
System.out.println(m.getCode()); // prints 10
m.setCode(100);
System.out.println(m.getCode()); // prints 100
Just be aware that you won't be able to reconstruct an Enum object from the code attribute, since that was defined by the programmer.
Well, this is a very basic question, I've never coded in java, but I'm writing a class for a friend... Having something like:
class myClass{
private string name;
public string getName() {
return this.name;
}
public void setName (int newValue) {
this.name = newValue;
}
private int number;
public int getNumber() {
return this.number;
}
public void setNumber (int newValue) {
this.number = newValue;
}
}
The way I was thinking of building the constructor was:
public myClass (string name, int numbers) {
this.name = name;
this.number = number;
}
My questions:
I'm using the same identifiers for the properties as for the parameters. Does "this." avoid any trouble here?
Is it better to use the set methods and, if so, should i use "this."?
Thank you very much
Yes, it avoids the name clash. In the constructor's context, the name name refers to the parameter, and the name this.name refers to the instance field.
Depends on what you mean by "better." Personally, I would make the name and number fields final, so the class is immutable. In my experience, it's better to start from an immutable class definition, and only move towards something mutable if there is a legitimate need to do so.
Yes, this differentiates between an instance variable and a method parameter variable of the same name.
There's always debate on whether constructor or setter initialization is better. If you're only going to set the name and number when you first create the object, and won't need to update those variables later, just using the constructor and leaving out the setters is probably better. And yes, in the setter, you'd need to use this if your parameter has the same name as the field you want to set.
There's no problem having the parameter using the same name as the field; the this. explicitly disambiguates and the program will behave as intended.
Depending on your program it may or may not be advantageous to use setters instead of directly writing fields. If you write the values directly in the constructor, then you bypass any runtime checks that you might have in your setters, which could potentially cause your object to hold data it normally can't. On the other hand, if your setter tries to do something with the old value, then you probably don't want to call the setter because, in the constructor, there might not be a meaningful old value. I'd say it's not clearly better or worse to set the fields in the constructor than to use setters, so long as you're careful to avoid breaking the class invariants.
Yes. Using the this keyword avoids issues.
If there are logic in the get/set methods, then you should use them instead. Otherwise, setting the values in the constructor is valid.
1) When the object scope property is the same as the argument name you must use this to differentiate between them. When there is a name clash the local var or argument will take precedence over the property.
For this reason, I don't like to ever have the exact same name for each as it can easily lead to bugs.
2) I also would use the setters from within the constructor, because if there ever needs to be a validation or some other operation done on the argument at time of setting you'll only have to make the change in one place. Otherwise it is duplication and violates the DRY (Don't Repeat Yourself) principle.
I would do:
public myClass (string name, int number) {
setName( name );
setNumber( number );
}
Yes, this. avoids problems. Some people recommend that way, such as Rogue Wave in their book The Elements of Java Style.
Other common ways of dealing with this are:
name members with a "m" or "m_" prefix
private string m_name;
private int m_number;
public myClass(string name, int number) {
m_name = name;
m_number = number;
}
call the parameters a different name, usually a single letter or abbreviated version of the member name
private string name;
private int number;
public myClass(string nam, int num) {
name = nam;
number = num;
}
But I prefer the way you are using now with this.