在编写加密实用程序类时,我遇到了以下方法的问题:
public static void destroy(Key key) throws DestroyFailedException {
if(Destroyable.class.isInstance(key)) {
((Destroyable)key).destroy();
}
}
@Test
public void destroySecretKeySpec() {
byte[] rawKey = new byte[32];
new SecureRandom().nextBytes(rawKey);
try {
destroy(new SecretKeySpec(rawKey , "AES"));
} catch(DestroyFailedException e) {
Assert.fail();
}
}
javax.crypto.spec.SecretKeySpec
在上述方法的特定情况下,java7
因为SecretKeySpec (javadocs 7)没有实现Destroyable (javadocs 7)
现在,SecretKeySpec (javadocs 8)java8
类已经被Destroyable (javadocs 8)和Destroyable#destroy方法现在可以根据这个声明default
默认方法使您能够向库的接口添加新功能,并确保与为这些接口的旧版本编写的代码的二进制兼容性。
然后代码编译没有任何问题,尽管类ScretKeySpec
本身没有改变,只有接口SecretKey已经改变。
问题是oracle's jdk8
该destroy
方法中有以下实现:
public default void destroy() throws DestroyFailedException {
throw new DestroyFailedException();
}
这会导致运行时出现异常。
所以二进制兼容性可能没有被破坏,但现有的代码已经被破坏了。上面的测试通过java7
但不通过java8
所以我的问题是:
通常如何处理可能导致异常的默认方法 - 因为未实现或不受支持 - 或运行时出现意外行为?除了做
Method method = key.getClass().getMethod("destroy"); if(! method.isDefault()) { ((Destroyable)key).destroy(); }
这仅对 java8 有效,并且在将来的版本中可能不正确,因为默认方法可能会获得有意义的实现。
将此默认方法保留为空而不是引发异常不是更好吗(IMO 具有误导性,因为除了合法调用销毁之外,没有尝试有效地销毁密钥,UnsupportedOperationException会更合适,你会立即知道发生了什么)
我的方法是(类型检查/转换/调用)
if(Destroyable.class.isInstance(key)) ((Destroyable)key).destroy();
用于判断是否销毁有误?什么是替代方案?
这是一种误解,还是他们只是忘记在其中添加有意义的实现
ScretKeySpec
?