Erro no writeObject

Boa tarde, é o seguinte:

Estou com um erro ao gravar objetos em um arquivo, quando o objeto do tipo ObjectOutputStrem executa o método writeObject, o try acusa e gera a exceção.Alguém pode me ajudar ? Segue o código do meu método e das classes:

package exer6_emdiante;

import java.io.Serializable;
import java.time.LocalDate;

    public class Empregado implements Serializable {
        private static final long serialVersionUID = 1L; //verifica a versão da classe
        
        protected static transient int mat_aux = 1;
        protected int matricula;
        protected String nome;
        protected String funcao;
        protected double salario;
        protected LocalDate data_adm;
        //transient indica q o objeto não erá conter o atributo
        
        //DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        
        public Empregado () {
            this.matricula = mat_aux;
            Empregado.mat_aux++;
        }
        
        public Empregado (String nome, String funcao, double salario,
                          LocalDate data_adm) {
            this();
            this.nome = nome;
            this.funcao = funcao;
            this.salario = salario;
            this.data_adm = data_adm;
        }
        
        public Empregado (int matricula, String nome, String funcao, double salario,
                          LocalDate data_adm) {
            this.matricula = matricula;
            this.nome = nome;
            this.funcao = funcao;
            this.salario = salario;
            this.data_adm = data_adm;
        }
        
        // métodos de acesso
        public int getMatricula() {
            return matricula;
        }
        public void setMatricula(int matricula) {
            this.matricula = matricula;
        }
        
        public String getNome() {
            return nome;
        }
        public void setNome(String nome) {
            this.nome = nome;
        }
        
        public String getFuncao() {
            return funcao;
        }
        public void setFuncao(String funcao) {
            this.funcao = funcao;
        }
        
        public double getSalario() {
            return salario;
        }
        public void setSalario(double salario) {
            this.salario = salario;
        }
        
        public LocalDate getData_adm(){
            return data_adm;
        }
        public void setData_adm(LocalDate data_adm) {
            this.data_adm = data_adm;
        }
}

Classe que contêm métodos para gravação e leitura:

package controllerArquivos;

import exer6_emdiante.Empregado;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
    public class Stream {
        
    final DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/DD/yyyy");

    public void gravaArquivoObjeto(Map<String, Empregado> empregados, String nomeArq) {
            FileOutputStream fos = null;
            ObjectOutputStream oos = null;
            
            try {
                fos = new FileOutputStream(nomeArq);
                oos = new ObjectOutputStream(fos);
                
                if (!empregados.isEmpty()) {
                    for (Map.Entry<String, Empregado> pair : empregados.entrySet()) {
                        Empregado emp = pair.getValue();
                        oos.writeObject(emp);   // Gera a exceção nessa linha
                    }
                }
                
                System.out.printf("Objeto(s) gravado(s) com sucesso.");
                
            } catch(FileNotFoundException fnfe) {
                System.out.printf("Arquivo não existe para: " + nomeArq);
            } catch (IOException ioe) {
                System.out.printf("Erro de gravação.");
            } finally {
                try {
                    if (fos != null) fos.close();
                    if (oos != null) oos.close();
                } catch(IOException e) {}
            }
        }
    }

Classe que uso os métodos:

package viewArquivos;

import controllerArquivos.Stream;
import exer6_emdiante.Empregado;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

public class ProgramaArquivos {
      public static void main(String[] args) {
            Map<String, Empregado> mapa = new HashMap();
            mapa.put("fulano", new Empregado(1,"fulano","analista",100,LocalDate.of(2020, 01, 10)));

            Stream stream = new Stream();
            try {
                  stream.gravaArquivoObjeto(mapa, "arquivo.txt");
            } catch(IOException ex) {
                  System.out.println("Ocorreu algum erro.");
            }
      }
}

Faltou postar o StackTrace da exceção.

Aliás, desculpa pelo meu mal entendimento a sua resposta, fiz uma alteração aqui para pegar o erro:

java.io.NotSerializableException: exer6_emdiante.Empregado
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
	at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
	at controllerArquivos.Stream.gravaArquivoObjeto(Stream.java:236)
	at viewArquivos.ProgramaArquivos.main(ProgramaArquivos.java:59)

Rodei sei código aqui e funcionou.

Estranho que minha classe que quero serializar (Empregado) está com a marcação, e acho ela não tem nenhum outro atributo que não seja serializado, mas estou procurando se o LocalDate é serializado e não acho…

Estranho, escrevi o código aqui um pouco mais resumido…

Manda ai, deixa eu rodar ele aqui.

Uma observação é que minha classe Empregado está em outro projeto meu e as outras duas, estão em um mesmo projeto.

public class ProgramaArquivos {
    public static void main(String[] args) {
        Map<String, Empregado> mapa = new HashMap();
        
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        String continua = "s", dataAdmFormatado;
        
        try(Scanner s = new Scanner(System.in)) {
            while ("s".equalsIgnoreCase(continua)) {
                Empregado empregado = new Empregado();

                System.out.printf("Nome funcionário: ");
                empregado.setNome(s.nextLine());
                System.out.printf("Função: ");
                empregado.setFuncao(s.nextLine());
                System.out.printf("Salário: ");
                empregado.setSalario(s.nextFloat());
                s.nextLine();
                System.out.printf("Data admissão: ");
                dataAdmFormatado = s.nextLine();
                
                empregado.setData_adm(LocalDate.parse(dataAdmFormatado, fmt));
                
                mapa.put(empregado.getNome(), empregado);
                
                System.out.printf("Deseja adicionar mais (s/n) ? ");
                continua = s.nextLine();
            }
            
            Stream stream = new Stream();
            stream.gravaArquivoObjeto(mapa, "arquivo.txt");
            
        } catch(InputMismatchException ime) {
            System.out.println("Dado informado não esperado.");
        }
    }
}
package exer6_emdiante;

import java.io.Serializable;
import java.time.LocalDate;
//import java.time.format.DateTimeFormatter;

// Classe Empregado adaptada para ser serializada e utilizada com Hash
// Serializable --> Apenas uma marcação. 
//                  Informa que a classe permite que seja gravado em arquivo 
public class Empregado implements Serializable {
    private static final long serialVersionUID = 1L; //verifica a versão da classe
    
    protected static transient int mat_aux = 1;
    protected int matricula;
    protected String nome;
    protected String funcao;
    protected double salario;
    protected LocalDate data_adm;
    //transient indica q o objeto não erá conter o atributo
    
    //DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    
    public Empregado () {
        this.matricula = mat_aux;
        Empregado.mat_aux++;
    }
    
    public Empregado (String nome, String funcao, double salario,
                      LocalDate data_adm) {
        this();
        this.nome = nome;
        this.funcao = funcao;
        this.salario = salario;
        this.data_adm = data_adm;
    }
    
    public Empregado (int matricula, String nome, String funcao, double salario,
                      LocalDate data_adm) {
        this.matricula = matricula;
        this.nome = nome;
        this.funcao = funcao;
        this.salario = salario;
        this.data_adm = data_adm;
    }
    
    // métodos de acesso
    public int getMatricula() {
        return matricula;
    }
    public void setMatricula(int matricula) {
        this.matricula = matricula;
    }
    
    public String getNome() {
        return nome;
    }
    public void setNome(String nome) {
        this.nome = nome;
    }
    
    public String getFuncao() {
        return funcao;
    }
    public void setFuncao(String funcao) {
        this.funcao = funcao;
    }
    
    public double getSalario() {
        return salario;
    }
    public void setSalario(double salario) {
        this.salario = salario;
    }
    
    public LocalDate getData_adm(){
        return data_adm;
    }
    public void setData_adm(LocalDate data_adm) {
        this.data_adm = data_adm;
    }
    
    public void growthSal(double perc) {
        this.setSalario(getSalario() + (getSalario() * perc / 100));
    }
    
    @Override
    public String toString() {
        return String.format("Matrícula: %d\nNome: %s\nFunção: %s\n"
           + "Salário: %.2f\nData admissão: " + 
             String.format("%td/%td/ty", data_adm)
            , getMatricula(), getNome(), getFuncao(), getSalario());
    }
    
    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }
        if ( !(o instanceof Empregado) || (this.getClass() != o.getClass()) ) {
            return false;
        } 
        if (this == o) {
            return false;
        }
        
        Empregado emp = (Empregado) o;
        
        if (nome == null && emp.getNome() != null)
            return false;
        
        return nome.equals(emp.getNome());
    }
    
    @Override
    public int hashCode() {
        return nome.hashCode();
    }
}

Cara, funcionou também. Preenchi os dados e gravou o arquivo.txt de boas:

Console:

Nome funcionário: 123
Função: 123
Salário: 123
Data admissão: 01/01/2000
Deseja adicionar mais (s/n) ? n
Objeto(s) gravado(s) com sucesso.

A única coisa que mexi foi retirar um try … catch desnecessário na chamada do método que grava o arquivo.

Mano, desculpa encomodar, mas isso é normal ?

    Note: C:\Users\Matheus\Documents\NetBeansProjects\lista8\src\viewArquivos\ProgramaArquivos.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

Em seguida o retorno :

compile-single:
run-single:
Nome funcionário: matheus
Função: developer
Salário: 1500
Data admissão: 14/08/2019
Deseja adicionar mais (s/n) ? n
java.io.NotSerializableException: exer6_emdiante.Empregado
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
	at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
	at controllerArquivos.Stream.gravaArquivoObjeto(Stream.java:236)
	at viewArquivos.ProgramaArquivos.main(ProgramaArquivos.java:59)
BUILD SUCCESSFUL (total time: 21 seconds)

Isso é apenas um warning. Pelo que vi no seu código e por conta disso: new HashMap();. Para remover o warning, tente mudar para new HashMap<>();.


Sobre o erro ao gravar o objeto, tente limpar os .class do seu projeto (deve ter alguma opção de limpar na sua IDE) e tente de novo.

Po lucas, muito obrigado mesmo, dei um clean and build nos 2 projetos e não da mais erro de gravação! Só que continua aparecendo o warnig, mas fora isso, resolveu meu problema.

Como o @Lucas_Camara já disse, esse warning é pelo fato de você estar instanciando o HashMap sem usar o <> .

Ajuste essa linha:

Map<String, Empregado> mapa = new HashMap();

Para ficar assim:

Map<String, Empregado> mapa = new HashMap<>();
1 curtida