在Java程序中,我有多个继承自父类的子类(它是抽象的).我想表达的是,每个孩子都应该有一个只设置一次的成员(我打算从构造函数中做到这一点).我的计划是编码s.th. 像这样:
public abstract class Parent {
protected final String birthmark;
}
public class Child extends Parent {
public Child(String s) {
this.birthmark = s;
}
}
Run Code Online (Sandbox Code Playgroud)
然而,这似乎不能取悦Java神.在父类中,我收到birthmark"可能尚未初始化" 的消息,在子类中我得到" birthmark无法访问最终字段".
那么Java的方式是什么呢?我错过了什么?
在尝试编写测试用例时会出现这个问题.Foo是框架库中的一个类,我没有源代码访问权限.
public class Foo{
public final Object getX(){
...
}
}
Run Code Online (Sandbox Code Playgroud)
我的申请会
public class Bar extends Foo{
public int process(){
Object value = getX();
...
}
}
Run Code Online (Sandbox Code Playgroud)
由于其他依赖性,我无法创建Foo对象,因此单元测试用例无法初始化.当值为null时,BarTest抛出空指针.
public class BarTest extends TestCase{
public testProcess(){
Bar bar = new Bar();
int result = bar.process();
...
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法可以使用反射api将getX()设置为非final?或者我该如何进行测试?
在Java中,我可以将本地"变量"声明为final,例如
void myMethod() {
final String foo = "Hello World!";
foo = "Bye-bye..."; // compile error!!
return;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试更改其值时,从编译器中获取错误.我想宣布一些我的本地"变量"最终,以避免意外改变它们的价值.
这在Objective-C中是否可行?
Java语言规范定义了第17.5节中最终字段的语义:
最终字段的使用模型很简单.在该对象的构造函数中设置对象的最终字段.在对象的构造函数完成之前,不要在另一个线程可以看到的位置写入对正在构造的对象的引用.如果遵循此原因,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本.它还将看到那些最终字段引用的任何对象或数组的版本,这些字段至少与最终字段一样是最新的.
我的问题是 - '最新'保证是否扩展到嵌套数组和嵌套对象的内容?
简而言之:如果一个线程将可变对象图分配给对象中的最终字段,并且对象图永远不会更新,那么所有线程都可以通过最终字段安全地读取该对象图吗?
示例场景:
在这种情况下,线程B看到的ArrayList的成员是否保证至少与MyClass的构造函数完成时一样最新?
我正在寻找澄清Java内存模型和语言规范的语义,而不是像同步这样的替代解决方案.我的梦想答案是肯定或否定,并参考相关文字.
更新:
我们何时应该使用未初始化的静态最终变量?我知道一个未初始化的静态最终变量只能在静态初始化程序块中赋值,但我想不出任何实际用途.
快速安心只是为了让您高枕无忧:
考虑以下因素
final String str = "This is the end";
Run Code Online (Sandbox Code Playgroud)
是str.length()在运行时评估还是在字节码中硬编码为15?
可能重复:
如何处理抛出已检查异常的静态最终字段初始值设定项
在这个例子中,我得到了错误的空白最后一个字段myClass的可能不被初始化:
private final static MyClass myClass; // <-- error
static {
try {
myClass = new MyClass(); // <-- throws exception
myClass.init();
} catch (Exception e) {
// log
}
}
Run Code Online (Sandbox Code Playgroud)
在那个例子中,我得到错误最终字段myClass可能已经被分配:
private final static MyClass myClass;
static {
try {
myClass = new MyClass(); // <-- throws exception
myClass.init();
} catch (Exception e) {
myClass = null; // <-- error
// log
}
}
Run Code Online (Sandbox Code Playgroud)
那个问题有什么解决方案吗?
在检查Java BigDecimal类的源代码时,我很惊讶它没有被声明为final class:
类BigDecimal
Run Code Online (Sandbox Code Playgroud)public class BigDecimal extends Number implements Comparable<BigDecimal>不可变的,任意精度的带符号十进制数.
(来自Oracle Docs)
是否有特定原因或开发人员忘记添加该关键字?不将不可变类声明为final是不错的做法?
同样的情况也适用BigInteger,但不是String宣布为最终的.
Java不允许在供应商中使用最终变量,因为它可能没有被初始化,而是在"(this)"之前.变量使它编译并运行正常.
此外,在分配变量之前调用此类供应商会导致NullPointerException而不是编译器错误,并在调用之后按预期运行.
这种行为是在某处描述的吗?
我正在使用OpenJDK 1.8.0_151.
例:
import java.util.function.Supplier;
class Example {
final String str;
Supplier<Integer> test1 = () -> str.length(); // DOES NOT COMPILE
Supplier<Integer> test2 = () -> this.str.length(); // DOES NOT COMPILE
Supplier<Integer> test3 = () -> (this.str).length(); // DOES NOT COMPILE
Supplier<Integer> test4 = () -> (this).str.length(); // OK
Example(String str) {
System.out.println(test4.get()); // NullPointerException
this.str = str;
System.out.println(test4.get()); // OK
}
}
---
javac Example.java
Example.java:7: error: variable str might not have been initialized
Supplier<Integer> test1 …Run Code Online (Sandbox Code Playgroud) 在C++ 11 关键字的各种 解释中final,我看到的是这样的例子.
class base
{
public:
virtual void f() final;
};
class derived : public base
{
public:
virtual void f(); // Illegal due to base::f() declared final.
};
Run Code Online (Sandbox Code Playgroud)
这实际上是一个有用的用途final吗?为什么要在基类中声明一个虚函数(意味着它在派生类中可以有效地重写)然后立即将其标记为final(否定该含义)?有什么用处virtual void f() final?
我可以看到标记derived::f()最终的价值而不是base::f().在这种情况下,base::f()可能有一个很好的基于设计的原因,为什么f()应该是虚拟的,并且derived::f()单独有一个很好的基于设计的原因,为什么没有进一步派生的类应该覆盖它的实现.
如果您不希望多态地覆盖该函数,为什么不放弃虚拟关键字?当然,派生类可能仍会以非多态方式覆盖该函数.virtual void f() final因此,基类中的目的base::f()是以任何方式牢固地不可重写 - 作为虚函数还是非虚函数?如果是这样,那么virtual在这种情况下我们必须添加关键字才能启用它似乎有点不幸final.我认为将非虚拟函数标记为final是合法的.
为什么使用virtual void f() final起源于基类的函数时感觉virtual和感觉final似乎相互矛盾?
final ×10
java ×8
c++ ×1
c++11 ×1
concurrency ×1
field ×1
immutability ×1
memory ×1
methods ×1
objective-c ×1
reflection ×1
string ×1
supplier ×1
variables ×1
virtual ×1