jdk - java para android gratis
Creación de aplicaciones de Android con el JDK incorrecto(?) De alguna manera (4)
Está utilizando una implementación especial de ConcurrentHashMap
La declaración de ''java.util.concurrent.ConcurrentHashMap'' aparece en /system/framework/core-oj.jar
que no tiene keySet()
método keySet()
Recientemente actualicé mi proyecto de Android para Android Studio 3. Quería admitir las funciones de lenguaje Java 8, así que agregué lo siguiente a build.gradle:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
Entonces ejecuto mi aplicación en un dispositivo Android 8.0.0. En el tiempo de ejecución veo
java.lang.NoSuchMethodError: No virtual method keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; in class Ljava/util/concurrent/ConcurrentHashMap; or its super classes (declaration of ''java.util.concurrent.ConcurrentHashMap'' appears in /system/framework/core-oj.jar)
Supongo que esto tiene que ver con el hecho de que la firma de keySet()
se cambió en Java 8 desde que regresó Set<K>
a que devolvió KeySetView<K,V>
.
La línea que ha provocado la excepción se ve así:
for (Long id : mSomeMap.keySet())
KeySetView
implementa Set
, sin duda es Iterable
, por lo que si esta línea se interpreta como Java 7 o Java 8, habría pensado que funcionaría de cualquier manera. Mi comprensión de los fundamentos de Java es incompleta: ¿qué está pasando aquí?
Actualizar
Mi comprensión escamosa hasta ahora es esto:
Si bien Android ahora es compatible con algunas características del lenguaje Java 8, su API no es idéntica a Java 8. En particular, la implementación de ConcurrentHashMap.keySet()
Android devuelve un Set
, mientras que la implementación de ConcurrentHashMap.keySet()
Java devuelve un KeySetView
.
De algún modo, Android Studio ha logrado compilar mi aplicación con el JDK estándar de Java 8 y, por lo tanto, en el tiempo de ejecución espera encontrar un método con la firma KeySetView<K,V> keySet()
. Sin embargo, ConcurrentHashMap
de Android no tiene un método con esta firma, así que obtengo un NoSuchMethodError
.
No estoy más cerca de averiguar cómo o por qué Android Studio se está construyendo con un JDK incompatible. En la Estructura del proyecto, ''Usar JDK incrustado (recomendado)'' está marcado, así que asumo que Android Studio se está construyendo con el JDK que viene incluido.
No es una solucion
La mayoría de los comentarios / respuestas hasta ahora han señalado que solo puedo declarar el Map
ConcurrentHashMap
como un Map
para evitar esto. Esa es una solución, y no una solución. Si el problema subyacente es que mi aplicación se está construyendo con el JDK incorrecto, puede haber otras instancias en las que las firmas de los métodos se desvíen, y dado que no puedo probar el 100% de las rutas de código en un proyecto grande, puedo '' t garantiza que no se NoSuchMethodErrors
más NoSuchMethodErrors
en el tiempo de ejecución.
Estoy usando esta solución y parece que está funcionando.
private final Map<ImageView, Request> mPendingRequests =
new ConcurrentHashMap<ImageView, Request>();
Puedes declarar ConcurrentMap
interfaz de ConcurrentMap
:
ConcurrentMap mSomeMap = new ConcurrentHashMap();
entonces use así:
for (Long id : mSomeMap.keySet())
acaba de lanzarlo al Map<?, ?>
:
for (Long id : ((Map< Long, ?>)mSomeMap).keySet())