我知道这是一个相当简单的主题,但我真的想要围绕它。
这就是我想要做的,但它不喜欢最终修饰符。还有另一种方法可以达到我想要的效果吗?这基本上就是我想确保id在整个活动期间不能改变。
private final long mId;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mId = getIntent().getLongExtra(ID_KEY, -1);
}
我应该指出这是Android代码。谢谢你的帮助。我并不担心搞瘾者或搞砸者或任何改变我代码的人。我问的原因是将来证明我的代码将由下一个开发人员接管。我发现这篇文章也有助于解释一些问题。 Android - Activity Constructor vs onCreate
答案 0 :(得分:56)
您只能在构造函数或初始值设定项中设置final
变量。常规方法不能更改声明为final
的变量的值。
答案 1 :(得分:20)
你做不到。但是如果它是私有的,你可以保证没有外部对象改变它,你没有设置它。
或者,您可以将long值包装在另一个类中 - LazyImmutableLong
。但这是一个更冗长的方法,你可能不需要它(注意:下面的类不是线程安全的)
class LazyImmutableLong {
private Long value;
public void setValue(long value) {
if (this.value != null) {
return; // the value has already been set
}
this.value = value;
}
public long getValue() {return value;}
}
在你的活动中
private LazyImmutableLong id = new LazyImmutableLong();
public void onCreate(..) {
id.setValue(..);
}
答案 2 :(得分:4)
以下Worm
(一次写入多次读取)类可以在这种情况下提供帮助。
我们可以创建一个嵌套的Wrapper
类,它存储您需要的最终变量。要初始化此变量,您应该调用wrapper
对象的构造函数。当您调用方法getData()
时,您将获得最终变量的引用,以防它被初始化,否则,您将获得null
。
方法getData()
和setData(T data)
必须是线程安全的。为了提供它,我们对volatile
对象使用wrapper
修饰符。读取volatile变量是同步的,并且同步写入volatile变量也是如此。尽管已经做了一些努力使这个代码线程安全,但我没有在这方面进行测试。根据线程安全级别,您可以考虑使setter和getter同步。
public class Worm<T> {
private volatile Wrapper<T> wrapper;
public Worm() {}
public Worm(T data) throws IllegalAccessError
{
setData(data);
}
public T getData()
{
if (wrapper == null)
return null;
return wrapper.data;
}
public void setData(T data) throws IllegalAccessError
{
if (wrapper != null)
throw new IllegalAccessError();
else
wrapper = this.new Wrapper<>(data);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Worm<T> other = (Worm<T>) obj;
return Objects.equals(this.getData(), other.getData());
}
@Override
public int hashCode() {
return Objects.hashCode(this.getData());
}
final private class Wrapper<T> {
final private T data;
Wrapper(T data) {
this.data = data;
}
}
}
答案 3 :(得分:0)
private final long mId;
根据java规范, final
引用不能在运行时修改。因此,一旦你宣布它为final,mId在其生命周期内不能指向其他东西(除非你使用反射(或)包装对象中的值并通过其他引用修改它。)
答案 4 :(得分:0)
您可以稍后在构造函数中设置全局final变量。例如:
public class ClassA {
private final long mID;
public ClassA(final long mID) {
this.mID = mID;
}
}
在这种情况下,在每个构造函数中,您必须初始化最终变量。
答案 5 :(得分:0)
您必须在创建构造函数后立即对其进行初始化,或者您可以在构造函数中以最大值初始化构造函数。不迟于......
答案 6 :(得分:-1)
不,它无法完成
如果你可以在一个地方宣布决赛并在以后初始化,那么最终的意思是什么。
如果您想拥有一个常量ID,为什么不使用共享首选项,将其存储在SP中并随时检索。