please explain this output that using explicit cast to Object - java

class VarArgs {
public static void printArray(Object... args) {
for (Object obj : args)
System.out.print(obj + " ");
System.out.println();
}
public static void main(String[] args) {
printArray( new Integer[] { 1, 2, 3 });
}
}
The console's output is:
[Ljava.lang.Integer;#1888759
just want to know what is this output. The supposed castiing was via Object[] and that gives 1,2,3 as output, but when I use Object for casting I get this output

You can use
Arrays.toString(new Integer[]{1,2,3});
to view the actual contents of the array.
Or cast new Integer[]{1,2,3} to Object[] instead of Object, i.e:
printArray((Object[])new Integer[]{1,2,3});

Explanation of what is happening in your code:
When you are calling the printArray method you are casting your array to an Object so in fact you are passing just one object (not an array).
The foreach loop in the printArray method iterates only once as only one argument has been passed to the printArray method - the Integer[] {1,2,3} array.
Therefore When your code is calling toString, the toString from the Array class is called, not the toString from the Integer class as you might expect.
Finally the result you got: [Ljava.lang.Integer;#1888759 is caused by the lack of the implementation of the toString method in the array classes in Java.
To fix the issue in your code:
Replace:
printArray((Object)new Integer[]{1,2,3});
with:
printArray((Object[])new Integer[]{1,2,3});
To print the content of an array call:
Arrays.toString(new Integer[]{1,2,3});

As Marco said, this uses the default toString method of an Object, which is its (virtual) memory address.
I would recommend using the Arrays.toString method here
With regards to your use of variable arguments - try disassembling the class file by running
javap -verbose VarArgs
to see what this compiles down into - you should see that your integer array is being passed as the single element of an array.

That is not the same as passing an array! That is the same as passing a variable length of parameters, so the method treats the array as one object, not an array of objects, hence the printout.
public static void printArray(Object[] args) {
for (Object o : args) {
System.out.println(o);
}
}
Object[] objects = new Integer[] { 1, 2, 3, 4 };
printArray(objects);
Notice that you need to use the wrapper for int, primitive types are not subclasses of object.

Related

One dimensional array in Java

When I run this code on cmd prompt with statement :
java Test A
output is
a
b
c
Wasn't it suppose to result in an error since dimension of args is 1 whereas dimension of x is 3 (args=x).
class Test
{
public static void main(String args[])
{
String[] x={"a","b","c"};
args=x;
for(String i: x)
{
System.out.println(i);
}
}
}
well, the array variable in java is only a reference, so if you give it another reference for a String array it will accept it, so the range of values the array variable(args) accepts is the references to String arrays at memory, it's like changing the value of an integer from 1 to 3, it's ok because they're both valid, and in the range that the integer accepts.
It will not result in an error because your object is not final and you are not changing the array object.
here
double[] data = new double[5]{2, 4, 5, 6, 8} // data can change but the instance of the class cant change
double[] data = new double[7] // here you are changing the data but not the object i.e the created instance of the object does not change but the instance the data(the variable) is holding changes
I hope you got your answer

Failed to pass array as parameter in java

I have a method doSomething() which accept Array as parameter. When I pass array like bellow:
package org.my;
public class ArrayMistry {
public static void main(String ... args) {
doSomething({1,2});// Compilation Error
}
public static void doSomething(int[] params) {
}
}
I am getting compilation error:
Exception in thread "main" java.lang.Error: Unresolved compilation
problems: Syntax error on token "doSomething", # expected before
this token Syntax error, insert "enum Identifier" to complete
EnumHeader Syntax error, insert "EnumBody" to complete
BlockStatements
at org.my.ArrayMistry.main(ArrayMistry.java:6)
Note:
if I pass as bellow then its OK:
public static void main(String ... args) {
int[] p = {1,2};
doSomething(p);// no Error
doSomething(new int[]{1,2});// no Error
}
Arrays are passed by reference. You need to create an array object with [1,2] and pass the reference of that created object to dosomething. The new keyword allocates space for the creation of this int array.
int[] arr = new int[]{1,2};
doSomething(arr);
It's because you aren't declaring {1, 2} as a new array. It must be declared as new int[]{1,2} to function properly, otherwise you are not creating an array.
You have to make an array to pass into a method because you initialized the method that way. The reason this doSomething({1,2}); doesn't work is because the array has not been initialized and {1, 2} is not an array, it is just some numbers in a parenthesis. if you wanted to send an array you have to do something like this
int[] p = {1,2};
doSomething(p);
Your method doSomething() specifically accepts an array of integers as its parameters.
Note in both cases where it worked, you either passed an existing array, or created a new one when passing it in.
In your original example, you are passing an arbitrary set of numbers with no memory reserved, or type specified.
Another way to solve the problem is by passing a reference as a parameter to the function like this:
doSomething(new int[]{1,2});

Generic method to print arrays in java

I am trying to write a generic method printAll which prints an array of integer or character.
Here's the code:
public static void main(String[] args) {
char cArray[] = {'a','b','c','d'};
int iArray[] = {1,2,3,4};
printAll(iArray); // Error at this line--refer below the code
}
public static <T> void printAll(T[] t){
for(T x:t) {
System.out.println(x);
}
}
Error: Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous tree type: <.any>
printAll(T[] t) will not accept primitive type arrays. You need to pass arrays of the respective wrapper types:
Character cArray[] = {'a','b','c','d'};
Integer iArray[] = {1,2,3,4};
But, you don't need to frame your own method. Just use the already existing - Arrays.toString() method, which is overloaded for different types of primitive arrays, and Object[] array.
Do not reinvent the wheel, use Arrays.toString or Arrays.deepToString. The former already is overloaded to support arrays of primitive (as noted in the first link that receives a char[]), the latter works only on arrays of class references objects.
You cannot use primitive types with generics. Use Integer (or the corresponding reference type)
Integer iArray[] = {1,2,3,4};
printAll(iArray);
You can always overload the printAll method for each of the primitive types.
I don't believe in doing peoples work for them, more to inform and teach how it can be done.
one easy and simple way to print arrays in java will be done through converting the array to a string then print. This works best as array lists. This can then be manipulated to print in a better format.
for example make an array list and add some values:
ArrayList<String> Array = new ArrayList<String>();
Array.add(1)
Array.add(2)
Array.add(3)
Array.add(4)
Array.add(5)
Then from here this can be printed by changing it to a string:
String str = Array.toString()
System.out.println(str);
this will print the following:
[1,2,3,4,5]
you can then change the format of this by using replaceALL on the string before you print it:
String str = Array.toString().replaceAll("[\\[\\]]","")
This will now give:
1,2,3,4,5
That is pretty much it, from here you could add extra things like System.lineSeparator which you would use to replace thhe "," with a new line.
String str = Array.toString().replaceAll("[\\[\\]]","").replaceAll(",",System.lineSeparator());
This would make it print out like:
1
2
3
4
5
class Generic {
public static<T> void printArray(T[] list) {
for(T in : list) {
System.out.println(in);
}
}
public static void main(String[] args) {
String[] lit=new String[3];
lit[0]="aiq";
lit[1]="abusov";
lit[2]="java";
printArray(lit);
}
}

Passing parametrized ArrayList to a function in java

I have the following function.
func(ArrayList `<String>`[] name) { ........ }
The function fills the ArrayList[]. (I don't want to return the ArrayList[])
However, in the caller function the ArrayList[] obtained has all ArrayLists as null.
For eg.
name = new ArrayList[num];
func(name);
System.out.println(name[0]);
I get NullPointerException at line 3. Is this because of line 1, i.e. I am not parametrizing? If yes, is there another way this can be done? Because java does not allow creating a generic array of parametrized ArrayList.
That is obviously not your real code, but you're creating an array of ArrayLists, which probably isn't what you want. You can probably just do:
ArrayList<String> name = new ArrayList(num);
func(name);
System.out.println(name.get(0));
Note that when you create the ArrayList, you're only specifying the initial capacity, not the size (number of initial items). It will have an initial size of 0. Your func can just call add to add items.
Even better (no typing errors):
ArrayList<String> name = new ArrayList<String>();
I recommend not bothering with the initial capacity argument (num) - just leave it blank and it will work perfectly. But do bother with the generic type of String in the constructor, or the compiler will complain.
If you want to know how to use the ArrayList (for example, why to use the get() function), you should look at the documentation.
For arrays in Java when you create it all of the elements are either 0, false, or null depending in their type.
So:
final List<String>[] foo;
foo = new ArrayList<String>[10];
foo[0].add("hello"); // crash
that crashes because foo = new ArrayList<String>[10]; allocates enough room to hold 10 ArrayList<String> but it sets all of the values to null. So you need one additional step:
for(int i = 0; i < foo.length; i++)
{
foo[i] = new ArrayList<String>();
}
I haven't compiled the code, but pretty sure it is all correct. You would do that between step 1 and 2 of your program.
I am guessing a bit because your code isn't quite accurate (it would not generate a null pointer as written as near as I can tell).
EDIT:
You would do the new in the method and the for loop with the assignments could be done inside of the method. I prefer to allocate and initialize in the same place (less confusing) but you can split it up if you needed to.
The problem you are encountering is due to the fact that in Java, parameters to methods are passed by value. What this means, is that every parameter is effectively "copied" into the method, meaning that any assignments you make to the parameters are only visible within the method, and cannot be seen by the caller.
Going by your example, you're passing in a null reference to an array of List<String>'s. This reference is then "copied" into the func() method, and when func then assigns something to this variable, it is only the local variable that is being updated, and not the reference held by your calling code.
Here's some compilable code (based on your example) that demonstrates the problem:
public class Main {
public static void main(String[] args) {
List<String>[] array = null;
fill(array);
System.out.println("In main(): " + array[0].get(0));
}
public static void fill(List<String>[] array) {
array = (List<String>[])new List[10];
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
}
}
The println in fill prints the correct value, because the array variable has been assigned to something within the fill method, however the println in the main method throws an NPE because only the "copy" of the array variable was changed by func, and not the "real" variable.
There are two ways to get around this: either instantiate the array within your calling code, or change the fill() method to return a reference to the array is has created.
Below is the first approach:
public class Main {
public static void main(String[] args) {
List<String>[] array = (List<String>[])new List[10];
fill(array);
System.out.println("In main(): " + array[0].get(0));
}
public static void fill(List<String>[] array) {
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
}
}
You may be wondering why this works, because you're still assigning ArrayList's to the elements of the array, however these objects are visible outside of the calling method. The reason for this is that although the fill method is getting a "copy" of the reference to the array, the reference itself is still referencing the same array object. This means that you can modify the internal state of the array object, and any changes you make will be seen by the caller because it referencing that same object.
Below is the second approach:
public class Main {
public static void main(String[] args) {
List<String>[] array = fill();
System.out.println("In main(): " + array[0].get(0));
}
public static List<String>[] fill() {
List<String>[] array = (List<String>[])new List[10];
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
return array;
}
}
(As an aside, you should generally try to avoid creating arrays of generic collections, a better idea would be to use a list to store the lists themselves. E.g:
List<List<String>> list = new ArrayList<List<String>>();
list.add(new ArrayList<String>());
list.get(0).add("test");
new ArrayList<?>[10] give me incompatible type. However, new ArrayList[10] works for me.

varargs and the '...' argument

Consider the method declaration:
String.format(String, Object ...)
The Object ... argument is just a reference to an array of Objects. Is there a way to use this method with a reference to an actual Object array? If I pass in an Object array to the ... argument - will the resultant argument value be a two-dimensional array - because an Object[] is itself an Object:
Object[] params = ....; // Make the array (for example based on user-input)
String s = String.format("%S has %.2f euros", params);
So the first component of the array (Which is used in the String.format method), will be an array and he will generate:
[class.getName() + "#" + Integer.toHexString(hashCode())]
and then an error because the array size is 1.
The bold sequence is the real question.
This is a second question: Does a ... array/parameter have a name?
From the docs on varargs:
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.
So you can pass multiple arguments or an array.
The following works just fine:
class VarargTest {
public static void main(String[] args) {
Object[] params = {"x", 1.2345f};
String s = String.format("%s is %.2f", params);
System.out.println(s); // Output is: x is 1.23
}
}
You can just pass an array:
public void foo(String... args) {
}
String args[] = new String[10];
foo(args);
The situation you are describing is going to be fairly rare: most of the time, your varargs items will be Strings, or numbers, or Widgets... it will be unusual for them to be Objects (which could be anything) or arrays.
But if the varargs argument is a bunch of Objects or an array type, then your question does arise: you can pass it a single array and then how will the compiler know whether you meant to pass an array (the one you provided), or an series of 1 item which it should PUT into an array for you?
A quick test shows the answer:
public class TestClass {
public static void main(String[] args) {
Object anObject = new Object();
Object[] anArray = new Object[] {anObject, anObject};
System.out.println("object1 = " + anObject);
System.out.println("array1 = " + anArray);
takesArgs();
takesArgs(anObject, anObject);
takesArgs(anArray); // is this the same as array1?
takesArgs(anArray, anArray);
}
public static void takesArgs(Object... stuff) {
System.out.println("The array was " + stuff);
}
}
The result of executing (your exact numbers will vary:
object1 = java.lang.Object#3e25a5
array1 = [Ljava.lang.Object;#19821f
The array was [Ljava.lang.Object;#addbf1
The array was [Ljava.lang.Object;#42e816
The array was [Ljava.lang.Object;#19821f
The array was [Ljava.lang.Object;#9304b1
So the answer is that in ambiguous cases it treats what you passed as the array instead of creating a new array to wrap it. This makes sense as you could always wrap it in an array yourself if you wanted the other interpretation.

Categories