Cette dernière notion, de compatibilité des types, mérite d'être approfondie. Considérons par exemple les nombres entiers et les nombres flottants. Un mathématicien, familier de la théorie des ensembles, sachant que l'ensemble des entiers est inclus dans l'ensemble des réels, à qui l'on demande de citer un nombre réel, n'hésitera pas à répondre 52#52 ; l'informaticien lui fera remarquer que 52#52 est un entier et que 53#53 est un flottant, que ces deux constantes appartiennent à des types distincts (en Java, int et double), mais acceptera cependant 52#52 comme un flottant. Inversement, ni le mathématicien ni l'informaticien n'accepterait 54#54 comme un entier. On caractérise la relation entre ces types entiers et flottants en disant que int est un sous-type de double, mais double n'est pas un sous-type de int. Cette relation, dite de sous-typage, déjà commode pour les différents types numériques, s'avère encore plus importante pour les types d'objet : pour dire, par exemple, que les rectangles sont des formes géométriques, on fera du type Rectangle un sous-type du type Forme.
La relation de sous-typage permet d'utiliser une expression d'un sous-type de 13#13 dans certains contextes où une expression de type 13#13 serait attendue :
Par contre, il n'est pas possible d'affecter à une variable de type 13#13 une expression d'un sur-type de 13#13, ou d'invoquer une fonction avec un argument dont le type est un sur-type du type du paramètre correspondant.