I am having a problem with the following lines where car is a String array which has not been initialized/has no elements.
String car [];
System.out.println(car.length);
What is a possible solution?
Since car has not been initialized, it has no length, its value is null. However, the compiler won't even allow you to compile that code as is, throwing the following error: variable car might not have been initialized.
You need to initialize it first, and then you can use .length:
String car[] = new String[] { "BMW", "Bentley" };
System.out.println(car.length);
If you need to initialize an empty array, you can use the following:
String car[] = new String[] { }; // or simply String car[] = { };
System.out.println(car.length);
If you need to initialize it with a specific size, in order to fill certain positions, you can use the following:
String car[] = new String[3]; // initialize a String[] with length 3
System.out.println(car.length); // 3
car[0] = "BMW";
System.out.println(car.length); // 3
However, I'd recommend that you use a List instead, if you intend to add elements to it:
List<String> cars = new ArrayList<String>();
System.out.println(cars.size()); // 0
cars.add("BMW");
System.out.println(cars.size()); // 1
Well, in this case the car variable will be null, so dereferencing it (as you do when you access car.length) will throw a NullPointerException.
In fact, you can't access that variable at all until some value has definitely been assigned to it - otherwise the compiler will complain that "variable car might not have been initialized".
What is it you're trying to do here (it's not clear to me exactly what "solution" you're looking for)?
String car [];
is a reference to an array of String-s. You can't see a length because there is no array there!
This won't work. You first have to initialize the array. So far, you only have a String[] reference, pointing to null.
When you try to read the length member, what you actually do is null.length, which results in a NullPointerException.
Since you haven't initialized car yet so it has no existence in JVM(Java Virtual Machine) so you have to initialize it first.
For instance :
car = new String{"Porsche","Lamborghini"};
Now your code will run fine.
INPUT:
String car [];
car = new String{"Porsche","Lamborghini"};
System.out.println(car.length);
OUTPUT:
2
As all the above answers have suggested it will throw a NullPointerException.
Please initialise it with some value(s) and then you can use the length property correctly. For example:
String[] str = { "plastic", "paper", "use", "throw" };
System.out.println("Length is:::" + str.length);
The array 'str' is now defined, and so it's length also has a defined value.
I think you are looking for this
String[] car = new String[10];
int size = car.length;
In Java, we declare a String of arrays (eg. car) as
String []car;
String car[];
We create the array using new operator and by specifying its type:-
String []car=new String[];
String car[]=new String[];
This assigns a reference, to an array of Strings, to car.
You can also create the array by initializing it:-
String []car={"Sedan","SUV","Hatchback","Convertible"};
Since you haven't initialized an array and you're trying to access it, a NullPointerException is thrown.
Related
I know that writing a lambda in Java 8 to use a variable requires final type, but why can a variable of final array type be modified?
public static void main(String[] args) {
final String[] prefix = {"prefix_"};
String suffix = "_suffix";
List<Integer> list = Arrays.asList(1005, 1006, 1007, 1009);
List<String> flagList = list.stream().map(param -> {
prefix[0] = "NoPrefix_";
String flag = prefix[0] + param + suffix;
return flag;
}).collect(Collectors.toList());
System.out.println(flagList);
System.out.println(prefix[0]);
}
result:
[NoPrefix_1005_suffix, NoPrefix_1006_suffix, NoPrefix_1007_suffix, NoPrefix_1009_suffix]
NoPrefix_
So a final array means that the array variable which is actually a reference to an object, cannot be changed to refer to anything else, but the members of the array can be modified
refer below link for more information.
https://www.geeksforgeeks.org/final-arrays-in-java/
As per description
for example
final String[] arr = new String[10];
list.stream().map(ele -> {
arr[0] = ele.getName(); // this will work as you are updating member of array
arr = new String[5]; // this will not work as you are changing whole array object instead of changing member of array object.
}).collect(Collectors.toList());
the same thing happen when you use any final collection there.
why can a variable of final array type be modified?
It can't, even though it looks like it can.
The declaration is below, which defines "prefix" as an array:
final String[] prefix
First, edit the code to include two println() calls right after the declaration, like this:
final String[] prefix = {"prefix_"};
System.out.println("prefix: " + prefix);
System.out.println(prefix[0]);
And at the end, add a second println() next to the one you already had, like this:
System.out.println("prefix: " + prefix);
System.out.println(prefix[0]);
If you run that code, you'll see that the object hashCode when printing prefix will be the same object each time. The thing that changes then is not what "prefix" references – that remains the same, it's the same array as before. Instead, what you're doing is changing something inside the array, which is different from the array itself.
Here are the relevant lines from a local run showing that the object reference remains the same, but the value for "prefix[0]" changes:
prefix: [Ljava.lang.String;#5ca881b5
prefix_
prefix: [Ljava.lang.String;#5ca881b5
NoPrefix_
If we try to assign an entirely new array to "prefix", then the compiler will show an error – it knows "prefix" was defined as final.
prefix = new String[]{"new"};
cannot assign a value to final variable prefix
If you're looking for a way to prevent changes to the data, and if it's possible to use a List (instead of an array), you could use
Collections.unmodifiableList():
Returns an unmodifiable view of the specified list. Query operations on the returned list "read through" to the specified list, and attempts to modify the returned list, whether direct or via its iterator, result in an UnsupportedOperationException.
When I create a method to determine what value I want to return, usually I can return a value directly - like so:
return 0;
However, I've discovered that when returning arrays, I have to create a new instance of an array, and return it - like so:
String[] rtnArr = {"str1", "str2"};
return rtnArr;
Why is this? Am I creating two arrays here, or am I only specifying a type when I instantiate the method?
Edit: I should clarify that I am returning one or another array based on a preliminary condition. That is to say, I have a switch and each case returns an array of different strings.
You are not creating two arrays. Array initializers are only allowed when initiating a variable, so you can't use them directly in a return statement.
You don't actually need a variable to return an array. You can also return an array like this
return new String[] {"Hello", "World"};
When you declare an array you can initialize it as String test[] = {"Hello", "World"}; because the array is obviously a string array so you don't need to do new String[] {"Hello", "World"}, but otherwise, you need an explicit initialization of the array with a type for type safety.
I've discovered that when returning arrays, I have to create a new instance of an array, and return it Why is this ? Am I creating two arrays here, or am I only specifying a
type when I instantiate the method ?
You don't need to return a new instance of the array always, sometimes you might need to return an existing array object as shown in the below code:
public class MyArrayTest {
private String[] myArray;
public MyArrayTest(String[] myArray) {
this.myArray = myArray;
}
public String[] getMyArray() {
return myArray;//returning existing array object
}
}
I would like to know if in both cases the MyObject object is created. And if not, why do both cases work just fine?
MyObject[] abcd = new MyObject[8];
abcd[0] = MyObject();
String str = abcd[0].someMethod();
and
MyObject[] abcd = new MyObject[8];
String str = abcd[0].someMethod();
I know that in the first example, a MyObject array is created with 8 elements and stored in the reference variable of that array called abcd. I have an array of MyObject references but no actualy MyObject objects. So I create these objects and the first object is stored in array 0.
In the second example.. is it the same thing, just shorter code?
*EDITED: Forgot to add [] I apologize. *
Assuming you meant
MyObject[] abcd = new MyObject[8];
abcd[0] = new MyObject();
String str = abcd[0].someMethod();
this will work fine.
The second version will throw a NullPointerException unless someMethod happens to be static. In that case Java does not rely on an instance to be created for the static method to be invoked.
It is not the same thing: when you create an array (and it should be declared as a MyObject[], not a MyObject), you just create a "placeholder", you do not create individual items in the array. And when an array is created, its elements are null at first, or whatever zero is for the different primitive types.
And in your first example, you should do new MyObject(), MyObject() alone will not work (except if there is a method by the name MyObject() in the current class which... returns an instance of class MyObject. Talk about confusion).
As a result, your second code will throw a NullPointerException (unless, as #Reimeus mentions in his answer, .someMethod() is a static method of class MyObject).
MyObject abcd = new MyObject[8];
abcd[0] = MyObject();
String str = abcd[0].someMethod();
this fragment does not compile it should be like
MyObject [] abcd = new MyObject[8];
abcd[0] = new MyObject();
String str = abcd[0].someMethod();
In this case you are creating the array and putting one element at the index 0.
In your second case :
MyObject abcd = new MyObject[8];
String str = abcd[0].someMethod();
it also doesn't compile, it should be
MyObject []abcd = new MyObject[8];
String str = abcd[0].someMethod();
and you will have a NullPointerException as abdc[0] is not initialized.
(you created the array, but didn't put any element in it).
abcd[0] = MyObject();
This is not valid Java syntax; looks more like C++. You need
abcd[0] = new MyObject();
In Java an object is never the immediate value of a variable or an array element. Without that line, each array element is just null, so you won't be able to call any methods on it without getting NullPointerException.
In case your someMethod is static, what the line abcd[0].someMethod() actually compiles into is just
MyObject.someMethod();
The compiler ignores everything but the static type of the expression abcd[0], which is MyObject. This is a special case of Java semantics.
The following code in Java uses a final array of String.
final public class Main {
public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"};
public static void main(String[] args) {
for (int x = 0; x < CONSTANT_ARRAY.length; x++) {
System.out.print(CONSTANT_ARRAY[x] + " ");
}
}
}
It displays the following output on the console.
I can never change
If we try to reassign the declared final array of type String, we cause an error:
final public class Main {
public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"};
public static void main(String[] args) {
CONSTANT_ARRAY={"I", "can", "never", "change"}; //Error - can not assign to final variable CONSTANT_ARRAY.
for (int x = 0; x < CONSTANT_ARRAY.length; x++) {
System.out.print(CONSTANT_ARRAY[x] + " ");
}
}
}
Error: cannot assign to final variable CONSTANT_ARRAY.
However, the following code works:
final public class Main {
public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"};
public static void main(String[] args) {
CONSTANT_ARRAY[2] = "always"; //Compiles fine.
for (int x = 0; x < CONSTANT_ARRAY.length; x++) {
System.out.print(CONSTANT_ARRAY[x] + " ");
}
}
}
It displays
I can always change
This mean that we could manage to modify the value of the final array of type String. Can we modify the entire array in this way without violating the immutable rule of final?
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
Edit to add from comments: Note that I said object you are assigning to it. In Java an array is an object. This same thing applies to any other object:
final List<String> myList = new ArrayList<String>():
myList = anotherList; // error, you can't do that
myList.add("Hi there!"); // perfectly fine.
You are misinterpreting the final implementation. final applies to the array object reference, which means once it is initiated, the reference can never change but the array its self can be populated. "Its not violating the rules" you have specified only one rule about the reference change which is working accordingly. If you want the values should also never change you should go for Immutable lists i.e
List<String> items = Collections.unmodifiableList(Arrays.asList("I", "can", "never", "change"));
You can only make it so the array reference can't be changed. If you want the elements to be unable to be changed, you need to use an unmodifiable collection of some kind.
When you declare an array as final, you can change the elements in the array, however you cannot change the reference of this array.
final only guarantees immutability of primitives. And also guarantees that a variable is assigned only once. If an object is mutable you can change the content of it event it defined as final. You may check immutable collections for your needs. Such as Collections.unmodifiableList()
http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#unmodifiableList(java.util.List)
The reference to the array object is final (can not change e.g. in case you would attempt to associate a different Java array object (instance of String[]) to the same final variable...you'd get a compile time error).
BUT the fields of the final array object in your example are not final, and so you can modify their value. ...while the Java object you created, CONSTANT_ARRAY, after receiving an initial value, will have that value "forever" == until the JVM stops. :) It will be the same String Array instance "forever".
Final variables in Java are not a big deal, just spend some time to digest the topic/idea carefully. :-)
I suggest to all of those who are uncertain to meditate over this page, for example:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4
Let me cite the respective part:
"Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object.
This applies also to arrays, because arrays are objects; if a final variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array."
The value of the variable CONSTANT_ARRAY cannot change. That variable contains a (reference to an) array. However, the contents of the array can change. Same thing happens when you declare any kind of final variable that is not a simple scalar type (e.g. an object).
Be careful how you name your variables. :-) Calling it a CONSTANT_ARRAY doesn't make the contents of the array unchangeable.
Here's a good reference: The final word on final
When a variable is declared with the final keyword, its value can’t be modified, essentially, a constant. This also means that you must initialize a final variable. If the final variable is a reference, this means that the variable cannot be re-bound to reference another object, but the internal state of the object pointed by that reference variable can be changed i.e. you can add or remove elements from the final array or final collection.
final int[] res;
int[] res1;
int[] res2 = new int[1];
res2[0]=20;
res1=res2;
res1=res2;//no error
System.out.println("res1:"+res1[0]);
res = res2;//only once
//res = res2;//error already initialised
res2[0]=30;
System.out.println("res:"+res[0]);
output::
res1:20
res:30
I have an array of type string which I want to re-use inside a method.
I need to pass it to a function which returns a subset of the elements of array passed. To capture the returned array from function, should I declare a new string array or can I safely re-use same array that was holding the unfiltered array to hold filtered array ??
Also clarify that, when I pass a variable like array to a function does it creates a new space for the array in the heap each time I pass it as parameter to further functions or just it uses the same space in the heap & just passes the reference? I guess in case of array it passes just the reference but in case of simple variables it allocates new space on stack, right?
EDIT: Thanks you all for the great answers and explanations!!
Please also clarify whether that if I am reusing the array, would I be required to set the null at the position when I end the subset of array ? (Actually the subset of my array is not directly calculated from the array but some other calulations, so I would be required to manually set the null otherwise the older elements of the list would be visible, right??)
when I pass a variable like array to a function does it creates a new space for the array in the heap each time I pass it as parameter to further functions or just it uses the same space in the heap & just passes the reference
Java is entirely pass by value, but with arrays and object types, the value being passed is a reference (pointer) to the actual object, which is not duplicated. So when you pass an array into a function, only the reference to the array is copied; the array itself isn't. That's why if a function modifies the contents of an array, the code calling the function sees the modifications.
Example:
// A method that changes the first entry in an array
void changeArray(String[] theArray) {
theArray[0] = "Updated";
}
// A method that uses the above
void someMethod() {
String[] foo = new String[3];
foo[0] = "Original 0";
foo[1] = "Original 1";
foo[2] = "Original 2";
this.changeArray(foo); // `changeArray` receives a *copy* of the reference
// held in `foo`; both references point to the same
// array
System.out.println(foo[0]); // Prints "Updated"
}
Passing a reference into a method is exactly like assigning it to another reference variable:
String[] foo = new String[3]; // Create a new aaray, assign reference to `foo` variable
String[] bar = foo; // Copy the reference into `bar` as well
foo[0] = "Hi there"; // Use the reference in `foo` to assign to the first element
System.out.println(bar[0]); // Use the reference in `bar`, prints "Hi there"
Essentially, references are values (numbers) that tell the JVM where the data for an object is. So even when we copy a reference (because Java is entirely pass-by-value, the value of the reference is passed to the function), it still points to the same memory as the original.
Since the reference is passed into the function by value, the function can't change the calling code's reference:
// A method that assigns a new reference; the calling code sees no change
void changeReference(String[] theArray) {
theArray = new String[1]; // Now we're not using the caller's object anymore
theArray[0] = "I was changed";
}
// A method that uses the above
void someMethod() {
String[] foo = new String[3];
foo[0] = "Original 0";
foo[1] = "Original 1";
foo[2] = "Original 2";
this.changeReference(foo);
System.out.println(foo[0]); // Prints "Original 0", our reference wasn't changed
}
You'll note that this is exactly how primitives are treated:
void whatever(int a) {
a = 5;
}
void someMethod() {
int foo;
foo = 3;
whatever(foo);
System.out.println(foo); // Prints 3, of course, not 5
}
...and in fact, object references (as opposed to objects) are primitives.
...should I declare a new string array or can I safely re-use same array that was holding the unfiltered array to hold filtered array
You can safely re-use it if that's appropriate within the scope of your function. It may be more appropriate to declare a new variable (e.g., filteredThingy), but that's a matter of style and will depend on the situation.
You probably can by it is very bad style and is very error prone and is very unsafe for future modifications.
Here is the example.
public void foo(String[] args) {
// do something with array.
args = new String[] {"a", "b"}; // reuse of the array.
// more code.
for (Sring s : args) {
// what will this loop get"?
// The answer is: a, b
// but will you remember this fact in a month if "more code" above is 50 lines long?
}
}
Passing objects is essentially passing references. E.g., your array will only exist in one place in memory when passing it between functions. Here's a runnable example illustrating that.
If you like you can reuse the same array in your routine. Note that changes made to that array will be visible to all objects sharing the same reference to that array. If that's not desirable then you must declare a new array.
String parentArray = {"S","B","R"};
// no need to use new operator to hold subSetArray.
String subSetArray = returnSubSet(parent);
public String[] returnSubSet(String[] _parent)
{
return Arrays.copyOfRange(_parent,1,2);
}
, when I pass a variable like array to
a function does it creates a new space
for the array in the heap each time I
pass it as parameter to further
functions or just it uses the same
space in the heap & just passes the
reference?
Answer
1. Object in Java are Pass by reference by value
2. when you pass an array to a function , a _parent variable will be created in stack and it points to the same Array Object in heap.
UPDATES: Primitive example
int global_scope_variable=10;
setValue(global_scope_variable);
public void setValue(int val)
{
// val is visible only within this method.
System.out.println(val); // output is 10
val=20;
System.out.println(val); // output is 20
System.out.println(global_scope_variable); // output is 10
}