2012-02-17 9 views
5

Recientemente me encontré con algunos problemas con android.os.Bundle que esperaba solucionar simplemente ampliando la clase y haciéndola más imprecisamente tipada. El problema específico que me encontré era errores como:¿Por qué es android.os.Bundle una clase final?

W/Bundle (6782): Key access_token expected byte[] but value was a java.lang.String. The default value <null> was returned. 
W/Bundle (6782): Attempt to cast generated internal exception: 
W/Bundle (6782): java.lang.ClassCastException: java.lang.String 
W/Bundle (6782): at android.os.Bundle.getByteArray(Bundle.java:1305) 

Por supuesto, la conversión de String a byte[] es trivial, por lo que mi pensamiento fue ir a tomar el Bundle hacer esta conversión automáticamente si está buscando un byte[] pero encuentra un String en su lugar. Es una tontería que ya no lo haga (y también tiene getters y setters específicos para casi cada tipo primitivo y algunos tipos diferentes Object en lugar de genéricos que simplemente funcionan en términos de Object, o en el peor Number , String y Parcelable), en mi opinión.

Pero de todos modos, descubrí rápidamente que no puedo solucionar el problema extendiendo Bundle, porque está declarado final. ¿Hay alguna razón conocida/específica para esto? Hay otras clases en android.os que no son final, entonces ¿qué hace que Bundle sea digno de esta asignación?

Además, ¿alguna idea sobre cómo solucionar esto? Se ha eliminado una clase contenedora ya que no existe un interface común para implementar (el código que realmente causa el problema es parte de una biblioteca de terceros, por lo que no puedo simplemente actualizarlo para referirme directamente a una clase contenedora).

Supongo que deja la única opción al buscar todos los lugares en el código que están configurando String valores para cosas que el código de terceros espera pasar como matrices de bytes.

+2

Probablemente por el mismo motivo Log is final: cabrear. – AedonEtLIRA

+0

En C# la conversión mundial de String a byte [] es trivial, pero no obvia (es decir, Convert.FromBase64String, o Encoding.Utf8.GetBytes, o alguna otra codificación). ¿Tiene Java una conversión oficial de String-> byte []? –

+0

@Alexei Levenkov - Sí, Java tiene [String.getBytes()] (http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#getBytes()). – aroth

Respuesta

1

Básicamente, todos los tipos "primitivos" son definitivos. Hay un par de razones para esto. En primer lugar, el paquete está destinado a ser parcelable y puede romper algunos si su semántica se sobrescribe. Además, Bundle está destinado a actuar siempre de cierta manera. Si lo sobrescribió, podría cambiar el comportamiento que las personas esperan o incluso arrojar un código de excepción que antes se consideraba seguro.También podría argumentarse que sería una vulnerabilidad de seguridad permitirlo ya que podrían sobrescribirlo con un código que podría rastrear lo que le sucedió.

0

Si tuvieras un String que quisieras lanzar como una matriz de bytes, y no quisieras manejar esa acción fuera del Bundle, ¿cómo lo harías?

Bundle.putByteArray(String string) <<== ?? 

Ya tienes putByteArray() que almacena un ByteArray y putString() que almacena una cadena ... como usted ha dicho, la conversión es trivial, por lo que si usted tiene que tener una cadena como un ByteArray, por qué no Simplemente haz la conversión antes de ponerla en el paquete y convertirla cuando la saques.

En cuanto a por qué la clase es final, que ya ha identificado que maneja "más o menos cada tipo primitivo y unos cuantos tipos diferentes Object", ¿por qué un gran trabajo con la clase, hay cosas innecesarias? Hay conveniencia y luego hay redundancia ...

+1

¿Eh? ¿Cómo se declara la clase 'final' reducir cruft? Para una clase que es parte de un SDK que se espera que sea utilizada por cientos de miles, no millones, de desarrolladores, esperaría que los arquitectos de SDK fueran muy reacios a hacer * cualquier clase * final, porque es difícil anticiparse a todo que todos esos desarrolladores podrían querer hacer. – aroth

+0

Recordemos ... estamos hablando de Bundle, una clase de tipo diccionario que simplemente tiene la intención de empaquetar datos para el transporte. Es cierto que es difícil anticipar todo lo que esos millones de desarrolladores podrían querer hacer, pero me imagino que están gastando la mayor parte de su energía tratando de anticipar todo lo que la mayoría de esos millones de desarrolladores podrían necesitar. Si realmente es tan importante para usted, le sugiero que envíe una solicitud de cambio de SDK. –

0

La clase es definitiva porque no debe NECESIDAD para heredarla. The documentation muestra que hay un montón de métodos para get y put ing todo tipo de tipos. Si realmente está interesado en convertir un String en un byte[], entonces lo que está buscando es un método Java (click me), y no es algo exclusivo de Android.

Cuestiones relacionadas