Java for C++ programmers tutorial说(突出显示是我自己的):
关键字final是粗略 相当于C ++中的const
在这种情况下,“粗略”是什么意思?他们完全不一样吗?
有什么区别,如果有的话?
答案 0 :(得分:182)
在C ++中标记成员函数const
意味着可以在const
个实例上调用它。 Java没有与之相当的东西。 E.g:
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 ++(pre-C ++ 11)不会这样做。 E.g:
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 {
}
};
这很好,因为标记成员函数const
的语义是不同的。 (您也可以通过在其中一个成员函数上使用const
来重载。(另请注意,C ++ 11允许将成员函数标记为final,请参阅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 {
};
(以前private
构造函数可能是你在C ++中最接近的那个)
有趣的是,为了保持与C ++之前的代码兼容11代码final
不是通常的关键字。 (以简单,合法的C ++ 98示例struct final;
为例,了解为什么将其作为关键字会破坏代码)
答案 1 :(得分:29)
在Java中,final关键字可用于四件事:
一件重要的事情是: Java最终成员变量必须才能设置一次!例如,在构造函数,字段声明或初始化器中。 (但是你不能在方法中设置最终的成员变量。)
使成员变量final的另一个结果与内存模型有关,如果您在线程环境中工作,这很重要。
答案 2 :(得分:25)
const
对象只能调用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)
final
对象不能设置为新对象,但它不是不可变的 - 没有什么能阻止某人调用任何set
方法。
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
答案 3 :(得分:12)
Java final相当于原始值类型的C ++ const。
对于Java引用类型,final关键字等效于const指针...即
//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();
//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();
答案 4 :(得分:8)
你已经有了一些很好的答案,但有一点似乎值得补充:C ++中的const
通常用于防止程序的其他部分改变对象的状态。正如已经指出的那样,java中的final
不能这样做(基元除外) - 它只是阻止引用被更改为不同的对象。但是,如果您使用的是Collection
,则可以使用静态方法
Collection.unmodifiableCollection( myCollection )
这将返回一个Collection
引用,该引用提供对元素的读访问权,但如果尝试修改则抛出异常,使其有点像C ++中的const
答案 5 :(得分:7)
Java的final
仅适用于原始类型和引用,而不适用于const关键字适用于任何事物的对象实例本身。
将const list<int> melist;
与final List<Integer> melist;
进行比较,第一个使得无法修改列表,而后者只会阻止您将新列表分配给melist
。
答案 6 :(得分:3)
除了具有某些subtle multi-threading properties之外,声明 final
的变量不需要在声明时初始化!
即。这在Java中有效:
// declare the variable
final int foo;
{
// do something...
// and then initialize the variable
foo = ...;
}
如果使用C ++的 const
编写,则无效。
答案 7 :(得分:2)
根据wikipedia:
答案 8 :(得分:2)
我猜它说“粗略”,因为当你谈论指针时,C ++中const
的含义变得复杂,即常量指针与指向常量对象的指针。由于Java中没有“显式”指针,final
没有这些问题。
答案 9 :(得分:0)
让我用switch / case语句的例子来解释我的理解。
每个case语句中的值必须是与switch值相同的数据类型的编译时常量值。
声明类似下面的内容(在您的方法中作为本地实例,或在您的类中作为静态变量(然后向其添加静态)或实例变量。
final String color1 = "Red";
和
static final String color2 = "Green";
switch (myColor) { // myColor is of data type String
case color1:
//do something here with Red
break;
case color2:
//do something with Green
break;
}
如果color1
是类/实例变量而不是局部变量,则此代码将无法编译。
如果将color1
定义为静态final(然后它变为静态最终变量),这将编译。
如果不编译,您将收到以下错误
error: constant string expression required
答案 10 :(得分:-5)
关键字“const”表示您的变量保存在ROM(带微处理器)中。在计算机中,您的变量保存在RAM区域中,用于汇编代码(只读RAM)。这意味着您的变量不在可写RAM中,包括:静态内存,堆栈内存和堆内存。
关键字“final”表示您的变量保存在可写RAM中,但您注意到编译器您的变量只更改了一次。
//in java language you can use:
static final int i =10;
i =11; //error is showed here by compiler
//the same in C++ the same as follows
int i =10;
const int &iFinal = i;
iFinal = 11; //error is showed here by compiler the same as above
我认为,“const”在性能方面表现不佳,因此Java不会使用它。