(一)final用于修饰类中的属性
final的基础知识:
java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量
带有恒定初始值的final static基本类型全用大写字母命名,并且字与字之间用下划线隔开。
1.final类不能被继承,没有子类,final类中的方法默认是final的。
2.final方法不能被子类的方法覆盖,但可以被继承。
3.final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
4.final不能用于修饰构造方法。
思考问题:
1.被final修饰的所有属性真的是在编译时就可以知道它的值么?
2.被final static修饰和被final修饰有什么区别?
3.空final有什么用处呢?
4.用final修饰引用类型和基本数据类型又有什么不同点?
先看下面的代码,猜猜i4和int_5的值会不会改变?如果把其中注释掉的代码给解除注释代码还能不能正常运行?
class value{
int i;
public value(int i){
this.i = i;
}
}
public class demo6 {
private final int j;
private final value value;
private static random rand = new random(47);
private string id;
public demo6(){
value = new value(1);
j = 1;
}
public demo6(string id){
this.id = id;
value = new value(0);
j = 0;
}
public demo6(int j){
this.j = j;
value = new value(j);
}
private final int valueone = 9;
private static final int value_tow = 99;
public static final int value_three = 39;
private final int i4= rand.nextint(20);
static final int int_5 = rand.nextint(20);
private value v1 = new value(11);
private final value v2 = new value(22);
private static final value val_3 = new value(33);
private final int[] a = {1,2,3,4,5,6};
public string tostring(){
return id ":" "i4 = " i4 ", int_5 = " int_5;
}
public static void main(string[] args) {
demo6 fd1 = new demo6("fd1");
// fd1.valueone ;
fd1.v2.i ;
fd1.v1 = new value(9);
for(int i=0;i
输出结果:
fd1:i4 = 15, int_5 = 18
creating new demo6
fd1:i4 = 15, int_5 = 18
fd2:i4 = 13, int_5 = 18
总结:
1.当我们使用final常量时并不能单纯的认为在编译时就可以知道他的值,在运行时通过随机生成的数值来初始化i4和int_5就可以得出这个结论
2.只用final修饰的常量在当前对象的值是唯一的,但是当我们在创建一个对象时final的值是可以初始化不同的值的.
3.被final修饰的引用,只是说明引用的指向不能被改变,但是其对象本身是可以被改变的,通过上面代码的int类型的数组的值被改变就可以发现
4.空白final是指被声明为final但又未给定初值的域,无论什么属性,编译器都要确保空白final在被使用前被初始化,不信可以试试把构造器中对空白final初始化的代码注释掉试试
5.在构造器中对空白final进行初始化,可以让不同的对象有不同的final值,并且保持final恒定不变的特性,这就是为什么说final的值并不是固定的原因了。
6.static final用来修饰成员变量和成员方法,可简单理解为“全局常量”。对于变量,表示一旦给值就不可修改,并且通过类名可以访问。对于方法,表示不可覆盖,并且可以通过类名直接访问。
(二)final用于修饰类中的方法
思考一下能不能继承父类的private方法或者final方法?
当你重写父类的private方法时,真的是重写么?
class withfinals{
private final int i = 19;
public int geti(){
return i;
}
private final void f(){
system.out.println("withfinals.f()");
}
private void g(){
system.out.println("withfinals.g()");
}
}
class overridingprivate extends withfinals{
// @override
private void f(){
system.out.println("overridingprivate.f()");
}
private void g(){
system.out.println("overridingprivate.g()");
}
}
class overridingprivate2 extends overridingprivate{
// @override
public final void f(){
system.out.println("overridingprivate2.f()");
}
public void g(){
system.out.println("overridingprivate2.g()");
}
}
public class demo7 {
public static void main(string[] args) {
overridingprivate2 op2 = new overridingprivate2();
op2.f();
op2.g();
system.out.println(op2.geti());
overridingprivate op = op2;
// op.f();
// op.g();
withfinals wf = op2;
// wf.f();
// wf.g();
}
}
输出结果:
overridingprivate2.f()
overridingprivate2.g()
19
其实子类确实继承了父类的私有方法和属性,不然又怎么调用父类的方法去操纵父类的私有属性呢。
代码如下:
import java.lang.reflect.accessibleobject;
import java.lang.reflect.method;
class father {
private string name = "father";
public father(){
}
private void printf(){
system.out.println("father方法");
}
}
class test extends father{
}
public class demo8 extends father{
public static void main(string[] args) throws exception{
class c = test.class;
test test = new test();
class f = c.getsuperclass();
method[] declaredmethods = f.getdeclaredmethods();
accessibleobject.setaccessible(declaredmethods,true);
for(method m :declaredmethods){
system.out.println("子类调用父类的" m.getname() "方法");
m.invoke(test);
}
}
}
输出结果:
子类调用父类的printf方法
father方法
通过反射可以看到子类确实继承了父类的private方法,只是因为访问权限的问题不能对私有的方法进行访问,当你用private和final同时修饰类中的方法时,你会发现编译器发出警告(private被声明为final)这也就间接的说明了其实private方法是被隐式的指定为final的,只是因为无法取用private方法所以没办法覆盖它,当然你也可以加上final修饰符,但是这个修饰符其实没有发挥任何意义。
方法可以声明为 final 方法,以防止子类覆盖或隐藏它。尝试重写或隐藏最终方法是编译时错误。
私有方法和在最终类中立即声明的所有方法的行为就像它们是最终方法一样,因为不可能重写它们,但是final方法可以在子类中用super调用,而private方法不可以在子类中调用。
(三)final参数
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。
public class test4 {
public static void main(string[] args) {
new test4().f1(2);
}
public void f1(final int i) {
//i ; //i是final类型的,值不允许改变的.
system.out.print(i);
}
}