Difference argument passing to method and assignment [duplicate] - java

This question already has an answer here:
Declaring an Array and altering its contents [duplicate]
(1 answer)
Closed 8 years ago.
List<Object[]> d = new ArrayList<Object[]>();
d.add({"A"});//compile error
Object [] arr = {"A"};//valid
I always thought that last 2 rows make equally operations and regulated by similar rules.
Who can it explain?

It's not about passing arguments to method. You can only use the {x} shorthand while initializing an array, such as your valid example. Anywhere else it's invalid. If you need to instantiate an array at a later time after initialization, you need to use new int[].
int[] a = {1,2}; // OK
int[] b;
b = {1,2}; // compiler error

I always thought that last 2 rows make equally operations and regulated by similar rules.
You were wrong.
Who can it explain?
I can't explain why you were wrong, but I can explain the syntax. The final line is valid because it is an initialisation, and initialisations have special syntax. If you had split it into a declaration and an assignment you would have got the same error in the assignment that you got in the second line. That syntax for a value simply does not exist in Java.

You can't use an array initializer as an argument.

In the first case
d.add({"A"});//compile error
You need to create a new instance of Object[] to serve as the method argument like this:
d.add(new Object[]{"A"});
In the second case, you create an array of Object. You can also do the similar thing:
Object [] arr = new Object[] {"A"};
Java lets you do the following because I think it maintains some compatibility with C/C++ array definition in the original design.
Object [] arr = {"A"};//valid

Related

The difference between int[] and Integer[] and why are they treated differently? [duplicate]

This question already has answers here:
Arrays.asList() not working as it should?
(12 answers)
Closed 4 years ago.
I've got two pieces of code, in both the main focus is the method Arrays.asList(T... a).
In the first of them I input an Integer[], in the second I input an int[] , and - this is the part that confuses me, in the two cases, the resulting List<...> is different:
Integer[] arrayBoxed = new Integer[10];
List<Integer> list = Arrays.asList(arrayBoxed);
It's pretty short, and none of the values in arrayBoxed are set, but it works, and produces an List<Integer>.
int[] array = new int[10];
List<int[]> list = Arrays.asList(array);
In this case, for some reason, I get a List<int[]>, which is a pretty pathological construct.
Why is that?
The problem is, that given the similar input into Arrays.asList, I'd expect both of the functions to output the same (both code pieces are fully functional). However, one time the method returns List<Integer>, the other time List<int[]>.
Arrays.asList takes an array of reference types, not primitive types.
So, when you call Arrays.asList(int[]), the reference type taken is int[] (the array type), and that's why the result is List<int[]>.
Integer is a reference type, which explains why List<Integer> is the return type.

how to make objects immutable in java [duplicate]

This question already has answers here:
Immutable array in Java
(15 answers)
Closed 8 years ago.
I have following piece of code :
final int[] a = new int[5];
a[0] = 10;
a[0] = 5;
this code is perfectly fine as I am modifying the object and not the reference but now I want something like this :
int[] a = final new int[5];
so line 3 above will fire an error that I am trying to change immutable array. Is there any simple way to do it? There is a function in collections but I don't want to use any type of collection.
Is there any simple way to do it?
With a plain array, no. Arrays will always be mutable, so if you want this functionality you'll have to wrap an array and provide a mechanism for reading it (and not one for writing to it). There are already utilities in the standard JDK classes that can do this for you, like in Collections as you state.
You can, for example, use an unmodifiable list as returned by Collections.unmodifiableList instead. For example, to create an unmodifiable list containing 1, 2 and 3:
List<Integer> a = Collections.unmodifiableList(Arrays.asList(1, 2, 3));
Without some sort of wrapper (be it standard or not), what you're asking for can't be done.
If you declare:
final int[] myarray = new int[5];
it will not make your array immutable as you expect. The reference myarray will be final, but contents of this array can be changed.
As you do not want to use Collections Framework, make your own wrapper class over your array, to prevent modifying it's contents. And it will make your array immutable.

Proper way of declaring an array [duplicate]

This question already has answers here:
Difference between int[] array and int array[]
(26 answers)
Closed 9 years ago.
I've seen that arrays work when you declare them like this:
int[] myarray = {2,4,6,8,10}; //Notice the brackets are with the type
And when you declare them like this:
int myarray[] = {2,4,6,8,10}; //Here the brackets are with the array name
So which one is the correct way of declaring an array and what are the differences (if any) between the 1st and the 2nd.
Thanks.
There is no functional difference at all. It is however considered good practice to put the brackets with the type:
int[] myarray = {2,4,6,8,10};
There is no difference but prefer the first declaration.
You can also place the brackets after the array's name:
// this form is discouraged
float anArrayOfFloats[];
However,
convention discourages this form; the brackets identify the array type
and should appear with the type designation.
You can declare an int, a one-, and a two-dimensional array, all within a single declaration:
int i, oneD[], twoD[][];
Apart from this use case, you should prefer the early placement of brackets, although both are correct as far as Java specification is concerned.
They are identical in effect.
The alternate declaration of int myArray[] is a throwback to C, but the type is int[], so the first version int[] myArray is preferrred.
There is no difference. It's just a Syntactic sugar in array declaration.
Less confusing is the first type, probably.

Why final is not applicable to array in Java? [duplicate]

This question already has answers here:
Why won't declaring an array final make it immutable in Java?
(6 answers)
Why can I edit the contents of a final array in Java?
(9 answers)
Closed 9 years ago.
I tried using final keyword to array but still i can change the values, why arrays are not supporting final.
Thanks in advance
Because final applies to the array reference, not the contents.
You can modify the array content, but you can't say, reinstantiate the array.
Arrays in java are reference types. When you declare an array final, you are declaring the array object reference itself final, not the elements the array contains. So while you cannot alter the array reference, you can still alter individual elements in the array.
To get the effect you want, you'll have to use Collections.unmodifiableList or something similar.
Consider these
final int a[]={11,2};
int b[]={};
a=b;// this will compile wrong
a[1]=1;//this will compile fine
Because if you are declaring final array then it means that the array reference can not be changed but you can obviously change the content
Arrays are supported, but it's no different for any other reference variables: you can change the state of the variable, but you can't change the object that the variable refers to, here the array object. For arrays, the state are the item references.
final int[] test = new int[3];
test = new int[2]; //Error here
(final applies to the reference, not the object data)
If you need an immutable data structure, List (you can use ArrayList if desired) is where you'll want to go. If you really need it to be an array, you'll need to create your own data structure with only getter methods.
final in Java affects the variable, it has nothing to do with the object you are assigning to it.
final String[] myArray = { "hi", "there" };
myArray = anotherArray; // Error, you can't do that. myArray is final
myArray[0] = "over"; // perfectly fine, final has nothing to do with it

ArrayList initialization equivalent to array initialization [duplicate]

This question already has answers here:
Create ArrayList from array
(42 answers)
Initialization of an ArrayList in one line
(34 answers)
Closed 6 years ago.
I am aware that you can initialize an array during instantiation as follows:
String[] names = new String[] {"Ryan", "Julie", "Bob"};
Is there a way to do the same thing with an ArrayList? Or must I add the contents individually with array.add()?
Arrays.asList can help here:
new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
Yes.
new ArrayList<String>(){{
add("A");
add("B");
}}
What this is actually doing is creating a class derived from ArrayList<String> (the outer set of braces do this) and then declare a static initialiser (the inner set of braces). This is actually an inner class of the containing class, and so it'll have an implicit this pointer. Not a problem unless you want to serialise it, or you're expecting the outer class to be garbage collected.
I understand that Java 7 will provide additional language constructs to do precisely what you want.
EDIT: recent Java versions provide more usable functions for creating such collections, and are worth investigating over the above (provided at a time prior to these versions)
Here is the closest you can get:
ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));
You can go even simpler with:
List<String> list = Arrays.asList("Ryan", "Julie", "Bob")
Looking at the source for Arrays.asList, it constructs an ArrayList, but by default is cast to List. So you could do this (but not reliably for new JDKs):
ArrayList<String> list = (ArrayList<String>)Arrays.asList("Ryan", "Julie", "Bob")
Arrays.asList("Ryan", "Julie", "Bob");
Well, in Java there's no literal syntax for lists, so you have to do .add().
If you have a lot of elements, it's a bit verbose, but you could either:
use Groovy or something like that
use Arrays.asList(array)
2 would look something like:
String[] elements = new String[] {"Ryan", "Julie", "Bob"};
List list = new ArrayList(Arrays.asList(elements));
This results in some unnecessary object creation though.
The selected answer is: ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
However, its important to understand the selected answer internally copies the elements several times before creating the final array, and that there is a way to reduce some of that redundancy.
Lets start by understanding what is going on:
First, the elements are copied into the Arrays.ArrayList<T> created by the static factory Arrays.asList(T...).
This does not the produce the same class as java.lang.ArrayListdespite having the same simple class name. It does not implement methods like remove(int) despite having a List interface. If you call those methods it will throw an UnspportedMethodException. But if all you need is a fixed-sized list, you can stop here.
Next the Arrays.ArrayList<T> constructed in #1 gets passed to the constructor ArrayList<>(Collection<T>) where the collection.toArray() method is called to clone it.
public ArrayList(Collection<? extends E> collection) {
......
Object[] a = collection.toArray();
}
Next the constructor decides whether to adopt the cloned array, or copy it again to remove the subclass type. Since Arrays.asList(T...) internally uses an array of type T, the very same one we passed as the parameter, the constructor always rejects using the clone unless T is a pure Object. (E.g. String, Integer, etc all get copied again, because they extend Object).
if (a.getClass() != Object[].class) {
//Arrays.asList(T...) is always true here
//when T subclasses object
Object[] newArray = new Object[a.length];
System.arraycopy(a, 0, newArray, 0, a.length);
a = newArray;
}
array = a;
size = a.length;
Thus, our data was copied 3x just to explicitly initialize the ArrayList. We could get it down to 2x if we force Arrays.AsList(T...) to construct an Object[] array, so that ArrayList can later adopt it, which can be done as follows:
(List<Integer>)(List<?>) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5));
Or maybe just adding the elements after creation might still be the most efficient.
How about this one.
ArrayList<String> names = new ArrayList<String>();
Collections.addAll(names, "Ryan", "Julie", "Bob");
This is how it is done using the fluent interface of the op4j Java library (1.1. was released Dec '10) :-
List<String> names = Op.onListFor("Ryan", "Julie", "Bob").get();
It's a very cool library that saves you a tonne of time.

Categories

Resources