[RESOLVIDO] Union ou semelhante em Java

Bom dia,

Estou desenvolvendo um applet java que deverá se comunicar com um dispositivo via rs-485, os dados recebidos são armazenados numa array.

O meu problema consiste no seguinte: alguns valores por serem maiores, são armazenados em duas posições do vetor. em C para unir esses valores (hexa) e ter um inteiro resultante era só usar um union como esse:

[code]union
{
int i;
char b[2];
}

val;

//exemplo
val.b[1] = 0xff;
val.b[2] = 0xf0;

//quando eu imprimia “val.i” o resultado era 65520, que é 0xfff0.
[/code]
Pelo que pesquisei aprendi que não existe union em Java, e não encontrei nada na internet sobre como fazer algo semelhante em java.

Alguém teria alguma idéia ou algum link que sirva pelo menos de “ponta pé” inicial para que eu consiga fazer isso?

Oi!

Desculpe minha ignorancia, pois além de saber pouco de C, faz anos que não programo nessa linguagem.
Poderia explicar o que a função union faz e o seu respectivo resultado?

Dessa forma fica mais fácil sugerir algo.
Abraços.

Certamente.

Uma union determina uma única localização de memória onde podem estar armazenadas várias variáveis diferentes.
Num caso como o que apresentei em que são usadas variáveis de tipos diferentes, a mémória alocada corresponde ao tipo de “maior tamanho”.

Eu uso basicamente para inserir dados hexa (char) e obter uma saída inteira ou real.

Por Java ser uma linguagem fortemente tipada já seria de se esperar que não possuísse o union.

Abraço!

[quote=atsuki]Certamente.

Uma union determina uma única localização de memória onde podem estar armazenadas várias variáveis diferentes.
Num caso como o que apresentei em que são usadas variáveis de tipos diferentes, a mémória alocada corresponde ao tipo de “maior tamanho”.

Eu uso basicamente para inserir dados hexa (char) e obter uma saída inteira ou real.

Por Java ser uma linguagem fortemente tipada já seria de se esperar que não possuísse o union.

Abraço![/quote]

Certo!
Um Map não resolveria o seu caso? A chave serve para a identificação e o seu valor é simplesmente uma lista de objetos contendo todos os valores que você achar necessário. Dessa forma, você possui uma única identificação para n valores de diferentes tipos, apenas terá de usar um Wrapper ao invés de primitivos.

Yeah 8)

Esse é um caso que não dá para simplesmente traduzir as instruções de uma linguagem para outra, tem que mudar a maneira de fazer.

Fale mais sobre o problema (informações como: que tipo de array vem os dados, em que formato, em que tipo de variavel vc precisa guardar, etc) que podemos ajudar a descobrir um jeito mais “java” de resolver.

O Map seria um possível substituto para um struct, em que as variaveis ficam uma do lado da outra . O caso é um pouco diferente… os dois membros do union representam o mesmo valor, ele permite gravar os dados como um tipo e recuperar como outro (veja no comentário no final do código de exemplo).
É como o “Redefines” do Cobol, em Java não tem nada parecido.

Vamos lá:

Os dados vem numa array do tipo Byte.
esta Array é toda preenchida com dados em hexa.
Após “unir” os valores de dois campos da array seu valor seria armazenado numa variável do tipo inteiro.

[quote=atsuki]Vamos lá:

Os dados vem numa array do tipo Byte.
esta Array é toda preenchida com dados em hexa.
Após “unir” os valores de dois campos da array seu valor seria armazenado numa variável do tipo inteiro.

[/quote]

Então desconheço. Talvez apenas criando um método e fazendo isso “na mão”.
Não acredito, como foi citado, que tenha uma função como essa em Java, se houver, desconheço :slight_smile:

Passando para o java…
http://java.sun.com/developer/Books/shiftintojava/page1.html

Não existe nada parecido com union em java.
Para vc converter 2 bytes em 1 inteiro em java vc pode seguir a orientação dada nesse post: http://forums.anandtech.com/showthread.php?p=9893532

int temp = ((int)tmpByte[0] << 8) + (tmpByte[1] & 0xff);

Para este caso específico, pode ser usado um método para unir os dois valores.

public static void main(String[] args) {
		byte b1 = (byte) 0xff;   
		byte b2 = (byte) 0xf0;
		int i = mergeBytes(b1, b2);
		System.out.println(i); // 65520
	}

	/**
	 * Une os 2 bytes fornecidos em um unico valor inteiro.
	 * Ex:
	 * b1 = 11111111
	 * b2 = 00000000
	 * resultado = (int) 1111111100000000 
	 * 
	 * @param b1 Byte mais significativo
	 * @param b2 Byte menos significativo
	 * @return
	 */
	private static int mergeBytes(byte b1, byte b2) {
		final byte maskRemoveMinusSign = 127; //        01111111
		final int maskAddMinusSign = 128;     // 000....10000000
		
		int convertedB1;
		if (b1 < 0) {
			b1 = (byte) (b1 & maskRemoveMinusSign);
			convertedB1 = b1;
			convertedB1 = convertedB1 | maskAddMinusSign;
		} else {
			convertedB1 = b1;
		}
		
		int convertedB2;
		if (b2 < 0) {
			b2 = (byte) (b2 & maskRemoveMinusSign);
			convertedB2 = b2;
			convertedB2 = convertedB2 | maskAddMinusSign;
		} else {
			convertedB2 = b2;
		}
		
		convertedB1 = convertedB1 << 8;
		return convertedB1 + convertedB2;
	}

Acho que não viu a referência que citei

[quote=lordcarlos]Não existe nada parecido com union em java.
Para vc converter 2 bytes em 1 inteiro em java vc pode seguir a orientação dada nesse post: http://forums.anandtech.com/showthread.php?p=9893532

int temp = ((int)tmpByte[0] << 8) + (tmpByte[1] & 0xff); [/quote]
Foi o que eu fiz, só que em muito menos linhas rsrsrs

Mas tem um detalhe: essa implementação rápida não funciona para números negativos (quando o primeiro bit é 1).
O motivo é que o cast de byte para int copia o valor numérico ao invés do valor em binário.
O byte [b]11111111/b convertido para int não vira 00000000000000000000000011111111 (255) , que seria o comportamento desejado para esta operação em particular. Ao invés disso, é preservado o valor numérico -1, que é 11111111111111111111111111111111

Não sei se minha implementação é a maneira mais otimizada de contornar a situação, mas deu certo.

Que complicado. Basta fazer alguns “and’s” e “or’s”:

 public static void main(String[] args) {  
         byte b1 = (byte) 0xff;     
         byte b2 = (byte) 0xf0;  
         int i = mergeBytes(b1, b2);  
         System.out.println(i); // 65520  
     }  
   
     /** 
      * Une os 2 bytes fornecidos em um unico valor inteiro. 
      * Ex: 
      * b1 = 11111111 
      * b2 = 00000000 
      * resultado = (int) 1111111100000000  
      *  
      * @param b1 Byte mais significativo 
      * @param b2 Byte menos significativo 
      * @return 
      */  
     private static int mergeBytes(byte b1, byte b2) {  
         return ((b1 << 8) & 0xFF00) | (b2 & 0x00FF);
     } 

Galera, muitissimo obrigado.

Todos de uma forma ou de outra me ajudaram bastante, alguns com código maior, outros com menor :slight_smile:

Não esperei obter um feedback tão eficiente.

Creio que algum moderador pode fechar o tópico. Certamente será muito útil à alguém que eventualmente venha a passar por uma dúvida semelhante.

Abraço a todos!

Devo admitir que pensar nessa solução estava um pouco além do meu alcance. Vivendo e aprendendo :slight_smile:

O que se costuma fazer aqui para marcar como resolvido e facilitar as pesquisas é o dono editar o post original do tópico e adicionar "[RESOLVIDO]" no título.