问题
TheJava for C++ programmers tutorialsays(突出显示是我自己的):
关键字final大致相当于C中的const
在这种情况下,"粗略"是什么意思?它们是不是完全相同?
有什么区别,如果有的话?
#1 热门回答(180 赞)
在C标记成员函数const
中,可以在const
实例上调用它。 Java没有与之相当的东西。例如。:
class Foo {
public:
void bar();
void foo() const;
};
void test(const Foo& i) {
i.foo(); //fine
i.bar(); //error
}
可以在Java中稍后分配一次,例如:
public class Foo {
void bar() {
final int a;
a = 10;
}
}
在Java中是合法的,但不是C而是:
public class Foo {
void bar() {
final int a;
a = 10;
a = 11; // Not legal, even in Java: a has already been assigned a value.
}
}
在Java和C中,成员变量可以分别为final
/const
。这些需要在类的实例构建完成时给出一个值。
在Java中,必须在构造函数完成之前设置它们,这可以通过以下两种方式之一来实现:
public class Foo {
private final int a;
private final int b = 11;
public Foo() {
a = 10;
}
}
在C中,你将需要使用初始化列表来为const
成员提供一个值:
class Foo {
const int a;
public:
Foo() : a(10) {
// Assignment here with = would not be legal
}
};
在Java中,final可用于将事物标记为不可覆盖。 C(前C 11)不这样做。例如。:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
但在C:
class Bar {
public:
virtual void foo() const {
}
};
class Error: public Bar {
public:
// Fine in C++
virtual void foo() const {
}
};
这很好,因为标记成员functionconst
的语义不同。 (你也可以只通过其中一个成员函数来执行过载。(另请注意,C 11允许将成员函数标记为final,请参阅C 11更新部分)
C 11更新:
C 11实际上允许你将类和成员函数标记为final
,与Java中的相同特性具有相同的语义,例如在Java中:
public class Bar {
public final void foo() {
}
}
public class Error extends Bar {
// Error in java, can't override
public void foo() {
}
}
现在可以用C 11编写为:
class Bar {
public:
virtual void foo() final;
};
class Error : public Bar {
public:
virtual void foo() final;
};
我必须使用G 4.7的预发行版编译此示例。请注意,在这种情况下,这不会取代const
,而是对其进行扩充,从而提供类似Java的行为,而这种行为与最接近的等效C关键字无关。因此,如果你希望成员函数同时为final
和const
,你可以这样做:
class Bar {
public:
virtual void foo() const final;
};
(需要const
和final
的顺序)。
以前没有直接相当于const
个成员函数,尽管使函数非-virtual
可能是一个潜在的选项,尽管在编译时不会导致错误。
同样是Java:
public final class Bar {
}
public class Error extends Bar {
}
进入C 11:
class Bar final {
};
class Error : public Bar {
};
(以前806909066建筑师可能是你在C中最接近这一点的人)
有趣的是,为了以通常的方式保持与前C 11 codefinal
isn'ta关键字的向后兼容性。 (采取琐碎,合法的C 98示例struct final;
,看看为什么使它成为关键字会破坏代码)
#2 热门回答(28 赞)
在Java中,final关键字可用于四件事:
- 关于密封它的类或方法(不允许子类/覆盖)
- 在一个成员变量上声明它可以设置一次(我认为这就是你所说的)
- 在方法中声明的变量上,以确保它可以设置一次
- 在方法参数上,声明它不能在方法中修改
一个重要的事情是:Java最终成员变量必须be设置一次!例如,在构造函数,字段声明或初始化器中。 (但是你不能在方法中设置最终的成员变量)。
使成员变量最终的另一个结果与内存模型有关,如果你在线程环境中工作,这很重要。
#3 热门回答(25 赞)
Aconst
对象只能调用const
方法,通常被认为是不可变的。
const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)
Afinal
对象不能设置为新对象,但它不是不可变的 - 没有什么能阻止某人调用anyset
方法。
final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!
Java没有固有的方法来声明对象不可变;你需要将类设计为不可变的。
当变量是基本类型时,final
/const
工作相同。
const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages