公共对私人使用反射

时间:2018-01-08 15:22:32

标签: java jsp

我正在尝试执行以下代码:

public class Connector {
     public static Connection getConnection() {
         conn = DriverManager.getConnection(String, String, String);
         conn.getClass().getMethod("close").setAccessible(false); // this is what i am trying to achieve
     }
     public static void close(Connection c) {
         c.getClass().getMethod("close").setAccessible(true);
         try{ c.close(); }
         catch(Throwable e) {}
     }
}

我想阻止其他人调用conn.close()并强制用户使用Connector.close(),因为有时conn.close()会在调用时抛出NullPointerException。它甚至可能吗?

6 个答案:

答案 0 :(得分:2)

从理论上讲,使用"类加载器魔法"可能是这样的。

换句话说:你可以创建自己的类加载器,在加载时操纵特定的类。

使用问题中提出的反射很可能无法正常工作。请记住:反射主要是关于代码结构的反映。是的,在Java 9之前,您可以轻松转向"低级别"并更改字段的可访问性(除非有安全管理器),但除此之外,允许更改代码结构。它适用于检查,而非操作

所以,真正的答案是:这样做。而是想一想人们应该使用的适当,干净的界面。

将某些东西公之于众,没有必要在运行时将其减少到更低。这与#34;正确的OOP"相反。

答案 1 :(得分:1)

不要编写自己的类加载器, 那很可怕。

而是创建自己的类, 或许命名为RestrictedConnection并使用合成来包含真实的Connection

接下来,不要为RestrictedConnection类提供close方法。

答案 2 :(得分:0)

您可以创建一个仅包含Connection对象的包装器对象,并将每个cllas重新路由到基础Connection,并关闭。

public class CustomConnection {
    private Connection conn;
    public CustomConnection( Connection conn ) {
        this.conn = conn;
    }

    public void close() {
       throw new ForbiddenException();
    }

    public void commit() {
        this.conn.commit();
    }

    ....

}

并更改您的Connector类:

public class Connector {
     public static CustomConnection getConnection() {
         conn = DriverManager.getConnection(String, String, String);
         return new CustomConnection( conn );
     }
}

答案 3 :(得分:0)

  

我想阻止其他人调用conn.close()并强制人们使用Connector.close(),因为从jsp调用时有时会conn.close()抛出NullPointerException。它甚至可能吗?

即使 可能,它也无法满足您的目的。您只需更改JSP代码尝试调用Connection.close()时发生的异常,很可能更改为IncompatibleClassChangeError。那不是更好。

撇开一个问题,即你的JSP是否一开始就可以直接访问Connection,或者调用它的close()方法,你有时会得到一个NPE标志着应用程序逻辑中的缺陷。您应该追踪并修复它 - 为什么您的JSP有时会获得null而不是真正的 Connection - 而不是试图在症状上添加乐队助手

答案 4 :(得分:0)

我认为你最好的选择是:

  • 子类连接,如果有人调用close,则抛出异常。这是一个更简单的选项,不会给出编译时错误,但调用它将永远不会工作,并且人们不会这样做(而不是因为它工作一次然后再得到错误)。

  • 创建注释预处理器,以便在用户代码中调用方法时出现编译时错误。这更加困难和复杂,可能不是最好的方法,但会在编译时出错,这总是更好。

如果可能的话,使用Reflection最多会产生一个运行时错误,所以在这种情况下,我选择一个更简单,更清晰的选项。

答案 5 :(得分:0)

无法相信没有人提到这一点:弃用它,在以后的版本中将其删除

public转换为方法private会导致代码破坏。

处理这种情况的最佳方法:通知其他人“将来可能会将其删除”:让他们有时间在破坏旧版本之前更新代码。

这是@Deprecated的用途。如果其他人依赖他们的代码,请不要在没有警告的情况下破坏它稍后,您可以删除它,并保证您告知依赖项它将不再可访问。

是的,用户仍然可以使用它。但至少他们知道他们不应该使用它。这样做的好处是让依赖代码时间的开发人员能够更新他们的软件,而不是立即破坏他们的软件。