为什么人们如此强调要使一个班级中的每个变量"最终"?我不相信将final添加到私有局部变量有任何真正的好处,或者真的使用final来除常量之外的任何东西并将变量传递给匿名内部类.
我不打算开始任何形式的火焰战争,老实说,我想知道为什么这对某些人来说如此重要.我错过了什么吗?
从O'Reilly的Essential ActionScript 3.0(2007)第113页开始:
作为最终帮助的方法隐藏了类的内部细节.使类或方法最终阻止其他程序员扩展类或重写方法以检查类的内部结构.这种预防被认为是保护应用程序免遭恶意攻击的方法之一.
这是指编译的,封闭源包的API的用户,以及"恶意利用"来学习关于类设计的东西吗?这真的是个问题吗?
对于更多上下文,这是使用两个原因中的第二个final.在2007版中,它位于第113页的" 继承下字幕"下的" 防止类扩展和方法被覆盖"一章中.
在ActionScript中使用final属性有两个原因:
在某些情况下,最终方法比非最终方法执行得更快.如果您希望以各种可能的方式提高应用程序的性能,请尝试将其方法设为最终.但请注意,在将来的Flash运行时,Adobe期望非最终方法的执行速度与最终方法一样快.
作为最终帮助的方法隐藏了类的内部细节.使类或方法最终阻止其他程序员扩展类或重写方法以检查类的内部结构.这种预防被认为是保护应用程序免遭恶意攻击的方法之一.
根据Java内存模型,final在对象的构造函数中初始化的字段不受进一步修改,保证每个读取它的线程都能正确看到它的值,即使对象本身已经与数据竞争一起发布.
JLS讨论了17.5.3最终字段的后续修改,并含糊地说明了这一点
实现可以提供在最终字段安全上下文中执行代码块的方式.
它似乎并没有真正定义这些修改的语义,也不确定这个最终的字段安全上下文必须存在的位置或如何定义它(即,JLS似乎并未对最终字段的后续修改提供任何保证).
我必须说我没有完全理解部分命令dereferences()和mc(),也没有完全理解在对最终字段进行任何修改之后发生的冻结操作的行为(归因于它的初始值或后续修改).
在这种情况下,我想知道的是:(de)序列化框架(如Gson)如何保证包含在构造函数中正确初始化的最终字段的反序列化对象不会造成线程可见性问题?
例如,考虑这个类:
class X {
private final String s;
public X(final String s) { this.s = s; }
@Override public String toString() { return s; }
}
Run Code Online (Sandbox Code Playgroud)
以下代码:
final Gson gson = new Gson();
X x = gson.fromJson(gson.toJson(new X("abc")), X.class);
System.out.println(x);
// prints abc
Run Code Online (Sandbox Code Playgroud)
fromJson使用调试器进入该方法,我看到它sun.misc.Unsafe用于分配一个实例X而不调用它的构造函数,并且字段是setAccessible(true),最后它们被设置.
这只是在Sun的(或兼容的)JVM中!看起来Gson也有特定于多个Android版本的代码.
那么,这些反序列化的最终字段是否有任何线程安全保证,就像我对X构造的实例一样new X("abc") …
我有这段代码从文件加载属性:
class Config {
val properties: Properties = {
val p = new Properties()
p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
p
}
val forumId = properties.get("forum_id")
}
Run Code Online (Sandbox Code Playgroud)
这似乎工作正常.
我已经尝试将初始化移动properties到另一个val中loadedProperties,如下所示:
class Config {
val properties: Properties = loadedProps
val forumId = properties.get("forum_id")
private val loadedProps = {
val p = new Properties()
p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
p
}
Run Code Online (Sandbox Code Playgroud)
}
但它不起作用!(properties在null中properties.get("forum_id")).
那为什么会这样?loadedProps引用时不评估properties?
其次,这是初始化需要非平凡处理的变量的好方法吗?在Java中,我将声明它们的final字段,并在构造函数中执行与初始化相关的操作.
Scala中是否存在此方案的模式?
谢谢!
在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似乎相互矛盾?
请参考以下代码.当我运行代码时,我能够更改最终的非静态变量的值.但是,如果我尝试更改最终静态变量的值,那么它会抛出java.lang.IllegalAccessException.
我的问题是为什么它不会在非静态最终变量的情况下抛出异常,反之亦然.为什么不同?
import java.lang.reflect.Field;
import java.util.Random;
public class FinalReflection {
final static int stmark = computeRandom();
final int inmark = computeRandom();
public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
FinalReflection obj = new FinalReflection();
System.out.println(FinalReflection.stmark);
System.out.println(obj.inmark);
Field staticFinalField = FinalReflection.class.getDeclaredField("stmark");
Field instanceFinalField = FinalReflection.class.getDeclaredField("inmark");
staticFinalField.setAccessible(true);
instanceFinalField.setAccessible(true);
instanceFinalField.set(obj, 100);
System.out.println(obj.inmark);
staticFinalField.set(FinalReflection.class, 101);
System.out.println(FinalReflection.stmark);
}
private static int computeRandom() {
return new Random().nextInt(5);
}
}
Run Code Online (Sandbox Code Playgroud) 我遇到了下面的Java代码,它起初看起来不错但从不编译:
public class UnwelcomeGuest {
public static final long GUEST_USER_ID = -1;
private static final long USER_ID;
static {
try {
USER_ID = getUserIdFromEnvironment();
} catch (IdUnavailableException e) {
USER_ID = GUEST_USER_ID;
System.out.println("Logging in as guest");
}
}
private static long getUserIdFromEnvironment()
throws IdUnavailableException {
throw new IdUnavailableException(); // Simulate an error
}
public static void main(String[] args) {
System.out.println("User ID: " + USER_ID);
}
}//Class ends here
//User defined Exception
class IdUnavailableException extends Exception {
IdUnavailableException() { }
}//Class …Run Code Online (Sandbox Code Playgroud) 我的代码如下.它对我编译很好,但是我的教授说他得到了一个错误,因为我的班级中没有一些变量被宣布为final.Eclipse在我的机器上似乎没有问题所以我不知道如何修复我看不到的错误.
我理解一些变量需要最终才能在嵌套类中工作,但是我创建的变量似乎工作正常,最终与否.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Random;
public class JColorFrame extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JColorFrame frame = new JColorFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public JColorFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, …Run Code Online (Sandbox Code Playgroud) 通过创建私有构造函数,我们可以避免从外部的任何地方实例化类.通过使类最终,没有其他类可以扩展它.为什么Util类需要private构造函数和final类?
据我了解,变量评估是在运行时完成的。但是,类型评估是在Java中的编译时完成的。
同样,正如我所见,使变量恒定(我正在使用局部变量,但是上面的概念没有改变),将在编译时知道其值。
我提供了两个示例来测试这个概念。第一个起作用,第二个不起作用。
有人可以向我解释为什么将变量设为常量可以使我将短变量分配给int变量,而不能将int变量分配给long吗?
// Working example
final int x = 10;
short y = x;
// Non-working example
final long a = 10L;
int b = a;
Run Code Online (Sandbox Code Playgroud) final ×10
java ×7
static ×2
c++ ×1
c++11 ×1
coding-style ×1
constructor ×1
immutability ×1
jls ×1
oop ×1
private ×1
reflection ×1
scala ×1
variables ×1
virtual ×1