I am talking specifically about the state of affairs in Java. We may try to do the same trick in Scala; my point here though was to have a real-life, although contrived, example of how subclassing is different from subtyping, and Java is a easy target.
First, definitions (informal, as well as the rest of this post).
Types in Java.
Java has the following kinds of types:
- primitive (e.g. char)
 - null
 - interfaces (declared with interface keyword)
 - classes (declared with class keyword)
 - array (declared with [square brackets])
 - type variables (used in generics)
 
Subclassing: declaring one class to be a subclass of another (class ... extends ...) - this allows a subclass to inherit functionality from its superclass
Subtyping: A is a subtype of B if an instance of A can be legally placed in a context where an instance of B is required. The understanding of "legally" may vary.
Many sources state firmly that in Java, a subclass is always a subtype. Opinions that a subclass is not always a subtype are also widespread; and that's obviously true for some languages: Self type is a good source of subclass not being a subtype confusion; we do  not have Self type in Java.
In Java 5 a covariant return type inheritance was added: if class A has a method that returns X, and its subclass B declares a method with the same name and parameter list (meaning, parameter types), and returning a subclass of X, then this method overrides the method in A.
In addition to this, arrays are also covariant: if A is a subtype of B, then A[], in Java, is a subtype of  B[]. 
This last feature allows us to create an example showing that no! Subclasses in Java are not always subtypes! See:
public class Subtyping
{
    interface A
    {
        A[] m();
        void accept(A a);
    }
    interface B extends A // subtype of A
    {}
    
    public static void main(String[] args) {
        A a = new AImpl(); // see AImpl below 
        B b = new BImpl(); // see BImpl below
        // now note that B is a subtype of A.
        a.accept(a); // this works; substitution is trivial
        b.accept(a); // this works too (substitution is trivial too)
        a.accept(b); // oops, this fails! b, being a subtype of a, is not accepted at runtime
    }
    static class AImpl implements A {
        public A[] m()
        {
            return new A[]{this};
        }
        
        public void accept(A a)
        {
            a.m()[0] = this;
        }
    }
    static class BImpl extends AImpl implements B{
        public B[] m()
        {
            return new B[]{this};
        }
    }
}
So there, this code demonstrates a subclass that is not legally a subtype. By 'legally' here I mean that the code always throws a Java runtime exception without adding any client precondition predicates.
Here's a good discussion of this issue:
public boolean lspHolds(Object o) {
  return o.toString().contains("@");
}
the pyramid here is neither a square nor a triangle. But when projected, it can be percieved as one. If we say "he's a soldier", it does not mean that's all the person is; what we mean is just a projection.