These terms are weird… they come from a branch of maths known as category theory. At least we know programmers aren’t the only ones who are bad at naming things…

Covariance

Unlike the use of the word ‘covariance’ in math, in the context of the type systems, ‘covariance’ takes on sort of a more literal meaning.
The prefix ‘co-’ often carries the connotation of togetherness. Like “Coalition”, “Cooperate”, “Coagulate”.
The root word ‘variance’, implies differentness or inconsistency.
Together, it means that different things can be treated as the same!

However, it is a little more specific than that. Not just that any types can be treated the same, but covariance is specifically when a subtype can be used as a super type.
Or simply:
Covariance is when you use a subtype in place of a supertype!

Contravariance

Opposite of covariance.
But doesn’t ‘contra-’ imply the lack of variance?
Yup. contravariance is a misnomer. It really actually means ‘contra-co-variance’…

I’ll let that sit.

Invariance

The simplest of the bunch.
Invariance just means types must match exactly. No Co/Contra-variance.

In Java and C#, generics type parameters are invariant by default.

Invariance in variable assignment

public static void main(String[] args) {
	Object[] a = new String[10]; // Covariance for arrays r ok!
	List<Object> b = new ArrayList<String>(); // ERROR!!! Not the same type!
}

Compilation Error

incompatible types: ArrayList<String> cannot be converted to List<Object>

why

Why are generic type parameters invariant by default but arrays can be covariant?

Covariance of objects that store other things like collections and lists and hashmaps run into really evil type safety issues when they allow covariance. For this reason, the language developers have chosen to make generic type parameters invariant to enforce strong and strict type safety.

As for why the array types in Java and C# allow covariance, it is simply because they were created at the start of the languages, pre-dating the idea of generics. So they had to allow covariance to create flexible data structures like Lists and HashMaps.
In modern times, it is now seen as a design mistake.