1

I have several objects that are subClasses of a particular class (ValidateVO). All of these are stored in our database with a type code on the validate table. I want to create one method that I can call for each of these classes that gets the relevant information. I'm not sure what type to make the instantiated Class, or maybe I don't know how to properly declare generics for this

private List<? extends ValidateVO> getValidateSubclassByType(Class<? extends ValidateVO> clazz, String type) {
    List<? extends ValidateVO> validates = new ArrayList<>();

    StringBuilder bldValidates = new StringBuilder()
    .append("SELECT VALIDATE_ID, VALIDATE_DESCRIPTION, VALIDATE_ACTIVE ")
    .append("FROM tblVALIDATE WHERE VALIDATE_TYPE = ?");

    try (
            Connection con = dataSource.getConnection();
            PreparedStatement pstmtValidates = con.prepareStatement(bldValidates.toString());
            ) {
        pstmtValidates.setString(1, type);
        ResultSet rsWholesalerGroups = pstmtValidates.executeQuery();
        if (rsWholesalerGroups.isBeforeFirst()) {
            while (rsWholesalerGroups.next()) {
                // if I use ValidateVO here, I have a problem when I add it to the list
                ValidateVO validate = clazz.newInstance();
                validate.setId(rsWholesalerGroups.getInt("VALIDATE_ID"));
                validate.setName(rsWholesalerGroups.getString("VALIDATE_DESCRIPTION"));
                validate.setActive(rsWholesalerGroups.getString("VALIDATE_ACTIVE").equals("Y"));
                // The following is the line with the error
                // The method add(capture#2-of ? extends ValidateVO) in the type List<capture#2-of ? extends ValidateVO> is not applicable for the arguments (ValidateVO)
                validates.add(validate);
            }
        } else {
            System.out.println("No WHOLESALERS");
        }
    } catch (SQLException ex) {
        ex.printStackTrace();
    }

    return validates;
}
bcr666
  • 2,157
  • 1
  • 12
  • 23
  • 1
    This might help https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super – Minn Dec 08 '18 at 20:37

1 Answers1

1

You don't need wildcard types. The method can define a generic parameter and use that both for the parameter and for the return types. newInstance called on Class<T> returns T.

private <T extends ValidateVO> List<T> getValidateSubclassByType(Class<T> clazz, String type) {
    List<T> validates = new ArrayList<>();

    StringBuilder bldValidates = new StringBuilder()
            .append("SELECT VALIDATE_ID, VALIDATE_DESCRIPTION, VALIDATE_ACTIVE ")
            .append("FROM tblVALIDATE WHERE VALIDATE_TYPE = ?");

    try (Connection con = dataSource.getConnection();
            PreparedStatement pstmtValidates = con.prepareStatement(bldValidates.toString());) {
        pstmtValidates.setString(1, type);
        ResultSet rsWholesalerGroups = pstmtValidates.executeQuery();
        if (rsWholesalerGroups.isBeforeFirst()) {
            while (rsWholesalerGroups.next()) {
                T validate = clazz.newInstance();
                validate.setId(rsWholesalerGroups.getInt("VALIDATE_ID"));
                validate.setName(rsWholesalerGroups.getString("VALIDATE_DESCRIPTION"));
                validate.setActive(rsWholesalerGroups.getString("VALIDATE_ACTIVE").equals("Y"));
                validates.add(validate);
            }
        } else {
            System.out.println("No WHOLESALERS");
        }
    } catch (SQLException ex) {
        ex.printStackTrace();
    }

    return validates;
}
ernest_k
  • 44,416
  • 5
  • 53
  • 99