Student: I tried something, and I’m not sure I get what happened.
Prof: I’m all ears.
Student: I was thinking about how to represent an Instagram post. It has a user, and text, and images, but also you can like it. And that makes a counter go up that everyone can see. So I tried writing a class for a post like that
Student: Did I do that right? Am I allowed to write that?
Prof: For sure! Why were you worried you might not have?
Student: Well, we haven’t written the
this.likes = lines outside of a constructor before. And a record won’t let us do it.Prof: What do you mean a record won’t let you?
Student: Well, look:
Student: It says the
final field cannot be assigned?Prof: Right, so that’s one more modifier to learn about.
final on a field says that it cannot be updated outside of the constructor. All the fields of a record are implicitly final. But you can get the same error message with a class:Prof: What you’re seeing in your program is actually the default for classes: fields are mutable unless we ask them to be immutable with
final. The field update statement this.x = v; will only work on non-final fields.Student: Is there any way to do field update on a record field, then?
Prof: No. You could say that’s a reason to not…
like() records.Student: …
Prof: Get it?
Student: … Yes.
Prof: Anyway, I think your program is great. It captures the idea of using a field update to model the likes of a post, and that’s something that can only be done with a
class, not with a record.Student: And you can still assign
final fields inside the constructor, though?Prof: Correct. Otherwise there would be no way to initialize those values. So Java simply will error if you write field updates in other places, but allows it in constructors.
Practice
This Post keeps its hashtags in an array, and retag swaps in a new one:
class Post {
String user;
String message;
String[] tags;
Post(String user, String message, String[] tags) {
this.user = user;
this.message = message;
this.tags = tags;
}
void retag(String[] newTags) {
this.tags = newTags;
}
}
String[] a = {"cse11", "java"};
String[] b = {"pizza"};
Post p = new Post("joe", "Free pizza in the CSE lobby", a);
void main() {
p.retag(b);
}Here is memory just as retag starts, before its field update runs:
Names (the stack)
p.retag(b) on @1003newTags = @1002main()top level
a = @1001b = @1002p = @1003Heap
@1001: [cse11, java]@1002: [pizza]@1003: Post[user=joe, message=Free pizza in the CSE lobby, tags=@1001]After
p.retag(b) finishes:the
tags field of @1003 holds a holds p.tags[0] is a[0] is