out.write((char*)&tam, sizeof(tam));
Veamos. size_t es un unsigned int, 4 bytes. Al hacer &tam, saco la dirección (size_t*), y con (char*), lo paso a un arreglo de char, eso está claro.
Si hago eso, es porque quiero escribir en 'out', los datos binarios del size_t.
Suponiendo que tam=5. en hexadecimal sería: 0x00000005. Si hago "out << tam", va a escribir un '5' en el archivo. Pero eso no me interesa al serializar, ya que en decimal, el número ocupa más memoria. Así que haciendo el casting a char*, convierto el número
0x00000005 a un array de char
{0x00, 0x00, 0x00, 0x05}. Así es como lo quiero poner en el archivo: 4 caracteres.
El sizeof(tam), equivalente a sizeof(size_t), es para saber el tamaño en bytes, ya que se lo tengo que pasar a la función write. En este caso, el tamaño es 4.
Si en la facultad te dicen de usar reinterpret_cast, puedes usarlo. Funcionará igual.
Acerca de lo de serializar en Java, cuidado, porque Java suele tener métodos propios para serializar clases estandar (pese a que puedas hacerlos también por ti mismo.
No se de tutoriales para serializar, lo único importante es el concepto: convertir una clase a un arreglo de bytes. (Y poder revertirlo luego)