Related
So this first code returns the memory address of the integer array, but I want it to print out the actual array.
import java.util.Arrays;
public class FinalsReview{
int[] list = new int[]{12, 435,546, 7, 24, 4, 6, 45, 21, 1};
public static void main(String[]args){
FinalsReview hello = new FinalsReview();
System.out.print(hello.create());
}
public int[] create(){
Arrays.toString(list);
return list;
}
}
However, the following code prints the actual array.
import java.util.Arrays;
public class FinalsReview{
int[] list = new int[]{12, 435,546, 7, 24, 4, 6, 45, 21, 1};
public static void main(String[]args){
FinalsReview hello = new FinalsReview();
hello.create();
}
public void create(){
System.out.println(Arrays.toString(list));
}
}
Why does the first one return the memory address?
it is not memory address, it is the hashCode() and classname that is how toString() is defined in Object, when you don't specify toString() method for int[] class you inherit it from Object
and that is implemented like
public String toString() {
return getClass().getName() + "#" + Integer.toHexString(hashCode());
}
while this Arrays.toString(list) is explicitly iterates over the Collection and printing value of each element
and why that from http://bugs.java.com/view_bug.do?bug_id=4168079
One caveat: the toString() method is often used in printing diagnostics.
One would have to be careful if very large arrays were involved. The
Lisp language deals with this using the print-level/print-length mechanism.
Something similar would be needed in Java as well. In practice, the
'toString' method provided in every class should be preferred as the
brief option suitable for use in concise diagnostics, and a more verbose
representation provided by additional application-specific conversion methods
if needed by the application logic.
Regardless of its technical merit, however, it is doubtful that we can make
such a change at this late date due to compatibility/stability concerns.
william.maddox#Eng 1998-08-31
I concur. It would definitely have been the right thing in 1.0, or
maybe even 1.1, but it's almost certainly too late for all of these changes
except perhaps the toString change. One consolation is that it's amazingly easy
It's because you're returning the array from the method create, and when you attempt to print it, the display is what Jigar Joshi described. Simply calling Arrays.toString(list) will not reformat the array so that it will give the output that you expect when you try to print it.
If you want it to print the elements of the array, have your method return String instead, and use return Arrays.toString(list).
Arrays.toString(list) merely returns a String that is being printed at System.out.println(Arrays.toString(list)), however in your first method you are just returning the Array without saving the result of Arrays.toString(list). You're only printing yourList.toString(), so to say:
int[] myList = ... //initialize
String s = Arrays.toString(list); //Save the returned String in a variable
System.out.println(myList); //Prints myList.toString()
System.out.println(s); //Prints out the contents of the array
The line
System.out.print(hello.create());
is evaluated by first invoking the create() method, the passing its return value (a reference to an object of type int[]) to the print() method of System.out. That method's Javadoc reads:
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().
and the Javadoc of String.valueOf() reads:
if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.
Ok, our array reference isn't null, so what does its toString method do? The answer is in section 10.7 of the Java Language Specification, which reads:
The members of an array type are all of the following:
The public final field length, which contains the number of components of the array. length may be positive or zero.
The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].
A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared.
All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
Therefore, the toString method must be inherited from Object. The Javadoc of Object.toString reads:
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
... and that's why you see the type and hashCode of the array object when you print your array. (Incidentally, a hash code is not quite the same as a memory address. For one, several objects may have the same hash code; otherwise java would be limited to about 4 billion objects per application).
That's why Arrays.toString is a useful method to have, as it returns a String with the contents of the array. (You do invoke this method in create(), and it builds that String, but then you don't do anything with that String object, which is why it isn't printed).
In your first example, you are running Arrays.toString(list); but youare throwing away the result (a single String), and returning the original value of list. System.out.println is then trying to convert the whole int[] array into a string, which it doesn't know how to do, so it is giving you the unexpected output.
In the second example, you are running the same utility function, but this time passing its output to System.out.println. The input to System.out.println is now the string you wanted.
What you need to do is make the create function return the String given by Arrays.toString(list), rather than the original int[].
Can you help me? What does int[]... arrays mean in Java?
Example:
public static int[] concat(int[]... arrays) {
int length = 0;
for (int[] array : arrays) {
length += array.length;
}
That is called varargs.. notation,
So that you can pass individual int[] objects to that method,, without worrying of no.of arguments.
When you write
public static int[] concat(int[]... arrays) {
Now you can use that method like
Classname.concat(array1,array2,array3) //example1
Classname.concat(array1,array2) //example2
Classname.concat(array1,array2,array3,array4) //example3
A clear benefit is you need not to prepare an array to pass a method. You can pass values of that array directly.
It means that the concat function can receive zero or more arrays of integers (int[]). That's why you can loop over the arrays argument, accessing one of the arrays contained in each iteration - if any. This is called variable arguments (or varargs).
Check this other question for more info.
This means, that you can pass zero, one or more arrays of int (int[]) to your method. Consider following example
public void method(String ... strings)
can be called as
method()
method("s")
method("s", "d")
...
So your method can be called as
concat()
concat(new int[0])
concat(new int[0], new int[0])
...
This means that you can pass the method any number of int[] objects:
concat(new int[]{1,2});
concat(new int[]{1,2}, new int[]{3,4,5});
concat(new int[]{1}, new int[]{3,4,5,6}, new int[]{1,1,1,1,1,1,1});
Why this is useful? It's clear why :)
The ... is the most important part, it means you can have an unlimited amount of integers passed in and it is just accessed via the array, so you could call it as:
concat(1,2,3,4,5) or concat(1)
Most languages have this sort of feature, some call it var args others call it params.
varargs ("...") notation basically informs that the arguments may be passed as a sequence of arguments (here - ints) or as an array of arguments. In your case, as your argument is of type "array of int", it means arguments may be passed as a sequence of arrays or as an array of arrays of int (note that array of arrays is quite equivalent to multidimensional array in Java).
For example you have a method:
void functionName (Object objects...)
{
Object object1=objects[0];
Object object2=objects[1];
Object object3=objects[2];
}
You can use your method as:
Object object1,object2,object3;
functionName(object1,object2,object3);
Using Variable Arguments
The ellipsis (...) identifies a variable number of arguments, and
is demonstrated in the following summation method.
public static int[] concat(int[]... arrays)
Use method
concat(val1, val2, val3);
concat(val1, val2, val3, val3);
I know that arrays in java extends Objects,So why passing them as params doesn't work.
public static void main(String[] args) {
foo(new Integer[]{1, 2, 3}); // 1
foo(new int[]{1,2,3}); //2
}
static void foo(Object... params) {
System.out.println(params[0]);
}
moreover,why it doesn't treat the array as a single parameter (line 1)
Output from running the above is:
1
[I#3e25a5
In java every function with (X... ) signature takes an array of X as parameter.
In your first example you get warning that you're passing the array of Integers as vararg Object without a cast. Java is clever enough to thing that you probably wanted to pass it as Object[] instead of a single Object. If you add a cast to Object[] the warning disappears.
In the second example the array is pàssed as only THE FIRST vararg, as every array is an object. It can't be passed as an array of object, because it's an array of primitives.
Arrays of any type are objects as you can verify running this snippet of code
public class Test{
public static void test(Object a) {
System.out.println("ok");
}
public static void main(String args[]){
int[] i = {1,2,3,4};
test(i);
}
}
It prints "ok", which means that int[] is an Object.
~
I just tried your code, and I get:
1
[I#71f6f0bf
The thing is, your method takes an array of Object by varargs. So, for the first call, params is an array of 3 elements containing each individual Integer. However, ints are not Objects (int's Wrapper class, Integer, is, but int isn't), so for the second call, params is an array of a single element containing the actual array object. That gibberish above is the output of an array's toString() method.
If you would have replace the varargs call with a Object[], the second call would not have compiled, because an int[] is not a Object[].
Object... interprets an array as a list of arguments, not as a single object.
Why not use a Set as a container instead?
I have a method with the following signature:
public void foo(String... params);
So all of these calls are valid:
foo("Peter", "John");
foo(new String[] { "Peter", "John" });
But why is this one not valid?
foo("Peter", new String[] { "John" });
From the docs:
The three periods after the final
parameter's type indicate that the
final argument may be passed as an
array or as a sequence of arguments.
You can't pass an argument and an array.
That's because in fact you try to pass Array containing String and another Array.
Because it's not the same thing. You just can't mix and match like that. The invalid one in your example would work with a function signature like this:
public void foo(String head, String ... tail)
This method
public void foo(String... params);
is just a convenience version of this one:
public void foo(String[] params);
And hence you can call it with a variable number of Strings (that will be converted to a String array by the compiler) or a String array, but a combination won't work, by design.
Think about it. What if you had a method like this:
public void foo(Object... objects);
And tried to call it like this:
foo("bar", new Object[] { "baz" });
Should the Object[] in the second position be treated as a single Object in the varargs call or should it be "expanded"? This would lead to very confusing behavior.
With a third party API I observed the following.
Instead of using,
public static string getString(){
return "Hello World";
}
it uses something like
public static void getString(String output){
}
and I am getting the "output" string assigned.
I am curious about the reason of implementing such functionality. What are the advantages of using such output parameters?
Something isn't right in your example.
class Foo {
public static void main(String[] args) {
String x = "foo";
getString(x);
System.out.println(x);
}
public static void getString(String output){
output = "Hello World"
}
}
In the above program, the string "foo" will be output, not "Hello World".
Some types are mutable, in which case you can modify an object passed into a function. For immutable types (such as String), you would have to build some sort of wrapper class that you can pass around instead:
class Holder<T> {
public Holder(T value) {
this.value = value;
}
public T value;
}
Then you can instead pass around the holder:
public static void main(String[] args) {
String x = "foo";
Holder<String> h = new Holder(x);
getString(h);
System.out.println(h.value);
}
public static void getString(Holder<String> output){
output.value = "Hello World"
}
That example is wrong, Java does not have output parameters.
One thing you could do to emulate this behaviour is:
public void doSomething(String[] output) {
output[0] = "Hello World!";
}
But IMHO this sucks on multiple levels. :)
If you want a method to return something, make it return it. If you need to return multiple objects, create a container class to put these objects into and return that.
I disagree with Jasper: "In my opinion, this is a really ugly and bad way to return more than one result".
In .NET there is a interesting construct that utilize the output parameters:
bool IDictionary.TryGet(key, out value);
I find it very usefull and elegant. And it is the most convenient way to aks if an item is in collection and return it at the same time. With it you may write:
object obj;
if (myList.TryGet(theKey, out obj))
{
... work with the obj;
}
I constantly scold my developers if I see old-style code like:
if (myList.Contains(theKey))
{
obj = myList.Get(theKey);
}
You see, it cuts the performance in half. In Java there is no way to differentiate null value of an existing item from non-existance of an item in a Map in one call. Sometimes this is necessary.
This functionality has one big disadvantage - it doesn't work. Function parameters are local to function and assigning to them doesn't have any impact outside the function.
On the other hand
void getString(StringBuilder builder) {
builder.delete(0, builder.length());
builder.append("hello world");
}
will work, but I see no advantages of doing this (except when you need to return more than one value).
Sometimes this mechanism can avoid creation of a new object.
Example:
If an appropriate object exists anyhow, it is faster to pass it to the method and get some field changed.
This is more efficient than creating a new object inside the called method, and returning and assigning its reference (producing garbage that needs to be collected sometime).
String are immutable, you cannot use Java's pseudo output parameters with immutable objects.
Also, the scope of output is limited to the getString method. If you change the output variable, the caller won't see a thing.
What you can do, however, is change the state of the parameter. Consider the following example:
void handle(Request r) {
doStuff(r.getContent());
r.changeState("foobar");
r.setHandled();
}
If you have a manager calling multiple handles with a single Request, you can change the state of the Request to allow further processing (by other handlers) on a modified content. The manager could also decide to stop processing.
Advantages:
You don't need to return a special object containing the new content and whether the processing should stop. That object would only be used once and creating the object waste memory and processing power.
You don't have to create another Request object and let the garbage collector get rid of the now obsolete old reference.
In some cases, you can't create a new object. For example, because that object was created using a factory, and you don't have access to it, or because the object had listeners and you don't know how to tell the objects that were listening to the old Request that they should instead listen to the new Request.
Actually, it is impossible to have out parameters in java but you can make a work around making the method take on a de-reference for the immutable String and primitives by either writing a generic class where the immutable is the generic with the value and setter and getter or by using an array where element 0 (1 in length) is the value provided it is instantiate first because there are situations where you need to return more than one value where having to write a class just to return them where the class is only used there is just a waste of text and not really re-usable.
Now being a C/C++ and also .Net (mono or MS), it urges me that java does not support at least a de-reference for primitives; so, I resort to the array instead.
Here is an example. Let's say you need to create a function (method) to check whether the index is valid in the array but you also want to return the remainding length after the index is validated. Let's call it in c as 'bool validate_index(int index, int arr_len, int&rem)'. A way to do this in java would be 'Boolean validate_index(int index, int arr_len, int[] rem1)'. rem1 just means the array hold 1 element.
public static Boolean validate_index(int index, int arr_len, int[] rem1)
{
if (index < 0 || arr_len <= 0) return false;
Boolean retVal = (index >= 0 && index < arr_len);
if (retVal && rem1 != null) rem1[0] = (arr_len - (index + 1));
return retVal;
}
Now if we use this we can get both the Boolean return and the remainder.
public static void main(String[] args)
{
int[] ints = int[]{1, 2, 3, 4, 5, 6};
int[] aRem = int[]{-1};
//because we can only scapegoat the de-ref we need to instantiate it first.
Boolean result = validate_index(3, ints.length, aRem);
System.out.println("Validation = " + result.toString());
System.out.println("Remainding elements equals " + aRem[0].toString());
}
puts: Validation = True
puts: Remainding elements equals 2
Array elements always either point to the object on the stack or the address of the object on the heap. So using it as a de-references is absolutely possible even for arrays by making it a double array instantiating it as myArrayPointer = new Class[1][] then passing it in because sometimes you don't know what the length of the array will until the call going through an algorithm like 'Boolean tryToGetArray(SomeObject o, T[][] ppArray)' which would be the same as in c/c++ as 'template bool tryToGetArray (SomeObject* p, T** ppArray)' or C# 'bool tryToGetArray(SomeObject o, ref T[] array)'.
It works and it works well as long as the [][] or [] is instantiate in memory first with at least one element.
in my opinion, this is useful when you have more than one result in a function.