0

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_

1
  • 1
    Because the prefix array reference isn't changed. Just the contents of the array. Not that you should write code like this. List<String> flagList = list.stream().map(param -> String.format("%s_%s_%s", "NoPrefix", param, suffix)).collect(Collectors.toList()); Commented Jul 29, 2022 at 3:55

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

1 Comment

Printing the array does not print its hashcode. It prints its identityHashCode (as hex), which is the default implementation of hashCode(). An array's actual hash code is found using Arrays.hashCode(). This is easily verifiable by creating two identical arrays (say int[] x = {1, 2, 3}; int[] y = {1, 2, 3};) and noting that their hashCode() values are different (their identities so x != y), but Arrays.hashCode(x) == Arrays.hashCode(y) as it should be to uphold the contract of hashCode()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.