Implement a Shape abstract class
I am generally impressed with the consistency of the implementations, neatness, etc.

I have a comment about the basic premise. The Shape should not be an abstract class, but an interface. It has no concrete implementations for any methods, and making it an abstract class makes it hard to inherit from other places too. Consider this instead:

public interface Shape {
    public double area();
    public double perimeter();
}


In addition to that concern, the following are also things you should consider:


The pi field on your Circle class should be private. There's no need to re-expose an already public constant in another way.
I would avoid the 'unit' default constructors. They don't help with anything. When would someone want to call new Triangle() and not want to have the dimensions?
Your classes are missing a toString() method. These are useful for many reasons, especially debugging.
You don't have a plan for out-of-bound dimensions. What will you do with negative, NaN, or infinite input?