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
Related
I am trying to pass a variable number of arguments into a constructor, because not all of the values will always be required, and empty values are okay. Can I make it such that I can pass the variables in, in any order, and have them assign to their corresponding variables in the class correctly?
Few things to note in my case is that the variables in the class are Serialized; the values are either a String, an Integer, a boolean, or a Date; and the values passed into the constructor will always match their corresponding class values (If the value in the class is an Integer, an Integer will always be passed in for that value, not a String.parseInt(), for example)
Class Foo {
#SerializedName("id")
private Integer id;
#SerializeName("name")
private String name;
#SerializedName("isFoo")
private Date isFoo;
public Foo (Object... args){
}
}
In the constructor I want to be able to ask if whatever object name matches a variable in the class, to assign it to that variable. So if one of the Object's passed is an Integer named id, is there a way to match it to id? It should be able to be matched in a few cases:
Foo foo = new Foo(id, name) //In this case, the bool would be null
Foo foo2 = new Foo(name, id, isFoo) //Here the Integer is second, but should still be able to be passed in correctly
I think this can be solved via Reflection but I am not sure how. Any help would be amazing.
I answer your actual question below, but answering the underlying desire of the question, you're probably looking for the Builder pattern:
Foo foo = new Foo.Builder().id(id).name(name).build();
Foo foo = new Foo.Builder().name(name).id(id).isFoo(isFoo).build();
It's one of the original Gang of Four patterns.
(In the above I made Builder a nested class within Foo, as the builder class and the thing it builds tend to be intimately related. But that's not necessary, it's just one way it's done.)
...can I assign values to variables based on the variable name?
No. The variables are not passed to your method. The value contained in the variables is read from them, and that value is passed to your method. By the time it gets to your method, there is no connection whatsoever back to the variable the value came from (if, in fact, it came from a variable).
In your specific example, since each of them has a distinct type, you could check each of the entries in args to see what its type is and work from that, but it would be fairly odd and I wouldn't recommend it.
Emphasizing that I wouldn't recommend it, that would look like:
for (Object arg : args) {
if (arg instanceof Integer) {
this.id = (Integer)arg;
} else if (arg instanceof String) {
this.name = (String)arg;
} else if (arg instanceof Date) {
this.isFoo = (Date)arg;
}
}
But again, I wouldn't recommend it, and if I came across it in a code review I'd want a really, really good justification for it. :-)
When we do:
String string = new String("Ralph");
//This creates a reference called string that points to a sequence of
//characters in memory
This is the same as:
String string = "Ralph";
When we print both, we get the actual value of the string.
If we print any other object in Java, we get an address for that object.
My question is, is there any dereferencing that is taking place behind the scenes?
When you pass an object reference to the System.out.println() method, for
example, the object's toString() method is called, and the returned value of toString() is shown in the following example:
public class HardToRead {
public static void main (String [] args) {
HardToRead h = new HardToRead();
System.out.println(h);
}
}
Running the HardToRead class gives us the lovely and meaningful,
% java HardToRead
HardToRead#a47e0
Now,
Trying to read this output might motivate you to override the toString()
method in your classes, for example,
public class BobTest {
public static void main (String[] args) {
Bob f = new Bob("GoBobGo", 19);
System.out.println(f);
}
}
class Bob {
int shoeSize;
String nickName;
Bob(String nickName, int shoeSize) {
this.shoeSize = shoeSize;
this.nickName = nickName;
}
public String toString() {
return ("I am a Bob, but you can call me " + nickName +". My shoe size is " + shoeSize);
}
}
This ought to be a bit more readable:
% java BobTest
I am a Bob, but you can call me GoBobGo. My shoe size is 19
The class String is a special class in Java.
But it gets out printed the same way every other class does.
If we call System.out.println("Ralph") the function println takes that String and then displays it.
The class Objects toString() method is implemented, so it displays the hash code of the Object, by calling the hashCode() function. If you overwrite the toString() method, it will display something else.
If you take any object other than a String and give it to a method that takes a String (or in fact cast it to a String) java will call the toString()method of that Object, to convert it to a String.
So 'printing' always does the same thing, it's just implemented in different ways, using the toString() method.
new String("Ralph") copies the character data array of the literal string and stores it in the new String instance.
However, you only get the address of an object when you print it because printing uses the toString() method of that object. If that method is not implemented, the default implementation defined in Object is used, which returns the class name plus the hash code (that seems like an address if hashCode() is not implemented).
I believe the primary types are printed with auto dereferencingString, int, float, etc., while the objects other than primary types, only with de-referencing function object.toString() that are implemented on the object level.
I have the following recursive function prototype:
public void calcSim(Type<String> fort, Integer metric)
Integer metric = 0;
calcSim(fort, metric);
System.out.println("metric: " + metric);
}
I want to print the value of metric as shown above. However it is always zero. Now, when I print at the end of the function, I do get a valid number.
How do I pass by reference or get the equivalent functionality like in C++
What all can I do with regards to my parameter passing? (by value, by reference, etc...)
There is no such thing as pass by reference in Java, sorry :(
Your options are either to give the method a return value, or use a mutable wrapper and set the value as you go. Using AtmoicInteger cause it is in JDK, making your own that doesn't worry about threadsafety would of course be mildly faster.
AtomicInteger metric = new AtomicInteger(0);
calcSim(fort, metric);
System.out.println("metric: " + metric.get());
Then inside the calcSim set it with metric.set(int i);
To get the behavior of pass by reference, you can create a wrapper class, and set the value in that class, eg:
class MyWrapper {
int value;
}
Then you can pass a MyWrapper to your method and change the value, for example like this:
public void calcSim(Type<String> fort, MyWrapper metric)
metric.value++;
System.out.println("metric: " + metric.value);
calcSim(fort, metric);
}
Integer is wrapper class. Wrapper classes are immutable. So, what you are expecting can't be achieved with Integer type.
You may create mutable wrapper class around primitive and update the object to achieve what you want.
Two big issues:
You are redefining metric with the same name in your method as well. How is program printing anything. It should complain at compilation time.
No defined exit criteria. Does you program(method) stops?
I think you wanted something as (pseudo code as I don't know what are you doing):
public void calcSim(Type<String> fort, Integer metric)
if(condtion){
//print or return
}else{
//modify fort or metric so that it exits
calcSim(fort, metric); //call this with modified value
System.out.println("metric: " + metric.value);
}
}
I know that at compile time when a String is created, that String will be THE string used by any objects of that particular signature.
String s = "foo"; <--Any other identical strings will simply be references to this object.
Does this hold for strings created during methods at runtime? I have some code where an object holds a piece of string data. The original code is something like
for(datum :data){
String a = datum.getD(); //getD is not doing anything but returning a field
StringBuffer toAppend = new StringBuffer(a).append(stuff).toString();
someData = someObject.getMethod(a);
//do stuff
}
Since the String was already created in data, it seems better to just call datum.getD() instead of creating a string on every iteration of the loop.
Unless there's something I'm missing?
String instances are shared when they are the result of a compile-time constant expression. As a result, in the example below a and c will point to the same instance, but b will be a different instance, even though they all represent the same value:
String a = "hello";
String b = hell() + o();
String c = "hell" + "o";
public String hell() {
return "hell";
}
public String o() {
return "o";
}
You can explicitly intern the String however:
String b = (hell() + o()).intern();
In which case they'll all point to the same object.
The line
String a = datum.getD();
means, assign the result of evaluating datum.getD() to the reference a . It doesn't create a new String.
You are correct that strings are immutable so all references to the same string value use the same object.
As far as being static, I do not think Strings are static in the way you describe. The Class class is like that, but I think it is the only object that does that.
I think it would be better to just call the datum.getD() since there is nothing that pulling it out into its own sting object gains for you.
If you do use the datum.getD() several times in the loop, then it might make sense to pull the value into a String object, because the cost of creating a string object once might be less than the cost of calling the getD() function multiple times.
This may sound very basic... can someone please explain the use of the toString() method and when to effectively use this?
Have done a search on google but could not find any good resource.
In most languages, toString or the equivalent method just guarantees that an object can be represented textually.
This is especially useful for logging, debugging, or any other circumstance where you need to be able to render any and every object you encounter as a string.
Objects often implement custom toString behavior so that the method actually tells you something about the object instance. For example, a Person class might override it to return "Last name, First name" while a Date class will show the date formatted according to some default setting (such as the current user interface culture).
There are several situations in which one would wish to override the toString method of a class (most of which are already mentioned in the existing answers), but one of the most common situations in which I have needed to explicitly call toString on an object is when using StringBuilder to construct a String.
public String createString(final String str) {
final StringBuilder sb = new StringBuilder(str);
sb.append("foo");
sb.append("bar");
return sb.toString();
}
You want to display an object and don't want to check if it is null before.
You want to concat Strings and not thinking about a special attribute, just provide a default one to the programmer.
Thus:
out.println("You are " + user);
will display "You are null" or "You are James" if user is null or toString displays "James" for this (existent) instance.
Assuming .NET or Java:
In general, you should overload ToString() when you want a textual representation of your class (assuming it makes sense for your class).
You can use toString() on an class by overriding it to provide some meaningful text representation of your object.
For example you may override toString() on a Person class to return the first and last name.
To string is should be used when you have a need to change a data type to a string. For built in types like int and such there string representations are what you expect. ie
int i = 5;
string s = i.ToString(); //s now equals "5"
Gives you the character string "5" for most complex types and all user created types you need to overload the tostring method or you will only get the name of the class. To string allows you to use the complex formating build into .net with your own objects. you can provide complex formatters like the datetime class does to give flexibility in using your own types.
toString() can be used to avoid the hexadecimal address, so to overcome this problem you need to override toString() then you will get original text format of data.
When you print reference variable then following task will happen.
if reference variable contains null then null value will be displayed.
if reference variable contains address of an object then toString() Method will be called by the JVM automatically.
By default toString() of Object.class will print:
ClassName#HexadecimalOfHashCode
You can override this method in your class to display some meaningful String.
Usually toString() method is used to print contents of an object.This method is already overridden in many java built-in class like String,StringBuffer,integer etc.
It used when we have to display the field values which we initialize through constructor and what to display without using any getter.
import Test.Date;
public class Employ {
private String firstname;
private String lastname;
private Date DOB;
private Date DOH;
public Employ(String name,String lastname,Date DOB,Date DOH)
{
this.firstname=name;
this.lastname=lastname;
this.DOB=DOB;
this.DOH=DOH;
}
public String toString(){
return String.format("%s %s Birthday %s Hired %s",firstname,lastname,DOB,DOH);
}
public static void main (String args[])
{
Date dob= new Date(12,3,1992);
Date doh= new Date(10,6,2005);
Employ em= new Employ("BOB", "Wrigh", dob,doh);
System.out.println(em);
}
}