Définition formelle des types compatibles en Java (solidité)


J'essayais de trouver la définition algorithmique des types convertibles (et donc non convertibles) en Java.

À mon avis, un compilateur CORRECT devrait bloquer au moment de la compilation les castings explicites et implicites entre les expressions ayant des types statiques non convertibles, quelle que soit la définition de non convertible.

D'autre part, car ce serait bien si chaque référence avait un type dynamique qui est un sous-type de son type statique, afin d'éviter ClassCastExceptions au moment de l'exécution, le compilateur doit toujours bloquer les castings entre les types qui n'ont pas de sous-types communs.

Une définition de candidat qui a du sens pour moi est la suivante:

  1. Deux classes A et B sont convertibles si A est un sous-type de B ou B est un sous-type de A
  2. Une interface I et une classe C sont convertibles si C implémente I ou I et C ont un sous-type commun (une classe qui implémente I et étend C, éventuellement dans un chemin)
  3. Deux interfaces I1 et I2 sont convertibles si elles ont un sous-type commun (une classe ou une autre interface)

Cependant, les extraits suivants ne donnent PAS d'erreurs de compilation (uniquement des avertissements par exemple dans IntelliJIDEA):

interface A {}
class B {}

class Test {

  public static void main(String[] args) {
    B b  = new B();
    A a = (A)b;    // this casting will produce a run-time error
  }
}
interface M {}
interface N {}
class A implements M {}
class B extends A {}
class C extends A implements N {}

class Test {

  public static void main(String[] args) {
    N x = new C();
    M y = (B)x;   // this casting will produce a run-time error
  }
}
interface M {}
class A implements N{}
interface N {}

class Test {

  public static void main(String[] args) {
    N x = new A();
    M y = (M)x;   // this casting will produce a run-time error
  }
}

En conclusion, je veux comprendre s'il existe une définition officielle des types (in)convertibles dans les spécifications Java, et si elle a été correctement implémentée dans les compilateurs existants.

Author: Nikolai Dmitriev, 2019-11-20

1 answers

La question que vous posez concerne la solidité du système de type java (voici une belle intro sur le sujet).

Il n'y a pas de définition formelle dans le cas de java, mais un certain nombre de reconstructions existent, arrivant à des instructions comme "Nous avons été surpris par la subtilité et la non-uniformité de la sémantique du langage, d'autant plus que sa description est plutôt colossale, ambiguë et erronée." avec une tendance à le considérer par et grand son , à part des pépins évidents.

Les problèmes évidents proviennent de problèmes de compatibilité arrière , par exemple avec les collections typées qui ont été placées au-dessus des collections non typées, et peuvent toujours être sapées par des opérations prenant la voie non typée. La question de la diffusion de l'OP s'attarde peut être une autre saveur de la question, puisque que devrait-on penser de char c = (char)1024;?

D'autre part des incohérences fondamentales ont également été déterrées, plus sur le niveau de"fonctions polymorphes paramétriques qui peuvent transformer n'importe quel type en n'importe quel type sans (down)casting ". Trouvez une discussion sur ce qui est fondamental et ce qui est un problème ici, faisant également allusion aux divergences entre la spécification du langage et le compilateur.

Il peut être intéressant de noter que l'argument est également valable pour le langage Scala jusqu'à la version 2.x , et peut-être tout autre langage OO à l'échelle de l'industrie, seul le prochain Scala 3 est prouvé débarrassez-vous d'eux . Un effort qui a pris aux contributeurs près d'une décennie et qui est censé être une nouveauté dans le domaine des langages orientés objet.

 2
Author: Nikolai Dmitriev, 2019-11-20 18:14:10