Java's toString() static or non-static (based on my example) - java

I am new to the concepts of oop and therefore what I write have may have bad assumptions. Please correct me where appropriate.
In some code I saw a function takes in an argument in the form of int number. Then, in the function the following line is written outputString = Integer.toString( number );
I interpreted this as go the the class Integer, find a method called toString() and feed this the int called number and set the output of that to outputString. Since the syntax is class.method(arg) I assumed that toString() is a static function.
I wanted to test if it was static. I rewrote the code with the argument as Integer number and then did outputString = number.toString(); and it worked. This has the form obj.method(arg) which I had assumed would only work for non static methods.
I am unsure what conclusion to draw from this or if I have made a wrong assumption. Thanks.

If you're talking about the class Integer, it has two methods toString, one static and the other one is not static.
Integer a = 5;
a.toString() // Is valid
Integer.toString(5); // Also is valid

There are 3 methods in java.lang.Integer class.
public static String toString(int i);
public static String toString(int i, int radix);
public String toString();
In your first case, you have used the 1st one ( a static method).
In your second case, you have used the 3rd one ( a non-static method).

I think you should know more information about inheritance in java. All classes extend Object class, that is why all classes have non-static toString() method and can override it. Class Integer have also static toString(int number) that returns String representation of int.

The Integer class has 2 methods as below;
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
getChars(i, size, buf);
return new String(buf, true);
}
AND
public String toString() {
return toString(value);
}
Both the methods are self explanatory. To Note second method calls the first one.
Integer.toString(1); // Calls method 1
Integer one = 1;
one.toString(); // Calls method 2

You may also want to lookup the Object's toString() method, which by the way gets inherited in every objects in java. This method is not static. The Integer's toString(int) method is only specific to the Integer class. This method is static (does not work on objects, but only on the Integer class). You will also want to check out the concepts of "method overriding", "method overloading" and "polymorphism". Here's a page containing almost exactly your question: https://www.geeksforgeeks.org/can-we-overload-or-override-static-methods-in-java/

Related

How do I get object and not address without using String/ toString?

I need to create my own String class called MyString without using default String class/vector API. I have to work on some required methods, and their return types are predetermined. I can add other methods as long as String is not used.
Expected use would be:
(at main) System.out.println(str.toLowerCase()) - returns lower case of str
When I want to work with toLowerCase() method with return type MyString, I can't return the object content but only return the address.
Normally, this problem would require modification of toString(), but since this method requires return type of String by default, I can't use modification of toString() for the assignment.
The assignment is supposed to be not so hard and should not require complex extensions. My constructor may be the problem, but I can't specify which part is.
Code
public class MyString {
private char value[];
MyString(char[] arr){
this.value = Arrays.copyOf(arr, arr.length);
}
...
MyString toLowerCase() { // can't change return type
for (int i =0; i<value.length; i++) {
if ((int)value[i] > 64 && (int)value[i] < 91) {
value[i] = (char) (value[i]+32);
}
}
return this; // this returns address, and I can't override toString
}
Problem with System.out.println(str.toLowerCase()) is it ends up calling PrintStream.println(Object o), but that method internally at some point calls o.toString() which uses code inherited from Object#toString() (since you couldn't override toString as it expect as result String which is forbidden in your project) which result in form TypeInfo#hexHashCode.
This means you can't use System.out.println(MyString).
BUT PrintStream (which instance is held by System.out) allows us to provide data to print in different forms. In this case you can use println(char[]). All you need to do is adding to MyString method like toCharArray() which would return (preferably a copy of) array of characters held by MyString class.
This way you can use it like System.out.println(myStringInstance.toCharArray()) so code from your main method would need to look like
System.out.println(str.toLowerCase().toCharArray());
// ^^^^^^^^^^^--this should return char[]
Firstly, the String class is an immutable type, i.e. the methods of String do not change the internal state (i.e. the char array), instead they return a new instance of type String.
To mirror that behavior you could implement something like this:
public MyString toLowerCase() {
char temp = new char[value.length];
// [...] Your code performing the actual logic on temp
return new MyString(temp);
}
The immutability (and its implications) of the String class is very important to understand in practice. For example, the following code procudes the intended result:
String word = "Word";
System.out.println("I can produce upper case (" + word.toUpperCase() + ") " +
"and lower case (" + word.toLowerCase() + ") " +
"without any side-effects on the original (" + word + ").");
However, it's not possible (without "hacky" solutions) to implement a method like this:
void shortenString(String inputAndOutput);
Second, the assignment expects that the class/method must be used as follows:
System.out.println(str.toLowerCase());
The attribute out is effectively a PrintStream, which offers (besides other methods) the following two:
println(Object x) - Prints an Object and then terminate the line.
println(String x) - Prints a String and then terminate the line.
If the method is called with an Object parameter, the internal implementation calls toString() on the given object, thus the only way to satisfy the requirement is to override this method. Unfortunately, this is not allowed by the assignment.
However, if it is not explicitly stated that the solution has to use java.lang.System, you could simply implement your own System class which accepts MyString, e.g.:
public class System {
public static class MyPrintStream /* optional: extends PrintStream */ {
public void println(MyString x) {
java.lang.System.out.println(x.getCharArray());
}
}
public static final out = new MyPrintStream();
}
This would allow you to use it exactly as described in the assignment:
import my.package.System;
public class Main {
public static void main(String[] args) {
// [...] Instantiate str
System.out.println(str.toLowerCase());
}
}

Anybody can tell me why this sentence works fine: System.out.println(p[i]);

Reading about cryptography, can not understand why the indicated line of code print data:
Provider p[] = Security.getProviders()
for (int i = 0; i < p.length; i++) {
System.out.println(p[i]); // <<<--- THIS LINE
why this print out data if it's not a string, it's a provider object
Thanks.
because println() accept many types, there are many signature of this method for example :
println(int i){...} //when you set int you call this
println(String i){...} //when you set String you call this
println(boolean i){...} //when you set boolean you call this
println(char i){...} //when you set char you call this
println(java.lang.Object i){...} //when you set Object you call this
... and so on
Take a look here java.lang.System
Basically, println() calls the Object's toString() method (i.e. Provider's toString()) to print the string representation of the object. (If Provider class has implemented toString() else the default toString() which is inherited from Object class)
Javadoc link : https://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html#println(java.lang.Object)
public void println(Object x)
Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().
Parameters:
x - The Object to be printed.
If Object (i.e.Provider in your case) class hasn't overridden default java.lang.Object's class toString() then what would it display?
It actually prints the class name + "#" symbol + the hex value of Object's hashcode method. (hashcode is also inherited from Object class)
public class Solution {
private int i;
public Solution() {
this.i = 10;
}
public static void main(String... args) {
Solution solution = new Solution();
System.out.println(solution);
// what is default toString prints?
System.out.println(Integer.toHexString(solution.hashCode()));
}
}
Sample Run
Solution#5eba06ff
5eba06ff
If Object (i.e.Provider in your case) has overridden default java.lang.Object's class toString() then what would it display?
It actually prints what you intent to print in toString().
public class Solution {
private int i;
public Solution() {
this.i = 10;
}
#Override
public String toString() {
return "Solution [i=" + i + "]";
}
public static void main(String... args) {
Solution solution = new Solution();
System.out.println(solution);
}
}
Sample Run
Solution [i=10]
Edit: All the classes in Java (not most of them as stated below, thanks for that) have toString() method which returns String representation of an object, the same applies for Provider class. When writing your own class you can override toString() method, meaning that you can write the method called toString() which will then be called whenever you try to access that object as a String (for example in System.out.println()).
Hope this helps, if not, just google toString().
In java, whenever we try to 1. print an object directly 2. or concat an object with string directly, the toString method is automatically called. By default, to string prints class name # hashcode
Like in your example, p[i].toString() is happening.
Since, object class is parent of every class directly or indirectly, all of its 11 functions (including toString() ) are inherited in the child class.
Provider class overrides the function toString() from the Hashtable<Object,Object> class. This overridden toString() returns a string with the name and the version number of this provider.
public class ExamineSecurity {
public static void main(String args[]) {
try {
Provider p[] = Security.getProviders();
for (int i = 0; i < p.length; i++) {
System.out.println(p[i]);
for (Enumeration e = p[i].keys(); e.hasMoreElements();)
System.out.println("\t" + e.nextElement());
}
}
catch (Exception e) {
System.out.println(e);
}
}
}
If we run this program with the 1.2 Sun security provider, we get this output:
Class Definition
SUN version 1.2
Alg.Alias.MessageDigest.SHA
Alg.Alias.Signature.SHAwithDSA
Alg.Alias.Signature.1.3.14.3.2.13
Alg.Alias.Signature.OID.1.2.840.10040.4.3
Alg.Alias.Signature.SHA-1/DSA
Alg.Alias.Signature.DSS
Alg.Alias.Signature.SHA1withDSA
Alg.Alias.Signature.OID.1.3.14.3.2.13
AlgorithmParameters.DSA
KeyFactory.DSA
Alg.Alias.Signature.1.2.840.10040.4.3
Alg.Alias.MessageDigest.SHA1
AlgorithmParameterGenerator.DSA
Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1
MessageDigest.MD5
Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1
MessageDigest.SHA-1
Alg.Alias.KeyPairGenerator.OID.1.3.14.3.2.12
Signature.DSA
Alg.Alias.KeyPairGenerator.1.3.14.3.2.12
Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1
Alg.Alias.Signature.1.3.14.3.2.27
Alg.Alias.Signature.SHA/DSA
Two things are readily apparent from this example. First, the strings that contain only an engine name and an algorithm implement the expected operations that we listed in Table 8-1. Second, as we mentioned in the section on the Provider class, security providers often leverage the fact that the Provider class is a subclass of the Properties class to provide properties that may make sense only to other classes that are part of the provider package. Hence, the signature algorithm 1.3.14.3.2.13 may make sense to one of the classes in the Sun security provider,but it is not a string that will necessarily not make sense to other developers. In fact, those aliases--including the ones that are prefaced by OID--do have meanings within the cryptography standards world, but for our purposes we'll stick with the standard algorithm names that we listed earlier.
The toString() method of the class Provider seems to be implemented.

Java Method Confusion

In Java, when for example you say string1.compareTo(string2), how is the compareTo method accessing the string1. I see the method takes in the second string but how does it compare it to the first if it is not getting passed along?
compareTo() is a member function of Class String, this means that for invoking this function you need an Object of Type String. So when you say string1.compareTo(string2) , this means that you are invoking compareTo() function on the String object 'string1' and passing 'string2' as the argument.
I think this little 'illustration' could help you
Class String {
public int CompareTo(String string2)
{
if (this==string2) return 1; //The == is completely wrong here but it gives you an idea on how it works
else return 0;
}
}
When you call string1.CompareTo(string2); in the method, this will reference the object itself, so here it references string1

Return two Strings from method

I'm a beginner in Java programming, and I'm trying to make a voting machine program, where you can vote for Republicans or Democrats. My question is, how can I edit my method so I would be able to return two strings with two distinct values?
For example, look at my code all the way in the bottom. It's wrong, but I wanted the tester to be able to print out Democrats: (some number) and Republicans: (some number) in one method. How can I do that?
import java.lang.String;
public class VotingMachine1 {
private double Democrats;
private double Republicans;
public VotingMachine1() {
Democrats = 0;
Republicans = 0;
}
public void voteRepublican() {
Republicans = Republicans + 1;
}
public void voteDemocrat() {
Democrats = Democrats + 1;
}
public void clearMachineState() {
Republicans = 0;
Democrats = 0;
}
//this is where I'm having difficulties. I know its wrong
public double getTallies() {
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
}
No return is necessary there, since you aren't leaving a function. To do what you seem to want to do, just replace that last method with the following:
public void getTallies()
{
System.out.println("Democrats: " + Double.toString(Democrats));
System.out.println("Republicans: " + Double.toString(Republicans));
}
Also, since your votecounts should only ever be integers, there's no reason to declare them as doubles instead of ints.
What you are looking for here is a format string. A format string is used when you know what your output should look like, and only have a few "holes" where unknown data should be filled in. To output your data using format strings, you would use the System.out.format(String, Object...) method:
System.out.format("Democrats: %f\n", Democrats);
System.out.format("Republicans: %f\n", Republicans);
In this case, the %f indicates that a floating-point number (since your variables are declared as double) will be printed instead of the %f. However, you may wish to consider declaring them as int (or long) instead, in which case you would use %d instead of %f in the format strings.
Finally, you ought to change your getTallies() method to return void instead of double, as you are printing the values, not returning them.
Your code and your description are so contradictory, it is not clear that you even know what you are trying to do. I believe that this is the real root of your problems.
Here goes:
public double getTallies()
{
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
First, your question says that you want to "return two strings with two values" ... but you have declared the method as returning one double.
Next, your code is printing values ... not returning them.
You've also made some major mistakes at the syntactic level, largely (I believe) because you are trying to do contradictory things:
return Republicans is not a valid Java expression, so you can't use it as a argument to the println method.
The println method can't be called with two arguments, as your code is trying to do. There is a zero argument version and a number of one argument overloads ... but no overloads with two or more arguments.
Basically, you need to start by making up your mind about what this method is supposed to do. Is it supposed to:
return the tallies (as two doubles)?
return a string representing the two tallies?
return nothing ... and output the two tallies to standard output?
do something else?
Once you've made up your mind:
code the method to do what you've decided it should do, and
chose a method name that correctly reflects what it is supposed to do. Hint: a method that starts with get is conventionally a "getter" that returns the attribute or attributes themselves ... not a String rendering.
double is a bad choice of type for a vote count too:
You cannot have a fractional vote.
You want to represent vote counts precisely and floating point types (like double) are not precise. (Or at least, not in the sense that you require.)
When you attempt to format or output a double, the resulting character string is likely to include a pesky decimal point ... or worse.
You should use int or long instead of double.
Finally, this is a serious Java style violation, and should get you a significant penalty if your marker is paying attention.
private double Democrats;
private double Republicans;
Variable names in Java should start with a LOWER CASE letter.
A few more random comments:
import java.lang.String; is superfluous as all classes in package java.lang are automatically imported in every Java source file.
Votes can not be fractional. People can't vote 0.75 candidate A, and 0.25 candidate B. If you use integer datatypes (int or long), you will be reflecting this fact better. Also, you will be saving yourself a lot of headache when you start obtaining results like 379857.999999. This is because floating point types have a better range, but worse precision (especially noticeable when working with pure integers).
According to Java usual naming conventions, variable names should start with a lowecase letter.
A better name for function getTallies is printTallies.
For output purposes, it's much better to use string formatting than concatenation. Some advantages are: multiple formats supported, ease of use, and internationalization.
Putting all together:
private int democratVotes;
private int republicanVotes;
public void printTallies() {
System.out.format("Democrats: %,d%n",democratVotes);
System.out.format("Republicans: %,d%n",republicanVotes);
}
In this particular case, votes will be printed with thousand separation (ex: 3,345,623 instead of 3345623). Check Java's Formatting Numeric Print Output tutorial.
Thinking better about it, there are some alternatives where getTallies would effectively be returning some form of value:
1) Make it to return a String with both tallies. It would be hard and inefficient to separate the tallies later, though.
public String getTallies() {
return "Democrats: %,d votes. Republicans: %,d votes.%n".format(democratVotes,republicanVotes);
}
2) Make it to return an array.
public int[] getTallies() {
return new int[2]{ democratVotes, republicanVotes };
}
public int[] getTallies1() { // Same as getTallies, but written step by step.
int[] result= new int[2] ;
result[0]= democratVotes ;
result[1]= republicanVotes ;
return result ;
}
3) Make it to return a class.
public VotingMachineResults getTallies() {
return VotingMachineResults(democratVotes,republicanVotes) ;
}
public static class VotingMachineResults {
private int democratVotes;
private int republicanVotes;
public VotingMachineResults(democratVotes,republicanVotes) {
this.democratVotes= democratVotes ; // `this` required to disambiguate field democratVotes from parameter democratVotes.
this.republicanVotes= republicanVotes ;
}
public int getDemocratVotes() {
return democratVotes ;
}
public int getRepublicanVotes() {
return republicanVotes ;
}
}
As you can see, this class is very similar to VotingMachine1, but it does not accept internal state changes. It is a "value" class.
In Java, you concatenate Strings with the + operator. Proper syntax for what you were trying to do looks like this:
System.out.println("Democrats: " + Democrats);
System.out.println("Republicans: " + Republicans);
A return statement is only used when you want to return some object or value to a method that called your current method. It is not appropriate in this place since you're only passing a value to another method (println()).
ALSO, you need to fix your getTallies() method. Make it return void instead of double since you aren't returning anything.
Here's something completely different: why not override toString()?
Presumably, any instance of VotingMachine1 will apply for all votes that you care about for that instance. That is to say, you don't create a new instance of a VotingMachine1 every time someone casts a vote.
So, what you can do is override the toString() method. We'll also use String.format() to handle the numerical values.
#Override
public String toString() {
// assumes that Democrats and Republicans are declared as int
// since it's pointless to indicate percentages of a vote
return String.format("Democrats: %d\nRepublicans: %d", Democrats, Republicans);
}
Now, whenever you vote, you can use the toString() method to get the information (which is called whenever one does System.out.println(object).
VotingMachine1 voter = new VotingMachine1();
voter.voteDemocrat();
voter.voteRepublican();
System.out.println(voter);
/* This prints:
Democrats: 1
Republicans: 1
*/
A less specific answer to your question would be to return an Object called (say) Votes
public class Vote {
int democratVotes
int republicanVotes
}
and then make your VotingMachine class simply return an instance of this object (suitably changed to make it immutable).
On my project we have created a generic version of this called a Tuple that returns a pair of values in a single object - it has an overloaded toString method for easy printing.
you can return an array with [0] and [1] as key and devide it on the basis of your need..
like
returnArray[0]="first string";
returnArray[1]="second string";
and use it ur way...

How does System.out.print() work?

I have worked with Java for a quite a long time, and I was wondering how the function System.out.print() works.
Here is my doubt:
Being a function, it has a declaration somewhere in the io package. But how did Java developers do that, since this function can take in any number of arguments and any argument types no matter how they are arranged? e.g:
System.out.print("Hello World");
System.out.print("My name is" + foo);
System.out.print("Sum of " + a + "and " + b + "is " + c);
System.out.print("Total USD is " + usd);
No matter what is the datatype of variables a, b, c, usd, foo or how they are passed, System.out.print() never throws an error.
For me, I have never worked on any project where the requirement was like this. Provided, if I get a requirement like this, I really don't know how to solve it.
Can anyone explain to me how it's done?
System.out is just an instance of PrintStream. You can check its JavaDoc. Its variability is based on method overloading (multiple methods with the same name, but with different parameters).
This print stream is sending its output to so called standard output.
In your question you mention a technique called variadic functions (or varargs). Unfortunately that is not supported by PrintStream#print, so you must be mistaking this with something else. However it is very easy to implement these in Java. Just check the documentation.
And if you are curious how Java knows how to concatenate non-string variables "foo" + 1 + true + myObj, it is mainly responsibility of a Java compiler.
When there is no variable involved in the concatenation, the compiler simply concatenates the string. When there is a variable involved, the concatenation is translated into StringBuilder#append chain. There is no concatenation instruction in the resulting byte code; i.e. the + operator (when talking about string concatenation) is resolved during the compilation.
All types in Java can be converted to string (int via methods in Integer class, boolean via methods in Boolean class, objects via their own #toString, ...). You can check StringBuilder's source code if you are interested.
UPDATE: I was curious myself and checked (using javap) what my example System.out.println("foo" + 1 + true + myObj) compiles into. The result:
System.out.println(new StringBuilder("foo1true").append(myObj).toString());
Even though it look as if System.put.print...() take a variable number of arguments it doesn't. If you look closely, the string is simply concatenated and you can do the same with any string. The only thing that happens is, that the objects you are passing in, are implicitily converted to a string by java calling the toString() method.
If you try to do this it will fail:
int i = 0;
String s = i;
System.out.println(s);
Reason is, because here the implicit conversion is not done.
However if you change it to
int i = 0;
String s = "" + i;
System.out.println(s);
It works and this is what happens when using System.put.print...() as well.
If you want to implement a variable number of arguments in java to mimimc something like C printf you can declare it like this:
public void t(String s, String ... args)
{
String val = args[1];
}
What happens here is that an array of Strings is passed in, with the length of the provided arguments. Here Java can do the type checking for you.
If you want truly a printf then you have to do it like this:
public void t(String s, Object ... args)
{
String val = args[1].toString();
}
Then would you have to cast or interpret the arguments accordingly.
It is a very sensitive point to understand how System.out.print works.
If the first element is String then plus(+) operator works as String concate operator. If the first element is integer plus(+) operator works as mathematical operator.
public static void main(String args[]) {
System.out.println("String" + 8 + 8); //String88
System.out.println(8 + 8+ "String"); //16String
}
Evidently, the compiler was made in a confusing way although the compiler developers thought they added some smartness. The true smartness they should really add is to look entire argument and interpret + operator consistently. For example, System.out.println(1+2+"hello"+3+4); should output 3hello7 instead of 3hello34
I think you are confused with the printf(String format, Object... args) method. The first argument is the format string, which is mandatory, rest you can pass an arbitrary number of Objects.
There is no such overload for both the print() and println() methods.
Its all about Method Overloading.
There are individual methods for each data type in println() method
If you pass object :
Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().
If you pass Primitive type:
corresponding primitive type method calls
if you pass String :
corresponding println(String x) method calls
You can convert anything to a String as long as you choose what to print. The requirement was quite simple since Objet.toString() can return a default dumb string: package.classname + # + object number.
If your print method should return an XML or JSON serialization, the basic result of toString() wouldn't be acceptable. Even though the method succeed.
Here is a simple example to show that Java can be dumb
public class MockTest{
String field1;
String field2;
public MockTest(String field1,String field2){
this.field1=field1;
this.field2=field2;
}
}
System.out.println(new MockTest("a","b");
will print something package.Mocktest#3254487 ! Even though you only have two String members and this could be implemented to print
Mocktest#3254487{"field1":"a","field2":"b"}
(or pretty much how it appears in the debbuger)
#ikis, firstly as #Devolus said these are not multiple aruements passed to print(). Indeed all these arguments passed get
concatenated to form a single String. So print() does not teakes multiple arguements (a. k. a. var-args). Now the concept that remains to discuss is how print() prints any type of the arguement passed
to it.
To explain this - toString() is the secret:
System is a class, with a static field out, of type PrintStream. So you're calling the println(Object x) method of a
PrintStream.
It is implemented like this:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
As wee see, it's calling the String.valueOf(Object) method. This is implemented as follows:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
And here you see, that toString() is called.
So whatever is returned from the toString() method of that class, same gets printed.
And as we know the toString() is in Object class and thus inherits a default iplementation from Object.
ex: Remember when we have a class whose toString() we override and then we pass that ref variable to print, what do you see printed? - It's what we return from the toString().
The scenarios that you have mentioned are not of overloading, you are just concatenating different variables with a String.
System.out.print("Hello World");
System.out.print("My name is" + foo);
System.out.print("Sum of " + a + "and " + b + "is " + c);
System.out.print("Total USD is " + usd);
in all of these cases, you are only calling print(String s) because when something is concatenated with a string it gets converted to a String by calling the toString() of that object, and primitives are directly concatenated.
However if you want to know of different signatures then yes print() is overloaded for various arguments.

Categories