匿名内部クラスを使用すると、多くの場合、最終的なキーワードを使用することができたときに、最終的なキーワードを言えば、おそらく多くの人々は、精通していません。また、Stringクラス内のJavaは、最終的なクラスですので、今日は、最終的なキーワードの使用を理解する必要があります。ここでは、このディレクトリの概要は次のとおりです。
キーワードの基本的な使い方.final
finalキーワードのII。の深い理解
そうでない場合は、正しい場所、理解の多く、私を修正してください。
オリジナルリンク:
http://www.cnblogs.com/dolphin0520/p/3736238.html
キーワードの基本的な使い方.final
Javaでは、最後のキーワードは、(メンバーおよびローカル変数を含む)、クラス、メソッド、変数を飾るために使用することができます。ここでは基本的な使い方finalキーワードのこれらの三つの側面を見てです。
1.変更されたクラス
このクラスは継承することができないことを示す、最終のクラスを変更する場合。それはあなたが彼を聞かせて決してクラスが継承される場合は、最終的に修正することが可能です。最後のクラスのメンバ変数は、必要に応じて、最終的な設定が、暗黙のうちに、最終的な方法として指定されている方法のすべてのメンバーが、最終的なクラスであることに注意してくださいすることができます。
変更され、最終的なクラスを使用する場合は、クラスは、安全上の理由から、または継承のために使用されることはありません将来的に実際にある場合を除き、慎重な選択に注意を払う、最終クラスのデザインを入力しないようにしてください。
2.変更方法
次の抜粋「Javaプログラミングのアイデア」、第4版、143ページ:
第二の理由は、Java実装の初期のバージョンでは効率である、方法が最終ターンになります。「ロック方法は、その意味を変更するために、任意の継承クラスを阻止することである最終的なアプローチ第一の理由を使用するための2つの理由があります。埋め込まれた呼び出し方法が大きすぎる。しかし、あなたは、Javaの最近のバージョンに組み込まれた通話をもたらした任意のパフォーマンスの向上が最終を最適化するために、これらのメソッドを使用する必要はありません表示されない場合があります。 "
唯一の明示的方法の前に、このメソッドを禁止したい場合はそのため、最終的としてカバーされ、サブクラスの場合に設定されています。
注意:プライベートクラスメソッドは暗黙のうちに、最終的な方法として指定。
3.変更された変数
修正変数は、最終的な場所でのほとんどのコンテンツですが、また、この記事の残りの部分は、焦点のこと。まず基本的な構文final変数を見て:
最終的な変数に対して、変数の基本データ型場合、その値は、初期化後に一度変更することができない;それは参照型の変数である場合、その初期化した後、別のオブジェクトへのポイントを許可しないであろう。
例えば:
上記のコード片は、変数の再割り当ては、IおよびOBJが与えられています。
finalキーワードのII。の深い理解
finalキーワードの基本的な使い方を学んだ後、このセクションでは、我々は、最終的なキーワード紛らわしい場所を見てください。
1.最後のクラス変数と共通の変数の違いは何ですか?
最終的なクラスのメンバ変数に適用した場合、メンバー変数は、(クラスメンバ変数、ローカル変数のみが使用前に初期化に割り当てられる必要があることに注意)コンストラクタに割り当て、最終的な変数の時に定義または初期化されなければなりません割り当てが初期化されると、それはアップ割り当てることができません。
だから、どのような違い、それは最終的に、最終的な変数や共通の変数を作るのですか?次の例を参照してください。
1
2
3
4
5
6
7
8
9
10
11
|
public
class
Test {
public
static
void
main(String[] args) {
String a =
"hello2"
;
final
String b =
"hello"
;
String d =
"hello"
;
String c = b +
2
;
String e = d +
2
;
System.out.println((a == c));
System.out.println((a == e));
}
}
|
あなたは最初にこの質問の出力を考えることができます。なぜ最初の比較が真であり、第2の比較はfasleです。最終的変数と我々は、コンパイル時にその正確な値を知ることができれば、最終的な変数は、基本データ型と文字列型である場合、通常の変数間の違いがあり、コンパイラは、コンパイル時定数として使用します。それは、最終的な変数の代わりに使用され、定数への直接アクセスの同等は、実行時に決定する必要はありません。このマクロ置換とC言語のビットのように。コンパイラ定数が非常に変数bを配置するために使用されているように、B直接その値を置き換えるように、このように変数bので、上記のコードの一部は、最終的な変形です。変数dのためとして、あなたは、実行時にリンクを介してアクセスする必要があります。確かに、我々はそれらの違いを理解しておく必要がありますが、変数の最終値の正確事例を知ることができる唯一のコンパイル時に注意を払うように、コンパイラは、以下のコードが最適化されないので、この最適化を実行します。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
class
Test {
public
static
void
main(String[] args) {
String a =
"hello2"
;
final
String b = getHello();
String c = b +
2
;
System.out.println((a == c));
}
public
static
String getHello() {
return
"hello"
;
}
}
|
falseにこのコードの出力。
2.最終的な変更されたオブジェクト参照変数は、変数、それの内容を指しますか?
上記では、可変オブジェクト変数の内容の、基準点、一度他のオブジェクトへもはやポイントができ、最終的な修正された参照変数の初期割り当てがありますか?次の例を見てください:
1
2
3
4
5
6
7
8
9
10
11
|
public
class
Test {
public
static
void
main(String[] args) {
final
MyClass myClass =
new
MyClass();
System.out.println(++myClass.i);
}
}
class
MyClass {
public
int
i =
0
;
}
|
このコードが正常に出力結果と結果を出力してコンパイルすることができます。これは、他のオブジェクトを指すことはできないが修正された参照変数の後、最終であることを示しているが、それはオブジェクトを指すコンテンツは可変です。
3.finalと静的
很多时候会容易把static和final关键字混淆,static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。看下面这个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public
class
Test {
public
static
void
main(String[] args) {
MyClass myClass1 =
new
MyClass();
MyClass myClass2 =
new
MyClass();
System.out.println(myClass1.i);
System.out.println(myClass1.j);
System.out.println(myClass2.i);
System.out.println(myClass2.j);
}
}
class
MyClass {
public
final
double
i = Math.random();
public
static
double
j = Math.random();
}
|
运行这段代码就会发现,每次打印的两个j值都是一样的,而i的值却是不同的。从这里就可以知道final和static变量的区别了。
4.匿名内部类中使用的外部局部变量为什么只能是final变量?
这个问题请参见上一篇博文中《Java内部类详解》中的解释,在此处不再赘述。
5.关于final参数的问题
关于网上流传的”当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法外的变量“这句话,我个人理解这样说是不恰当的。
因为无论参数是基本数据类型的变量还是引用类型的变量,使用final声明都不会达到上面所说的效果。
看这个例子就清楚了:
上面这段代码好像让人觉得用final修饰之后,就不能在方法中更改变量i的值了。殊不知,方法changeValue和main方法中的变量i根本就不是一个变量,因为java参数传递采用的是值传递,对于基本类型的变量,相当于直接将变量进行了拷贝。所以即使没有final修饰的情况下,在方法内部改变了变量i的值也不会影响方法外的i。
再看下面这段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
class
Test {
public
static
void
main(String[] args) {
MyClass myClass =
new
MyClass();
StringBuffer buffer =
new
StringBuffer(
"hello"
);
myClass.changeValue(buffer);
System.out.println(buffer.toString());
}
}
class
MyClass {
void
changeValue(
final
StringBuffer buffer) {
buffer.append(
"world"
);
}
}
|
运行这段代码就会发现输出结果为 helloworld。很显然,用final进行修饰并没有阻止在changeValue中改变buffer指向的对象的内容。有人说假如把final去掉了,万一在changeValue中让buffer指向了其他对象怎么办。有这种想法的朋友可以自己动手写代码试一下这样的结果是什么,如果把final去掉了,然后在changeValue中让buffer指向了其他对象,也不会影响到main方法中的buffer,原因在于java采用的是值传递,对于引用变量,传递的是引用的值,也就是说让实参和形参同时指向了同一个对象,因此让形参重新指向另一个对象对实参并没有任何影响。
所以关于网上流传的final参数的说法,我个人不是很赞同。
参考资料:
《Java编程思想》