- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在编写加密实用程序类时,我遇到了以下方法的问题:
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)
现在使用 java8
类 SecretKeySpec (javadocs 8)已制作Destroyable (javadocs 8)和方法Destroyable#destroy现在是 default
这很好根据 statement
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.
尽管类 ScretKeySpec
本身没有改变,但代码编译没有任何问题,只有接口(interface) SecretKey已经。
问题是在oracle的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 具有误导性,因为除了合法的销毁调用之外,没有任何东西试图有效地销毁 key ,UnsupportedOperationException 会更合适,你会立即知道发生了什么)
我的方法是(类型检查/转换/调用)
if(Destroyable.class.isInstance(key))
((Destroyable)key).destroy();
对于判断是否销毁有误吗?有什么替代方案?
这是误解还是他们只是忘记在 ScretKeySpec
中添加有意义的实现?
最佳答案
Is this a misconception or did they just forget to add meaningful implementation in SecretKeySpec?
他们没有忘记。 SecretKeySpec
确实需要一个实现,但它还没有完成。查看错误 JDK-8008795 .抱歉,尚无关于何时修复此问题的预计时间。
理想情况下,destroy
的有效实现应该在添加默认方法时添加,并且接口(interface)被改造到现有类上,但它并没有发生,可能是因为调度。
您引用的教程中的“二进制兼容性”概念是一个相当严格的定义,Java Language Specification, chapter 13 使用的就是这个定义。 .基本上它是关于库类的有效转换,当与针对这些库类的旧版本编译的类结合时,不会在运行时导致类加载或链接错误。这与导致编译时错误的源代码不兼容和行为不兼容形成对比,这通常会导致系统运行时行为发生不需要的更改。比如抛出之前没有抛出的异常。
这并不是要尽量减少您的代码被破坏的事实。这仍然是一个不兼容。 (对不起。)
作为解决方法,您可以添加 instanceof PrivateKey || instanceof SecretKey
(因为这些显然是缺少destroy
实现的类)并让测试断言它们确实抛出DestroyFailedException
,否则如果instanceof Destroyable
执行测试中的其余逻辑。当这些实例在某些 future 的 Java 版本中得到合理的 destroy
实现时,测试将再次失败;这将是一个信号,将测试改回对所有 Destroyable 调用 destroy
。 (另一种方法可能是完全忽略这些类,但这样有效的代码路径可能会在相当长的一段时间内未被发现。)
关于java8 : dealing with default methods,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24850737/
自从我开始工作(约 6 年)以来,我一直是 .NET 的一员。最近在做一个使用Django的项目,需要并行学习Python。很多时候我碰到的 Python 代码看起来很简单,但我就是看不懂。这是其中之
谁能解释一下 JLS §8.4.8.4 中提到的“严格的default-abstract 和default-default 冲突规则” . 它们是否在 JLS 中定义?我似乎找不到他们的定义。 最佳答
我在我的启动图像通用项目中添加了“Default.png,Default-568h@2x.png,Default@2x.png”这三个文件,我有三个不同的图像,分辨率与苹果中提到的完全相同文档,适用于
我试图在删除 AWS RDS MySQL 数据库后删除默认的数据库参数组,但出现以下错误 Failed to delete default.mysql8.0: Default DBParameterG
我想使用 firebase 云函数发送通知,所以我尝试使用 firebase.messaging().getToken() 获取 token ,但我不断收到错误消息: TypeError: fireb
无法通过 Instagram 登录我的应用。我正在使用 react-native instagram 包,但我面临这个问题,因为 _react3.default.creteRef() 不是一个函数。引
从 Rust 1.6 开始,当前特征 Default定义为, pub trait Default { fn default() -> Self; } 为什么不是这个 pub trait Def
在我的第一次代码审查(不久前)中,我被告知在所有 switch 语句中包含默认子句是一种很好的做法。我最近想起了这个建议,但不记得其理由是什么。现在对我来说听起来很奇怪。 始终包含默认语句是否有合理的
这个错误很奇怪。在 firebase 中 react native 有什么问题我已经通过 npm install 安装了 firebase这是我的代码 import React, {Component
对于以下 3 种编译情况: gcc -o helloc hello.c (1) g++ -o hellocpp hello.cpp
我有一个 switch 语句。它几乎可以正常工作,但是它不仅显示一个案例,还显示选定的案例,然后显示默认案例。这是我的代码: var people = { names: ["Sam", "Tim"
这个问题在这里已经有了答案: Default keyword in Swift parameter (1 个回答) 关闭 6 年前。 我试图理解前置条件函数并遇到了“= default”。快速谷歌和
禁止!配置的服务帐户无权访问。服务帐户可能已被撤销。用户“system:serviceaccount:default:default”无法获取命名空间“mycomp-services-process”
我一直在我的 React 中广泛使用命名导出和默认导出,我遇到了这 2 个相似的语法。 从'./Button'导出默认值; export { default } from './Button'; 有人
我很困惑什么时候使用 .prototype 来扩展一个对象,什么时候不使用它。像下面的部分代码,为什么不在FacebookApi.defaults中使用.prototype,难道.prototype只
这个问题在这里已经有了答案: What is the difference between "var=${var:-word}" and "var=${var:=word}"? (4 个答案) 关闭
我想创建一个数据类基类,其中子类中的所有字段都自动可选且默认为无(如果未提供默认值)。 下面的代码……几乎可以满足我的要求,但又不完全是。它出错的方式就像我从未编写过 __init_subclass_
所以我有三个 Typescript 文件: 配置/env/development.ts import { Config } from '../config'; class DevConfig {
我在一个名为 Activity 的表中添加了一个名为 Ordinal 的新列。问题是我给了它一个 UNIQUE 约束,将它设置为允许 NULL(尽管我最终不会想要这个。我只需要将它设置为那个以使脚本更
嗨,我是 struts2 的新手,在我的项目中,我在注册页面使用 json-default 扩展,并使用validation.xml 文件验证它,在同一个项目中,我在登录页面使用 struts-def
我是一名优秀的程序员,十分优秀!