# ArrayList\_Serializable Demo Fails

**URL:** <https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770>\
**Category:** Coding Questions\
**Created:** [September 16, 2023, 4:43am UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770 "2023-09-16T04:43:15Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)\
**Post date:** [September 16, 2023, 4:43am UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/1 "2023-09-16T04:43:15Z")

</div>

In trying to learn about Serializable I found this example online: [https://samderlust.com/dev-blog/java/write-read-arraylist-object-file-java](https://samderlust.com/dev-blog/java/write-read-arraylist-object-file-java) but am unable to get it to run without error. Similar efforts with other examples as well as my own project have failed. Can anyone get this demo to run without error in our IDE? Thanks.

```auto
import java.io.*;
import java.util.ArrayList;

class Person implements Serializable {
  String firstName;
  String lastName;
  int birthYear;

   Person(String firstName, String lastName, int birthYear) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.birthYear = birthYear;
  }

  @Override
    public String toString() {
    return "Person{" +
      "firstName='" + firstName + '\'' +
      ", lastName='" + lastName + '\'' +
      ", birthYear=" + birthYear +
      "}\n";
  }
}

void setup() {
  Person p1 = new Person("Jony", "Deep", 1980);
  Person p2 = new Person("Andrew", "Justin", 1990);
  Person p3 = new Person("Valak", "Susan", 1995);

  ArrayList<Person> people = new ArrayList<>();

  people.add(p1);
  people.add(p2);
  people.add(p3);

  //write to file - change filePath for your system
  try {
    FileOutputStream writeData = new FileOutputStream("/Users/xxxx/peopledata.ser");
    ObjectOutputStream writeStream = new ObjectOutputStream(writeData);

    writeStream.writeObject(people);
    writeStream.flush();
    writeStream.close();
  }
  catch (IOException e) {
    e.printStackTrace();
  }
  // Change filePath to match one above 
  try {
    FileInputStream readData = new FileInputStream("/Users/xxxx/peopledata.ser");
    ObjectInputStream readStream = new ObjectInputStream(readData);

    ArrayList people2 = (ArrayList<Person>) readStream.readObject();
    readStream.close();

    println(people2.toString());
  }
  catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
  }
}

```

---

<div class="post-metadata">

**Author:** ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)\
**Post date:** [September 16, 2023, 8:32am UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/2 "2023-09-16T08:32:44Z")

</div>

Hi @svan,

this can’t work that way in processing context. Remember that your class defined here is in the end a non static inner class of a class extends PApplet (which itself does not implement Serializable). As a consequence the inner class (here People) is not serializable.

Read the reason why here:  
[https://docs.oracle.com/en/java/javase/17/docs/specs/serialization/serial-arch.html#the-serializable-interface](https://docs.oracle.com/en/java/javase/17/docs/specs/serialization/serial-arch.html#the-serializable-interface)

You can bypass this circumstance by moving the People class into a file People.java (Add Tab) and adding a public before the constructor of it:

People.java:

```auto
import java.io.*;

class Person implements Serializable {
  String firstName;
  String lastName;
  int birthYear;

   public Person(String firstName, String lastName, int birthYear) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.birthYear = birthYear;
  }

  @Override
    public String toString() {
    return "Person{" +
      "firstName='" + firstName + '\'' +
      ", lastName='" + lastName + '\'' +
      ", birthYear=" + birthYear +
      "}\n";
  }
}

```

Cheers  
— mnse

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [September 16, 2023, 1:55pm UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/3 "2023-09-16T13:55:27Z")

</div>

> [@mnse](#):
>
> You can bypass this circumstance by moving the People class into a file “People.java”…

- Although it’s commendable, it isn’t required at all! 😏
- We can still keep the class inside a “.pde” file by simply declaring it as `static`. 💡
- Doing so we decouple the nested class from the sketch’s PApplet subclass. 💔
- As a clear example, take a look at this old post about Serializable: 👓

> [@Deserializing objects sent from a client program to a server program](https://discourse.processing.org/t/deserializing-objects-sent-from-a-client-program-to-a-server-program/16124/8):
>
> /\*\* \* Serializable PImage (v1.0.1) \* GoToLoop (2019/Dec/26) \* \* https://Discourse.Processing.org/t/ \* deserializing-objects-sent-from-a-client-program-to-a-server-program/16124/8 \*/ import java.io.Serializable; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.io.ObjectOutput; import java.io.FileInputStream; import java.io.ObjectInputStream; import java.io.ObjectInput; static final String FILENAME = "imagen.serial", URL = "https://" + "Forum.Processing.o…

BtW, I’ve updated that previous old example to use a working Wikipedia image URL now: 🔗

* * *

## “Serializable\_PImage.pde”:

```auto
/**
 * Serializable PImage (v1.1.3)
 * GoToLoop (2019/Dec/26)
 *
 * https://Discourse.Processing.org/t/arraylist-serializable-demo-fails/42770/3
 *
 * https://Discourse.Processing.org/t/
 * deserializing-objects-sent-from-a-client-program-to-a-server-program/16124/8
 */

static final String
  SERIALFILE = "imagen.serial", 

  FILENAME = "Wikipedia-logo-v2.png", 

  URL = "https://" + "www.Wikipedia.org/" +
  "portal/wikipedia.org/assets/img/" + FILENAME;

PImage img;

void settings() {
  img = loadAndSaveRemoteImage(URL);
  if (img == null) img = createImage(100, 100, RGB);

  size(img.width, img.height);
  noLoop();
}

void setup() {
  saveSerial(SERIALFILE, new SerializableImage(img));

  final SerializableImage sImg = (SerializableImage) loadSerial(SERIALFILE);
  println(sImg, sImg == sImg.clone());
  
  img = sImg.recreateImage();
}

void draw() {
  background(img);
}

```

* * *

## “Functions.pde”:

```auto
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectOutput;

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.ObjectInput;

PImage loadAndSaveRemoteImage(final String url) {
  final File f = dataFile(new File(url).getName());
  final String path = f.getPath();
  final PImage img = loadImage(f.isFile() ? path : url);

  println(url + ENTER + path);
  if (img != null) img.save(path);

  return img;
}

void saveSerial(final String filename, final Object o) {
  final File f = dataFile(filename);
  createPath(f);

  try {
    final ObjectOutput out = new ObjectOutputStream(new FileOutputStream(f));
    out.writeObject(o);
    out.close();
  }

  catch (final IOException e) {
    e.printStackTrace();
  }
}

Object loadSerial(final String filename) {
  final File f = dataFile(filename);
  println(f);

  try {
    final ObjectInput in = new ObjectInputStream(new FileInputStream(f));
    final Object o = in.readObject();
    in.close();
    return o;
  }

  catch (final IOException e) {
    e.printStackTrace();
  }

  catch (final ClassNotFoundException e) {
    e.printStackTrace();
  }

  return null;
}

```

* * *

## “SerialClass.pde”:

```auto
import java.io.Serializable;

static public class SerializableImage implements Cloneable, Serializable {
  static protected final long serialVersionUID = 1_620_140_667;

  public int w, h, type, scale, pix[];

  public SerializableImage(final PImage img) {
    w = img.width;
    h = img.height;

    type = img.format;
    scale = img.pixelDensity;

    img.loadPixels();
    pix = img.pixels.clone();
  }

  public PImage recreateImage() {
    return recreateImage(null);
  }

  public PImage recreateImage(final PApplet p) {
    final PImage img = new PImage(w, h, type, scale);
    img.parent = p;

    img.loadPixels();
    PApplet.arrayCopy(pix, img.pixels);
    img.updatePixels();

    return img;
  }

  @Override public SerializableImage clone() {
    try {
      final SerializableImage sImg = (SerializableImage) super.clone();
      sImg.pix = sImg.pix.clone();
      return sImg;
    }

    catch (final CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }

  @Override public String toString() {
    return "[" + w + " x " + h + "]: " + w * h;
  }
}

```

* * *

Or if you still prefer a separate tab file “.java” approach: ☕

## “SerializableImage.java”:

```java
package processing.core;

public class SerializableImage implements Cloneable, java.io.Serializable {
  static protected final long serialVersionUID = 1_620_140_667;

  public int w, h, type, scale, pix[];

  public SerializableImage(final PImage img) {
    w = img.width;
    h = img.height;

    type = img.format;
    scale = img.pixelDensity;

    img.loadPixels();
    pix = img.pixels.clone();
  }

  public PImage recreateImage() {
    return recreateImage(null);
  }

  public PImage recreateImage(final PApplet p) {
    final PImage img = new PImage(w, h, type, scale);
    img.parent = p;

    img.loadPixels();
    PApplet.arrayCopy(pix, img.pixels);
    img.updatePixels();

    return img;
  }

  @Override public SerializableImage clone() {
    try {
      final SerializableImage sImg = (SerializableImage) super.clone();
      sImg.pix = sImg.pix.clone();
      return sImg;
    }

    catch (final CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }

  @Override public String toString() {
    return "[" + w + " x " + h + "]: " + w * h;
  }
}

```

---

<div class="post-metadata">

**Author:** ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)\
**Post date:** [September 16, 2023, 2:19pm UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/4 "2023-09-16T14:19:06Z")

</div>

Adding “static public” to the class does indeed fix the demo. Thanks.

---

<div class="post-metadata">

**Author:** ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)\
**Post date:** [September 16, 2023, 4:28pm UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/5 "2023-09-16T16:28:24Z")

</div>

However, when I try to apply this technique to my own class, it fails because Processing won’t let me mix static and non-static:

```auto
import java.io.*;
import java.util.ArrayList;

ArrayList<Rect> rects;

static public class Rect implements Serializable {

  int x, y, w, h;
  color bkgrnd;

  // Constructor
  public Rect(int xpos, int ypos, int wide, int ht, color background) {
    this.x = xpos;
    this.y = ypos;
    this.w = wide;
    this.h = ht;
    this.bkgrnd = (color)background;
  }

// This causes error
  void display() {
    fill(bkgrnd);
    rect(x, y, w, h);
  }
}

void setup() {
  size(600, 600);
  rects = new ArrayList<Rect>();
  rects.add(new Rect(30, 30, 150, 50, color(0, 255, 0)));
  
  // Change filePath for your system
  try {
    FileOutputStream writeData = new FileOutputStream("/Users/xxxxx/rects.txt");
    ObjectOutputStream writeStream = new ObjectOutputStream(writeData);

    writeStream.writeObject(rects);
    writeStream.flush();
    writeStream.close();
  }
  catch (IOException e) {
    e.printStackTrace();
  }
  // Change filePath to match one above 
  try {
    FileInputStream readData = new FileInputStream("/Users/xxxxx/rects.txt");
    ObjectInputStream readStream = new ObjectInputStream(readData);

    ArrayList rects2 = (ArrayList<Rect>) readStream.readObject();
    readStream.close();

    println(rects2.toString());
  }
  catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
  }
}

```

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [September 16, 2023, 4:42pm UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/6 "2023-09-16T16:42:14Z")

</div>

> [@svan](#):
>
> ```auto
> void display() {
> fill(bkgrnd);
> rect(x, y, w, h);
> }
> 
> ```

Both **fill()** & **rect()** are instance (non-`static`) methods from class PApplet.

In my own SerializableImage::**recreateImage()** method, it requests an instance of PApplet as a parameter named _p_, so it can be assigned to PImage::_parent_ field:

> [@GoToLoop](#):
>
> ```auto
> public PImage recreateImage(final PApplet p) {
> final PImage img = new PImage(w, h, type, scale);
> img.parent = p;
> 
> // ...
> 
> ```

You can do the same for your Rect::**display()** method:

```auto
void display(final PApplet p) {
  p.fill(bkgrnd);
  p.rect(x, y, w, h);
}

```

You can also request a PGraphics instance as well, so it’s even more flexible:

```auto
void display(final PApplet p) {
  display(p.getGraphics());
}

void display(final PGraphics pg) {
  pg.fill(bkgrnd);
  pg.rect(x, y, w, h);
}

```

---

<div class="post-metadata">

**Author:** ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)\
**Post date:** [September 16, 2023, 4:58pm UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/7 "2023-09-16T16:58:04Z")

</div>

> [@GoToLoop](#):
>
> `final PApplet p`

That works, but how do I call it? The following causes a null pointer exception:

```auto
PApplet p;
// How do I get an instance of PApplet?
void draw(){
  for (int i = 0; i < rects.size(); i++) {
    Rect r = rects.get(i);
    r.display(p);
  }
}

```

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [September 16, 2023, 5:06pm UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/8 "2023-09-16T17:06:40Z")

</div>

Keyword `this` in any top-level function inside a “.pde” file refers to a subclass PApplet instance:

> **[this / Reference](https://processing.org/reference/this.html)**
>
> Refers to the current object (i.e., "this object"), which will change depending on the context in which this is referenced. In Processing, it's most common to use this to pass a referenc…

```auto
void draw() { // PApplet top-level method
  for (final Rect r : rects) r.display(this); // `this` is subtype PApplet here
}

```

```auto
void draw() { // PApplet top-level method
  for (final Rect r : rects) r.display(g); // PApplet::g is of subtype PGraphics
}

```

---

<div class="post-metadata">

**Author:** ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)\
**Post date:** [September 16, 2023, 5:09pm UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/9 "2023-09-16T17:09:31Z")

</div>

I should have known that, but didn’t try it. Thanks.

---

<div class="post-metadata">

**Author:** ![svan](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@svan](https://discourse.processing.org/u/svan)\
**Post date:** [September 16, 2023, 8:21pm UTC](https://discourse.processing.org/t/arraylist-serializable-demo-fails/42770/10 "2023-09-16T20:21:19Z")

</div>

The following source code demonstrates using a Rect class with an ArrayList for drawing rectangles and Serializable for saving/opening a rectangle file (set filePath for your system). A menuBar class is used to add generic buttons to the demo. The Rect class may be placed under a Tab ‘as is’ and will remain functional. Thanks to @GoToLoop for making this possible with Serializable.

```auto
import java.io.*;

MenuBar menuBar;
ArrayList<Rect> rects;
int selectedRect;

class MenuBar {
  int x, y, w, h;
  color bkgrnd;

  MenuBar(int xpos, int ypos, int wide, int ht, color background) {
    x = xpos;
    y = ypos;
    w = wide;
    h = ht;
    bkgrnd = (color)background;
  }

  void button(int x, int y, int w, int h, String title) {
    fill(255);
    rect(x, y, w, h, 15);
    fill(0);
    textSize(18);
    textAlign(CENTER);
    text(title, x, y, w, h);
  }

  void display() {
    noStroke();
    fill(bkgrnd);
    rect(x, y, w, h);
    stroke(0);
    button(30, 15, 110, 24, "Add Rect");
    button(150, 15, 80, 24, "Save");
    button(240, 15, 80, 24, "Clear");
    button(330, 15, 80, 24, "Open");
    button(420, 15, 130, 24, "Remove Rect");
  }
}

static public class Rect implements Serializable {

  float x, y, w, h;
  color bkgrnd;
  boolean selected;

  // Constructor
  public Rect(float xpos, float ypos, float wide, float ht, color background) {
    this.x = xpos;
    this.y = ypos;
    this.w = wide;
    this.h = ht;
    this.bkgrnd = (color)background;
  }

  void display(PApplet p) {
    p.fill(bkgrnd);
    p.rect(x, y, w, h);
  }
}

void saveArrayList() {
  try {
    FileOutputStream writeData = new FileOutputStream("/Users/xxxxx/rects.txt");
    ObjectOutputStream writeStream = new ObjectOutputStream(writeData);
    writeStream.writeObject(rects);
    writeStream.flush();
    writeStream.close();
  }
  catch (IOException e) {
    e.printStackTrace();
  }
}

void openArrayList() {
  try {
    FileInputStream readData = new FileInputStream("/Users/xxxxx/rects.txt");
    ObjectInputStream readStream = new ObjectInputStream(readData);
    rects = (ArrayList<Rect>) readStream.readObject();
    readStream.close();

    for (int i = 0; i < rects.size(); i++) {
      Rect r = rects.get(i);
      println("[" + i + "]" + r.x + "," + r.y + "," + r.w + "," + r.h + "," + red(r.bkgrnd) + "," + green(r.bkgrnd) + "," + blue(r.bkgrnd));
    }
  }
  catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
  }
}

void addRect() {
  color bkgrnd = color(random(255), random(255), random(255));
  rects.add(new Rect(random(300), random(60, 400), random(300), random(30, 100), bkgrnd));
}

void removeRect() {
  rects.remove(selectedRect);
}

void clearArrayList() {
  for (int i = rects.size() - 1; i >= 0; i--) {
    rects.get(i);
    rects.remove(i);
  }
}

void setup() {
  size(600, 600);
  rects = new ArrayList<Rect>();
  menuBar = new MenuBar(0, 0, width, 60, color(180));
}

void draw() {
  background(209);
  menuBar.display();
  for (int i = 0; i < rects.size(); i++) {
    Rect r = rects.get(i);
    r.display(this);
    if (r.selected) {
      fill(255);
      rect(r.x+r.w-5, r.y+r.h-5, 10, 10);
    }
  }
}

void mousePressed() {
  if ((mouseX >= 30) && (mouseX <= 30 + 110) && (mouseY >= 15) && (mouseY <= 15 + 24)) {
    addRect();
  }
  if ((mouseX >= 150) && (mouseX <= 150 + 80) && (mouseY >= 15) && (mouseY <= 15 + 24)) {
    println("Save btn hit.");
    saveArrayList();
  }
  if ((mouseX >= 240) && (mouseX <= 240 + 80) && (mouseY >= 15) && (mouseY <= 15 + 24)) {
    clearArrayList();
  }
  if ((mouseX >= 330) && (mouseX <= 330 + 80) && (mouseY >= 15) && (mouseY <= 15 + 24)) {
    openArrayList();
  }
  if ((mouseX >= 420) && (mouseX <= 420 + 130) && (mouseY >= 15) && (mouseY <= 15 + 24)) {
    removeRect();
  }

  for (int i = 0; i < rects.size(); i++) {
    Rect r = rects.get(i);
    if ((mouseX >= r.x) && (mouseX <= r.x + r.w) && (mouseY >= r.y) && (mouseY <= r.y + r.h)) {
      r.selected = true;
      selectedRect = i;
      println("selected Rect = ", selectedRect);
    } else {
      r.selected = false;
    }
  }
}

```
