Perché negli esempi sul libro a volte compare throws e a volte no?

Qui ad esempio compare:

codice:
/* Display a text file. 
   To use this program, specify the name 
   of the file that you want to see. 
   For example, to see a file called TEST.TXT, 
   use the following command line. 
 
   java ShowFile TEST.TXT 
 
   This variation wraps the code that opens and 
   accesses the file within a single try block. 
   The file is closed by the finally block. 
*/ 
 
import java.io.*; 
 
class ShowFile { 
  public static void main(String args[]) 
  { 
    int i; 
    FileInputStream fin = null; 
 
    // First, confirm that a file name has been specified. 
    if(args.length != 1) { 
      System.out.println("Usage: ShowFile filename"); 
      return; 
    } 
 
    // The following code opens a file, reads characters until EOF 
    // is encountered, and then closes the file via a finally block. 
    try { 
      fin = new FileInputStream(args[0]); 
 
      do { 
        i = fin.read(); 
        if(i != -1) System.out.print((char) i); 
      } while(i != -1); 
 
    } catch(FileNotFoundException e) { 
      System.out.println("File Not Found."); 
    } catch(IOException e) { 
      System.out.println("An I/O Error Occurred"); 
    } finally { 
      // Close file in all cases. 
      try { 
        if(fin != null) fin.close(); 
      } catch(IOException e) { 
        System.out.println("Error Closing File"); 
      } 
    } 
  } 
}
e qui no:

codice:
/* Copy a text file. 
   To use this program, specify the name 
   of the source file and the destination file. 
   For example, to copy a file called FIRST.TXT 
   to a file called SECOND.TXT, use the following 
   command line. 
 
   java CopyFile FIRST.TXT SECOND.TXT 
*/ 
 
import java.io.*; 
 
class CopyFile { 
  public static void main(String args[]) throws IOException  
  { 
    int i; 
    FileInputStream fin = null; 
    FileOutputStream fout = null; 
 
    // First, confirm that both files has been specified. 
    if(args.length != 2) { 
      System.out.println("Usage: CopyFile from to"); 
      return; 
    } 
 
    // Copy a File. 
    try { 
      // Attempt to open the files. 
      fin = new FileInputStream(args[0]); 
      fout = new FileOutputStream(args[1]); 
 
      do { 
        i = fin.read(); 
        if(i != -1) fout.write(i); 
      } while(i != -1); 
 
    } catch(IOException e) { 
      System.out.println("I/O Error: " + e); 
    } finally { 
      try { 
        if(fin != null) fin.close(); 
      } catch(IOException e2) { 
        System.out.println("Error Closing Input File"); 
      } 
      try { 
        if(fout != null) fout.close(); 
      } catch(IOException e2) { 
        System.out.println("Error Closing Output File"); 
      } 
    } 
  } 
}
Chi mi spiega perché nel primo caso throws è necessario?