どこに線を引くかが問題です。暗黙のダウンキャストの有効性を検出する言語を設計できます。
public static void main(String args[]) { 
    // An implicit upcast 
    Fruit parent = new Apple();
    // An implicit downcast to Apple 
    Apple child = parent; 
}
次に、メソッドを抽出してみましょう。
public static void main(String args[]) { 
    // An implicit upcast 
    Fruit parent = new Apple();
    eat(parent);
}
public static void eat(Fruit parent) { 
    // An implicit downcast to Apple 
    Apple child = parent; 
}
私たちはまだ元気です。静的解析ははるかに困難ですが、それでも可能です。
しかし、問題は誰かが追加した2番目の瞬間に現れます:
public static void causeTrouble() { 
    // An implicit upcast 
    Fruit trouble = new Orange();
    eat(trouble);
}
では、どこでエラーを発生させますか?これはジレンマを引き起こします。問題はにあると言えますが、Apple child = parent;これは「以前は機能していました」と反論することができます。一方、追加   eat(trouble);によって問題が発生しました」が、ポリモーフィズムの核心は、それを可能にすることです。
この場合、プログラマーの仕事の一部を行うことができますが、それを完全に行うことはできません。あきらめる前にそれをさらに進めるほど、何がうまくいかなかったかを説明することが難しくなります。したがって、エラーを早期に報告するという原則に従って、できるだけ早く停止することをお勧めします。
ところで、Javaでは、あなたが説明したダウンキャストは実際にはダウンキャストではありません。これは一般的なキャストで、リンゴをオレンジにキャストすることもできます。つまり、技術的に言えば、@ chiのアイデアはすでにここにあります。Javaにはダウンキャストはなく、「エブリキャスト」だけです。結果の型が引数の型の下流で見つからない場合にコンパイルエラーをスローする、特殊なダウンキャストオペレーターを設計することは理にかなっています。プログラマーが非常に正当な理由なしにそれを使用しないようにするために、「エブリキャスト」の使用をはるかに困難にすることは良い考えです。C ++のXXXXX_cast<type>(argument)構文が思い浮かびます。