Boa noite pessoal, estou tentando fazer uma serialização e posterior desserialização de um objeto tipo ArrayList…
Ao serializar não acontecem erros nem nada, mas quando tento desserializar aparece o warning abaixo, eu queria entender o porque disso, não quero desenvolver de qlq jeito, eu prezo pela qualidade… desde já agradeço… segue o método abaixo que invoca a mensagem:
public void actionPerformed(ActionEvent e) {
ArrayList<Short> recebeEstado;
try {
FileInputStream fis = new FileInputStream(new File("/estadoObj.ser"));
ObjectInputStream in = new ObjectInputStream(fis);
recebeEstado = (ArrayList<Short>) in.readObject();
} catch(Exception ex) {
ex.printStackTrace();
}
}
quando compilo a classe com esse método aparece a seguinte mensagem:
Note: BeatBox.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Ora, porque eu quero, há algum motivo para eu não querer? consome mais memória ou coisa do tipo???
E tb da maneira como estou fazendo aqui eu não sei a quantidade exata de números do tipo short que serão armazenados na ArrayList, se soubesse utilizaria um array… sem problemas…
Sim, exatamente. Todo objeto armazenado na ArrayList é armazenado como Object ou seja o compilador não sabe o que necessariamente foi armazenado, mas ao verificar que está sendo convertido para o tipo correto, ele não reclama… mas dessa vez ele me deu esse warning…
Olá pessoal, então Lina o que o pmlm me respondeu é o que acontece com qualquer objeto adicionado em um ArrayList, o objeto perde o tipo e é retornado como Object e o compilador não tem como saber o que este Object é exatamente, mas ao ver que está sendo convertido para um tipo igual ao da variável que recebe ele não chia, mas dessa vez apareceu essa nota:
Eu só queria ver se alguém saberia me dizer por que o compilador está dizendo que esta é uma operação não checada ou insegura…
[quote=[r.Jovelli]]Olá pessoal, então Lina o que o pmlm me respondeu é o que acontece com qualquer objeto adicionado em um ArrayList, o objeto perde o tipo e é retornado como Object e o compilador não tem como saber o que este Object é exatamente, mas ao ver que está sendo convertido para um tipo igual ao da variável que recebe ele não chia, mas dessa vez apareceu essa nota:
Eu só queria ver se alguém saberia me dizer por que o compilador está dizendo que esta é uma operação não checada ou insegura…
:?: :?: :?: [/quote]
Eh um warning que ele te informa que esta passando uma parte do codigo vc trabalhou com genericos e a outra parte nao ultilizou para melhor exemplificar basta vc compilar a classe com ,
javac -Xlint:uncheched nomedaclasse.java
Ira lhe falar qual parte do seu código esta insegura
Imagine que em algum lugar da aplicação você serializou um ArrayList, e depois faz isso:
ObjectInputStream in = /* blablabla */
List<Short> myShorts = (ArrayList<Short>) in.readObject();
Quando esse trecho for executado você não terá nenhum erro, pois como sabemos os generics não existem após a compilação (um ArrayList foi serializado, um ArrayList é o que vai ter!). Pois bem, a lista myShorts vai passear entre os objetos sem nenhum problema - até o momento em que você tentar utilizar algum elemento:
short firstValue = myShorts.get(0).shortValue();
Imagine a confusão, estamos chamando um método de Short em um objeto que é String. Um erro tão medonho que nem imagino qual exceção será lançada :shock: . E você lá tentando debugar e descobrir por que diabos a sua List está populada com Strings.
O que isso significa? NADA! HAHAHAAH
Mas espero que ajude a entender por que esta operação é INSEGURA.
Blz pessoal a explicação do gomesrod me deu uma boa idéia de o porque esta serialização ser considerada arriscada, ainda compilando com javac -Xlint:unchecked nomeClasse aparece que é requerido ArrayList e que foi encontrado Object…
Não e a serialização que eh arriscada , foi simplesmente pq vc esta usando métodos genéricos em um local eh em outro nao , somente isto o warning , te mostrando que pode ter falhas e talz .
O diabinho está certo. Veja esse caso: você serializou uma String em algum lugar do programa, e depois fez isso:
ObjectInputStream in = /* blablabla */
Short shortJeans = (Short) in.readObject();
Não vai dar erro de compilação, nem warning, e na hora de executar tomamos na cara uma big exceção. Mas de certa forma isso é bom, pois sabemos exatamente o ponto onde está o erro e como rastreá-lo.
Diferente do outro exemplo, em que você esperava um ArrayList e o que estava serializado também era um ArrayList. A atribuição vai acontecer sem problemas e o erro aparece em um outro lugar qualquer da aplicação! Ou seja, a encrenca não foi tanto por causa da desserialização e sim por passar de um “mundo não-generic” para um “generic”. É uma situação muito mais traiçoeira, e por isso o compilador dá aquele warning.
Lembre-se do antigo provérbio chinês: O COMPILADOR É SEU AMIGO.
E para finalizar, uma informação. Não sei se você já sabe disso, mas vou colocar mesmo assim: o compilador avisou que essa atribuição é insegura, mas se você tem realmente certeza que está tudo Ok existe um jeito de dizer a ele “Obrigado pelo aviso, não precisa mais avisar porque já conferi tudo direitinho” - Coloque sobre o método a anotação @SuppressWarnings(“unchecked”).
Eae pessoal eu li estes comentários e ainda dei uma pesquisada na net e li mais sobre os generics e agora deu pra entender porque do warnning e como funciona melhor os
generics, o artigo abaixo me ajudou a entender melhor e talz…
Então eu não conhecia esse comando não, é novo pra mim, mas preferi não usá-lo, é bom ter um warnning para avisar, não sei se vou alterar esse código qualquer dia…
Mas vlw mesmo a todos pela força…
Se alguém precisar e eu puder contribuir… estamos ae…
[quote=[r.Jovelli]Boa noite pessoal, estou tentando fazer uma serialização e posterior desserialização de um objeto tipo ArrayList…
[/quote]
Quando vc disse que queria “serializar um ArrayList” te confesso que não entendi bem o título da sua dúvida mas acho que o que vc quer é isso aqui…
public class Testes {
static class Teste implements Serializable{
List<String> dado = new ArrayList<String>();
public Teste(){}
protected void addDado(String d){
dado.add(d);
}
protected List<String> getDado(){
return dado;
}
}
public static void main(String[] args){
Teste t = new Teste();
try{
File arquivo = new File("C:\arquivo");
arquivo.mkdir();
File arqui = new File(arquivo, "arqui.mrc");
FileOutputStream f = new FileOutputStream(arqui);
ObjectOutputStream o = new ObjectOutputStream(f);
int i = 0;
while(i < 10){
t.addDado("a");
i++;
}
o.writeObject(t);
FileInputStream fi = new FileInputStream(arqui);
ObjectInputStream oi = new ObjectInputStream(fi);
t = (Teste) oi.readObject();
List<String> lista = t.getDado();
System.out.println(lista);
}
catch(FileNotFoundException f){
f.printStackTrace();
}
catch(IOException i){
i.printStackTrace();
}
catch(ClassNotFoundException c){
c.printStackTrace();
}
}
}
Na mosca cara, é exatamente isso que eu quero fazer, a única diferença é que no seu exemplo vc sabe que serão armazenados dez números e no código que eu fiz aqui eu não sei quantos números serão armazenados na ArrayList… se eu soubesse quantos números exatamente seriam armazenados eu serializaria um array de Short…
Mas é isso mesmo moacirjava, consegui entender o warnning e tudo, vlw pela força…
Um abraço…
Este é o código que desenvolvi para serializar:
[code]private class MySerializarListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
ArrayList<Short> estadoCheckBox = new ArrayList<Short>();
for (short i = 0; i < 256; i++) {
if (checkBoxList.get(i).isSelected()) {
estadoCheckBox.add(i);
}
}
try {
FileOutputStream fos = new FileOutputStream(escolherArquivo("salvar")); //abre um JFileChooser com o método showSaveDialog();
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject(estadoCheckBox);
} catch(Exception ex) {
ex.printStackTrace();
}
}
}[/code]
E este para desserializar:
[code]
private class MyDesserializarListener implements ActionListener {
@SuppressWarnings("unchecked") //Faz com que o método ao ser compilado não mostre warnings referentes a unckecked
public void actionPerformed(ActionEvent e) {
ArrayList<Short> recebeEstado;
for (short i = 0; i < 256; i++) {
checkBoxList.get(i).setSelected(false);;
}
try {
FileInputStream fis = new FileInputStream(escolherArquivo("abrir"));
ObjectInputStream in = new ObjectInputStream(fis);
recebeEstado = (ArrayList<Short>) in.readObject();
for (Short percObj : recebeEstado) {
checkBoxList.get(percObj).setSelected(true);
}
} catch(Exception ex) {
ex.printStackTrace();
}
UtilMidi.sequencer.stop();
criarTrilhaIniciar();
}
}[/code]