我开始用Java做一些高级的事情(对我来说是先进的xD)。
我有这个:
interface ResultSet {
public void close();
}
class DbResult {
ResultSet data;
Statement statement;
public void close() {
this.data.close();
this.statement.close();
}
}
我试图这样做:
interface ResultSet { //I think that is abstract or something
public void close();
}
abstract class DbResult implements ResultSet {
Statement statement;
@Override
public void close() {
super.close();
this.statement.close();
}
}
显然它不起作用,因为ResultSet不是超类。我还尝试使DbResult成为一个接口并扩展ResultSet,但它告诉我接口方法不能有一个主体,所以我不知道如何做到这一点。
我试图这样做,所以我可以关闭结果语句,结果只有一个变量而不是2,所以不会因为忘记关闭语句而导致内存泄漏。
Database类以这种方式查询数据库:
class Database {
private Connection connection;
/* Here a constructor that
inits the connection and such things */
public DbResult query(String q) {
Statement statement = this.connection.createStatement();
DbResult result = (DbResult)statement.executeQuery(q);
result.statement = statement;
return result;
}
修改 好吧,既然我知道我不知道我是否能以一种黑客的形式做到这一点,我想:
有没有办法检查是否在类中调用了不存在的方法,捕获它并在另一个变量中调用该方法名?
例如,ResultSet
有一个名为getString()
的方法。我想知道是否可以调用DbResult.getString("blah");
,而DbResult
会将该方法重定向到this.data
,但是在DbResult类中实现getString
方法。
我想知道是否可行,因为ResultSet
中有大量函数,而调用DbResult.data.METHOD
不如DbResult.METHOD
优雅。
答案 0 :(得分:1)
也许您想要使用的是抽象类而不是接口,例如:
interface A2 {
void foo();
void otherAbstractMethod();
}
abstract class AbstractA2 implements A2 {
@Override // implemented metthod
public void foo() {
System.out.println("From the default method");
}
@Override //unimplemented abstract method
public abstract void otherAbstractMethod();
}
class B2 extends AbstractA2 {
@Override
public void foo() {
super.foo();
System.out.println("From the override");
}
@Override
public void otherAbstractMethod() {
// TODO add some code
// the line below won't compile
// super.otherAbstractMethod();
}
}
并测试它
public class TestA {
public static void main(String[] args) {
A2 myA = new B2();
myA.foo();
}
}
修改强>
关于你的问题的变化,哪些变化一切并且彻底改变,我再次感到困惑。 ResultSet 是您的接口,还是您尝试实现java.sql.ResultSet?如果是后者,您的代码将充满困难,因为您的类无法扩展,并且无法替代查询返回的ResultSet的实际类型。我没有看到您使用合成和不继承的替代品。换句话说,继续你最初做的事情 - 创建包含ResultSet字段但不是实现接口的字段。
请注意,如果使用Decorator Pattern,则可以实现ResultSet。有了这个,你就可以创建自己的类,这是一个&#34;包装器&#34;对于原始类型,将要求您使用合成和继承,并为接口创建所有需要的方法,然后将它们委托给ResultSet组件。< / p>
例如,ResultSet有一个名为getString()的方法。我想知道是否可以调用DbResult.getString(&#34; blah&#34;);并且DbResult会将该方法重定向到this.data,但是在DbResult类中实现getString方法。
不,你必须在你的子装饰器类中实现所有这些方法。
答案 1 :(得分:1)
猜猜:它已经是Java的一部分(从版本7开始):
Java API Documentation: java.lang.AutoCloseable
public interface AutoCloseable {
void close();
}
ResultSet
,Statement
(以及许多其他类)已经实现了此接口。
最好的事情是:try
在try语句中管理的资源是automatically closed, if they implement this interface。
答案 2 :(得分:1)
是否有办法检查是否调用了不存在的方法 在类中,捕获它并在另一个变量中调用该方法名称?
因此,您希望将调用包装到实例而不必扩展它或实现其每个方法,这实际上是可行的,但仅适用于通过接口公开的方法。
好消息是ResultSet
实际上是一个界面。
这可以通过动态代理来完成(请参阅Proxy
和InvocationHandler
)。
您可以创建由Proxy
支持的InvocationHandler
,其中包含ResultSet
。对您的代理实例的任何调用都将委派给InvocationHandler
,ResultSet
可以直接处理它们,或者在您的情况下,将它们委托给包装的实际public class MyResultSetInvocationHandler implements InvocationHandler {
private final ResultSet wrappedResultSet;
private MyResultSetInvocationHandler(ResultSet resultSet) {
wrappedResultSet = resultSet;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// call method on delegate
Object result = method.invoke(wrappedResultSet, args);
// optionally do something with the result, and return it afterwards
return result;
}
catch (Throwable ex) {
// handle exception, or rethrow it
throw ex;
}
}
/**
* Factory method, creates a dynamic proxy wrapping the given result set.
*/
public static ResultSet wrap(ResultSet delegate) {
MyResultSetInvocationHandler handler = new MyResultSetInvocationHandler(delegate);
return (ResultSet) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { ResultSet.class }, handler);
}
}
实例。
// the actual result set
ResultSet resultSet = ...
// and your wrapped proxy/handler as a surrogate
resultSet = MyResultSetInvocationHandler.wrap(resultSet);
用法:
{{1}}