Oh, i see what you mean. Yes, true.
Hang on, when you say 'type safety', what do you mean? Do you mean at the
java level, or preventing the client code sending an integer parameter where
a string is needed and things like that? I'd been assuming the former, but
i'm not sure i've understood right.
Furthermore, i wonder if you could use generics to unite the two.
If you consider statements with one parameter, then something like:
interface Connection {
PreparedStatement<T> prepareStatement(String sql, Class<T> paramtype) ;
}
interface PreparedStatement<T> {
ResultSet executeQuery(T param) ;
}
Where prepareStatement would throw an exception if the paramType didn't
match that which was implied by the query string.
I don't think you can extend this to arbitrarily sized argument lists,
though. You'd need something like:
interface Connection {
PreparedStatement<T...> prepareStatement(String sql, Class<T...> paramtype...) ;
}
interface PreparedStatement<T...> {
ResultSet executeQuery(T... param...) ;
}
With client code looking like:
PreparedStatement<String, int> stmt =
conn.prepareStatement("SELECT * FROM customers WHERE county = ? AND creditLimit >= ?", String.class, int.class) ;
ResultSet rows = stmt.executeQuery("Rutland", 4000) ;
AFAIK, there's no way to do this in present-day java.
Well, not without genuine evil ...
abstract class Parameter<T, P extends Parameter> {
private T value ;
protected Parameter(T value) {
this.value = value ;
}
public T getValue() {
return value ;
}
public abstract P getNextParameter() ;
}
class Param<T, P> extends Parameter<T, P> {
private P next ;
public Param(T value, P next) {
super(value) ;
this.next = next ;
}
public P getNextParameter() {
return next ;
}
}
class Null extends Parameter<Void, Null> {
public static final Null NO_MORE_PARAMS = new Null() ;
private Null() {
super(null) ;
}
public Null getNextParameter() {
return null ;
}
}
interface PreparedStatement<P extends Parameter> {
ResultSet executeQuery(P param) ;
}
import static Null.NO_MORE_PARAMS ;
PreparedStatement<Param<String, Param<int, Null>>> stmt ;
stmt.executeQuery(new Param("B. L. Zebub", new Param(666, NO_MORE_PARAMS))) ;
I haven't actually tried to compile this, so i'm not sure it's right. I
also haven't quite thought through how you'd construct the actual
PreparedStatement object in such a way that type safety was preserved. You
might need a generic ParameterType class too.
My head hurts.
tom