Oi Einar,

ainda não sei se compreendi bem o seu problema. Mas vamos lá!

Quando você está implementando um método construtor e faz a chamada ao
construtor da superclasse, utilizando super(), esta chamada deve ser feita
antes de qualquer ação dentro do construtor. Isto é uma característica não só
do Java, mas de outras linguagens de programação OO. Por isso sua primeira
tentativa não funcionou:
class MessageOutputStream extends ObjectOutputStream {
  private ByteArrayOutputStream _bos;
  MessageOutputStream() throws java.io.IOException {
    super(_bos = new ByteArrayOutputStream());  // ERRO!
  }
}

Neste caso, ele tenta primeiro fazer _bos  = new ByteArrayOutputStrem() antes
de chamar o super( _bos);

Você poderia fazer:

import java.io.*;
class MessageOutputStream extends ObjectOutputStream {
  private ByteArrayOutputStream _bos = new ByteArrayOutputStream();
  MessageOutputStream() throws java.io.IOException {
    super();

 }

  MessageOutputStream(ByteArrayOutputStream bos) throws java.io.IOException {
 super(bos);
  _bos = bos;
 }
}

No caso acima não enviando o parâmetro para o superconstrutor, já que durante
a execução ele faria a instanciação do new ByteArrayOutputStream() antes de
invocar o super. Ou seja, seu problema está resolvido, porque não tem solução.
O cliente vai ter que enviar a referência do objeto se você quiser usar o
super, ou então não usa o super e boa.

Questoes conceituais, talvez você já saiba de tudo que está abaixo, mas pode
ser interessante para o pessoal que está começando:

Os dados criados dentro de uma classe são pertencentes a esta classe, mas
podem ser referenciados por outros objetos enquanto a classe ainda não tenha
sido destruída. Isto é uma característica do encapsulamento. Quando declaramos
um objeto e passamos como referência um outro, estamos apenas apontando para o
objeto real, e portanto não temos uma nova cópia do objeto referenciado. Isto
significa que se o objeto original for destruído a referencia ficará,
obviamente sem referência. Mas acho que você já sabia disso... estou me
prolongando e vou acabar complicando... :)

Escrevi um programa bem rapidamente para testar o que estava falando, está
abaixo:

import java.io.*;
class MessageOutputStream extends ObjectOutputStream {
  private ByteArrayOutputStream _bos = new ByteArrayOutputStream();
  MessageOutputStream() throws java.io.IOException {
    super();
  }
  MessageOutputStream(ByteArrayOutputStream bos) throws java.io.IOException {
  super(bos);
  _bos = bos;
 }
  MessageOutputStream(FileOutputStream fos) throws java.io.IOException {
  super(fos);
 }

 ByteArrayOutputStream getBos()
 {
  return _bos;
 }
 public static void main (String a[])
 {
  try{
     FileOutputStream ostream = new FileOutputStream("t.tmp");
   MessageOutputStream m = new MessageOutputStream(ostream);

     m.writeObject("\n Dado adicionado em m");
   System.out.println("1:"+m.toString());

     m.flush();
//  MessageOutputStream b = m;
   m = null;
   MessageOutputStream b = m;

   Runtime.getRuntime().gc();
   b.writeObject("\nDado adicionado em b!!!!");
   System.out.println("2:"+b.toString());
    ostream.close();
  }
  catch (IOException e) {
    System.out.println("erro");
  }
 }
}

Tente inverter os comentário e o erro que surgirá na execução:

Exception in thread "main" java.lang.NullPointerException
        at MessageOutputStream.main(MessageOutputStream.java:35)

Por causa da perda da referência.

É isso, se não ajudei, desculpe.

[]'s
Handerson Ferreira Gomes

Einar Saukas wrote:

> Ricardo Muneo Kayo wrote:
> >
> > Vc jah tentou usar essa classe com a sua ultima implementacao(4a. do
> > email)? Funcionou???
>
>         Sim, funcionou.
>
> > Pelo que eu entendi, vc quer fazer uma heranca multipla em JAVA, meio
> > mascarado, nao eh??? Acho que nao vai funcionar!!!
>
>         Não, eu simplesmente queria fazer uma herança simples da classe
> ObjectOutputStream mesmo. A única dificuldade é que eu preciso preservar
> o parâmetro que eu estou passando para o construtor dessa classe.
>
>         É bastante razoável que minha primeira opção não funcione, porque
> eu não posso mesmo acessar variáveis da instância antes de inicializar a
> base. Mas quanto à segunda opção (usar variáveis temporárias antes de
> inicializar a base), eu não vejo nenhum motivo para isso não funcionar,
> porque afinal de contas tais informações ficam armazenadas na pilha e
> não na área de memória da instância.
>
>         Tem alguém nessa lista de discussão que acompanhe mais de perto
> o processo de padronização do Java (Bruno?) e saiba dizer se tem algum
> motivo para essa restrição? Será que isso é imposto pelo padrão ou
> simplesmente uma particularidade da implementação atual do JDK?
>
>         Um abraço,
>
> Einar Saukas
> Technical Consultant
> Summa Technologies, Inc.
> http://www.summa-tech.com
>
> > Einar Saukas wrote:
> > >
> > >         Oi pessoal!
> > >
> > >         Encontrei um problema interessante no projeto em que estou
> > > trabalhando, será que alguém tem alguma sugestão? Minha intenção
> > > era fazer uma classe assim, só que não funciona:
> > >
> > > class MessageOutputStream extends ObjectOutputStream {
> > >   private ByteArrayOutputStream _bos;
> > >   MessageOutputStream() throws java.io.IOException {
> > >     super(_bos = new ByteArrayOutputStream());  // ERRO!
> > >   }
> > > }
> > >
> > >         Todas as outras soluções semelhantes que eu consegui imaginar
> > > também não funcionam, como essa por exemplo:
> > >
> > > class MessageOutputStream extends ObjectOutputStream {
> > >   private ByteArrayOutputStream _bos;
> > >   MessageOutputStream() throws java.io.IOException {
> > >     ByteArrayOutputStream tmp = new ByteArrayOutputStream();
> > >     super(tmp);  // ERRO!
> > >     _bos = tmp;
> > >   }
> > > }
> > >
> > >         Na verdade, existe uma única variante que funciona, mas é
> > > uma péssima solução:
> > >
> > > class MessageOutputStream extends ObjectOutputStream {
> > >   static ByteArrayOutputStream tmp;
> > >   private ByteArrayOutputStream _bos;
> > >   MessageOutputStream() throws java.io.IOException {
> > >     super(tmp = new ByteArrayOutputStream());
> > >     _bos = tmp;
> > >   }
> > > }
> > >
> > >         Por isso, a solução que eu acabei adotando foi deixar parte
> > > da inicialização para ser feita pelo "cliente" da classe:
> > >
> > > class MessageOutputStream extends ObjectOutputStream {
> > >   private ByteArrayOutputStream _bos;
> > >   MessageOutputStream(ByteArrayOutputStream bos)
> > >       throws java.io.IOException {
> > >     super(bos);
> > >     _bos = bos;
> > >   }
> > > }
> > >
> > >         Em todo caso, se alguém tiver alguma idéia de como implementar
> > > minha intenção original, eu agradeço. Eu acho que não tem muito jeito,
> > > mas não custa nada perguntar...
> > >
> > >         Um abraço,
> > >
> > > Einar Saukas
> > > Technical Consultant
> > > Summa Technologies, Inc.
> > > http://www.summa-tech.com
>
>     --------------------------- LISTA SOUJAVA ---------------------------
>     http://www.soujava.org.br  -  Sociedade de Usuários Java da Sucesu-SP
>     [para sair da lista: http://www.soujava.org.br/forum/cadastrados.htm]
>     ---------------------------------------------------------------------

    --------------------------- LISTA SOUJAVA ---------------------------
    http://www.soujava.org.br  -  Sociedade de Usuários Java da Sucesu-SP
    [para sair da lista: http://www.soujava.org.br/forum/cadastrados.htm]
    ---------------------------------------------------------------------

Responder a