> if the constructor were made public I would then have to validate the student, using a private method, to ensure that if the student is domestic, the client can't pass a list of documents by throwing an exception. The static methods allowed the creation of the student objects and the client can't pass a List<String> documents for domestic students, and there is no need to throw an exception. 

This assumption is simply wrong because your *factory method* does not check any argument. So there is no difference whether you create your `Student` objects vis your factory method or not.

On the other hand having a *factory method* that really checks consistency of the parameters is a good practice. But there is no need to have that in the class itself and therefor it does not need to be `static`. Especially if you do not take all the parameters in one method but provide a separate setter for each.  The name for is *Builder Pattern*. 

    StudenBuilder{
        private  String id;
        private  String firstname;
        private  String lastname;
        private  Collection<String> documents;
        private  StudentType typeofStudent;
    
       public StudenBuilder withId(String id){ 
         this.id=id;
         return this;
       }
       public StudenBuilder withFirstname(String firstname){ 
         this.firstname=firstname;
         return this;
       }
       public StudenBuilder withLastname(String lastname){ 
         this.lastname=lastname;
         return this;
       }
       public StudenBuilder with(Collection<String> documents ){
         Collections.unmodifiableList(new ArrayList<String>(documents));
          return this;
       }
       public StudenBuilder withStudentType(StudentType typeofStudent ){
          this.typeofStudent=typeofStudent;
         return this;
       }
       public Student build(){
          // check consistency
          // e.g. require documents for a certain StudentType
          return new Student(id, firstname, lastname, documents, typeofStudent);
       }
    }

The usage would look like this:

    Student newStudent = new StudentBuilder()
                         .withId("someId")
                         .withFirstName("some first name")
                         .withLastName("some last name")
                         .withStudentType(StudentType.SOME)
                         .build();