我试过了:
class protectedfinal
{
static abstract class A
{
protected final Object a;
}
static class B extends A
{
{ a = new Integer(42); }
}
public static void main (String[] args)
{
B b = new B();
}
}
但我收到了这个错误:
protectedfinal.java:12: error: cannot assign a value to final variable a
{ a = new Integer(42); }
^
1 error
如何解决这个问题?
有些人建议使用构造函数,但这只适用于某些情况。它适用于大多数对象,但不能从构造函数中引用对象本身。
static abstract class X
{
protected final Object x;
X (Object x) { this.x = x; }
}
static class Y extends X
{
Y () { super (new Integer(42)); }
}
static class Z extends X
{
Z () { super (this); }
}
这是错误:
protectedfinal.java:28: error: cannot reference this before supertype constructor has been called
Z () { super (this); }
^
有人可能认为存储这种引用没有多大意义,因为this
已经存在。这是正确的,但这是在构造函数中使用this
时出现的一般问题。无法将this
传递给任何其他对象以将其存储在最终变量中。
static class Z extends X
{
Z () { super (new Any (this)); }
}
那么我怎样才能编写一个抽象类,它强制所有子类都有一个在子元素中初始化的最终成员?
答案 0 :(得分:6)
您必须在其构造函数中初始化A.a
。子类将使用super()
将初始值设定项传递给A.a
。
class protectedfinal {
static abstract class A {
protected final Object a;
protected A(Object a) {
this.a = a;
}
}
static class B extends A {
B() {
super(new Integer(42));
}
}
public static void main (String[] args) {
B b = new B();
}
}
在调用超类构造函数之前不能使用this
,因为在此阶段对象未初始化,即使Object
构造函数此时尚未运行,因此调用任何实例方法将导致不可预知的结果。
在您的情况下,您必须以另一种方式解决Z
类的循环引用:
Z () { super (new Any (this)); }
使用非最终字段或更改类层次结构。实例方法super(new Any(a()));
的解决方法由于同样的原因不起作用:在运行超类构造函数之前,不能调用实例方法。
答案 1 :(得分:2)
在我个人的观点中,你的问题暗示了设计的缺陷。 但要回答你的问题。如果绝对必要,您可以change final fields in java using reflection。
如果一切都失败了,你仍然可以使用sun.misc.unsafe。
但是我强烈反对你这样做,因为它可能会杀死你的虚拟现实。
答案 2 :(得分:0)
到目前为止,我的工作是使用方法而不是最终成员:
class protectedfinal
{
static abstract class AA
{
protected abstract Object a();
}
static class BB extends AA
{
@Override
protected Object a() { return this; }
}
public static void main (String[] args)
{
AA a = new BB();
System.out.println (a.a());
}
}
但我想使用最终成员,因为我认为访问最终成员比调用方法更快。是否有机会与最终成员一起实施?