扩展Java X509Certificate
以便为其添加自定义函数的正确方法是什么?让我们来看看:
public abstract class MyX509Certificate extends java.security.cert.X509Certificate {
protected X509Certificate() {
super();
}
}
通常,您只需从密钥库获取证书并将其转换为:
X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
我试图像这样投我的:
MyX509Certificate my = (MyX509Certificate) keystore.getCertificate(alias);
但我明白了:
线程中的异常" main" java.lang.ClassCastException:sun.security.x509.X509CertImpl无法强制转换为ca.carillon.crypto.cert.MyX509Certificate
为什么?
答案 0 :(得分:2)
错误消息显示:
java.lang.ClassCastException:sun.security.x509.X509CertImpl无法强制转换为ca.carillon.crypto.cert.MyX509Certificate
它基本上说一种类型(sun.security.x509.X509CertImpl
)无法转换为其他类型(您的MyX509Certificate
类)。
sun.security.x509.X509CertImpl
是subclass of java.security.cert.X509Certificate
,并且keystore.getCertificate
方法返回了它。
X509Certificate
是abstract class,keystore.getCertificate
将返回它的内部实现(子类)。这个子类可能会有所不同,具体取决于您的环境(JVM,提供程序等)。在这种情况下,它会返回sun.security.x509.X509CertImpl
- 您无法在任何地方看到此课程,因为它是JVM内部的,并且在大多数情况下您实际上并不需要知道它。您需要知道的只是X509Certificate
。
当您创建自己的X509Certificate
子类时,层次结构将如下所示:
X509Certificate <- super class
|
-------------------------------------
| |
sun.security.x509.X509CertImpl MyX509Certificate <- subclasses of X509Certificate
kesytore(X509CertImpl
)和您的自定义类(MyX509Certificate
)返回的类都是X509Certificate
的子类。
当密钥库返回X509CertImpl
时,可以将其强制转换为X509Certificate
(子类实例可以分配给具有超类类型的变量)。
但如果你试图这样做:
MyX509Certificate my = (MyX509Certificate) keystore.getCertificate(alias);
密钥库返回X509CertImpl
,X509Certificate
,但 <{1}} - 你不能扮演一个兄弟姐妹&#34;上课到另一个。 MyX509Certificate
只知道其超类(X509CertImpl
),但它不了解X509Certificate
。
如果您想为MyX509Certificate
添加功能,或许扩展它不是最佳解决方案,您应该选择"Composition over Inheritance" approach。
您可以创建一个具有一个X509Certificate
(AKA&#34;包装器&#34;)的类,并使用它添加功能:
X509Certificate
然后使用密钥库返回的证书创建此类:
public class MyCustomCertificate {
// wraps a X509Certificate
private X509Certificate cert;
public MyCustomCertificate(X509Certificate cert) {
this.cert = cert;
}
public void myCustomFunctionality1() {
// do something with this.cert
}
public void myCustomFunctionality2() {
// do something with this.cert
}
// and so on...
}
X509Certificate x509Cert = (X509Certificate) keystore.getCertificate(alias);
MyCustomCertificate myCert = new MyCustomCertificate(x509Cert);
有许多未实现的方法,扩展它将需要你实现它们(这不值得做,IMO)。相反,您可以使用密钥库返回的证书(已经实现了所有这些方法)并添加了您想要的功能。
但是,如果您真的想扩展X509Certificate
,可以将方法委托给包装证书:
X509Certificate
答案 1 :(得分:1)
要回答您关于 为什么 的实际问题,您无法向自己的班级投票。实例化的对象不是MyX509Certificate
,因此无法强制转换。如果类是该类型,则只能转换为类型。
例如:
public abstract class AbstractParentClass {
}
public class ChildClassA extends AbstractParentClass {
}
public class ChildClassB extends AbstractParentClass {
}
您现在可以实例化ChildClassA
并将其分配给AbstractParentClass
类型的变量,然后将其转换为ChildClassA
变量
public static void main(String[] args){
AbstractParentClass instance = new ChildClassA();
ChildClassA sameInstance = (ChildClassA) instance;
}
无法 做的是将其强制转换为不属于其类分类的类。
AbstractParentClass instance = new ChildClassA();
// This is runtime error because ChildClassB is not a ChildClassA
ChildClassB sameInstance = (ChildClassB) instance;
因此,除非您自己实例化该类,而不是因为您正在从密钥库中检索它,否则该类不是MyX509Certificate
类型。